Skip to content

Repository files navigation

VMProtect License Manager

Next.js TypeScript Supabase License

A modern, self-hosted license management system for VMProtect-protected software. Designed to automate license generation for software developers while outsourcing the license key generation and HWID collection tasks to sellers/resellers.

🎯 Why This Project?

As a software developer using VMProtect for copy protection, you face a challenge: generating license keys requires your private RSA key and understanding of VMProtect's binary format. This creates bottlenecks:

  • Manual process: You must personally generate each key when a customer purchases
  • HWID collection: Customers need to submit their Hardware ID, which you must relay
  • Seller coordination: If you have resellers, they depend on you for every license

This project solves these problems by providing a web-based platform where:

  1. You (admin) import your VMProtect product keys once
  2. Sellers can independently generate licenses using credits you allocate
  3. Customers provide their HWID directly to sellers
  4. Everything is tracked with full audit trail and approval workflows

✨ Features

  • 🔐 VMProtect Compatible - Generate license keys using VMProtect's RSA encryption format (offline verification)
  • 👥 Multi-tenant - Admin and seller roles with credit-based quotas
  • 📦 Multi-product - Support multiple products with individual RSA key pairs
  • 🔄 Renewals & Refunds - Built-in approval workflow for license management
  • 📊 Full Audit Trail - Track all license generations, credit transactions, and requests
  • ⏱️ Flexible Duration - 7-day (0.3 credits) to 6-month license options
  • 🔑 HWID Management - Monthly free change + paid instant change option
  • 📋 Sortable Tables - Click columns to sort by customer, date, credits
  • 🌐 Bilingual - Full English and Chinese language support (日/月 labels)
  • 📱 Mobile Optimized - Responsive design for all screen sizes
  • 🚀 Easy Deploy - One-click deploy to Vercel

🖼️ Screenshots

Admin Main View

Click to view more screenshots

Admin Panel

Main Dashboard User Management Product Management
Admin Main View Admin Users Admin Add Parse Product XML
Credit Management License Import Request Approvals
Admin Credit Admin Import License Admin Approvals
Product Assignment All Requests License Overview
Admin Product Assign Admin Requests Admin Requests

Seller Panel

Seller Dashboard Batch Generation Batch Generation Window
Seller Requests Seller Batch Generation Seller Batch Generation Window
Credit History Credit History (License Ref) Approvals
Seller Credit History Seller Credit History License Ref Seller Approvals

Features

License Renewal HWID Request Refund Request
Renew License Request HWID Request Refund

🚀 Quick Start

Prerequisites

  • Node.js 18+
  • Supabase account (free tier works)

1. Clone & Install

git clone https://github.com/thetobysiu/vmprotect-license-manager.git
cd vmprotect-license-manager
npm install

2. Database Setup

  1. Create a new project at supabase.com
  2. Go to SQL EditorNew Query
  3. Copy and run the entire contents of supabase/schema.sql
  4. Go to SettingsAPI and copy your credentials

3. Environment Variables

Create .env.local:

NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key

4. Run

npm run dev

Open http://localhost:3000

Default login: admin / admin (change password immediately!)

☁️ Deployment

Vercel (Recommended)

Deploy with Vercel

Or manually:

npm i -g vercel
vercel --prod

Other Platforms

Any platform supporting Next.js works:

npm run build
npm start

📖 User Guide

Admin Features

Feature Description
User Management Create/delete seller accounts, manage assigned products
Credit Management Add/deduct credits (supports decimals like 0.3), view transaction history
Product Management Import VMProtect XML, assign products to sellers
License Overview Sortable columns, filters, search by customer/HWID, export CSV, bulk delete
Import Licenses Import existing licenses via XML or text
Request Approval Approve/reject refund and HWID change requests with optional credit charge
HWID Settings Configure HWID change cost percentage (default 30%)

Seller Features

Feature Description
Generate Licenses Bulk generate via CSV or single quick-add (7 days to 6 months)
My Licenses Sortable table with customer, HWID, created, expiry, credits columns
Renewals Extend license expiry (7 days = 0.3 credits, 1-6 months)
Refund Requests Submit refund requests to admin
HWID Changes One free change per month, or pay 30% credits for instant change

Credit System

Duration Credits Notes
7 days 0.3 Short-term trial
1 month 1.0 Standard
2 months 2.0 ...
6 months 6.0 Maximum

HWID Change Options

Option Cost Approval
Monthly free 0 Auto-approved (once per month per license)
Paid instant 30% of license credits Auto-approved
Request approval Admin decides Admin can charge 0 or custom amount

License Key Tracking

When a HWID change is requested, the system now stores:

  • Original HWID - The previous hardware ID
  • Original License Key - The old serial number (for blocklist use)
  • New HWID - The updated hardware ID
  • New License Key - Generated after approval

This allows you to maintain a blocklist of compromised or revoked keys while keeping full audit history.

🔧 VMProtect Integration

How VMProtect Licensing Works

VMProtect uses asymmetric RSA cryptography for license key generation and verification:

┌─────────────────────────────────────────────────────────────────────────┐
│                        KEY GENERATION (Server-side)                      │
├─────────────────────────────────────────────────────────────────────────┤
│  License Data (Name, HWID, Expiry, ProductCode)                         │
│         ↓                                                                │
│  PKCS#1 v1.5 Padding                                                    │
│         ↓                                                                │
│  RSA Encrypt with PRIVATE KEY  ←── Only you have this!                  │
│         ↓                                                                │
│  Base64 Encoded License Key (serial number)                             │
└─────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────┐
│                      KEY VERIFICATION (Client-side)                      │
├─────────────────────────────────────────────────────────────────────────┤
│  Base64 License Key                                                      │
│         ↓                                                                │
│  RSA Decrypt with PUBLIC KEY  ←── Embedded in your protected .exe       │
│         ↓                                                                │
│  Verify: HWID matches, Expiry valid, ProductCode correct, CRC valid     │
│         ↓                                                                │
│  ✅ License Valid (or ❌ Invalid)                                        │
└─────────────────────────────────────────────────────────────────────────┘

Key Concepts

Term Description
Private Key Secret key used to sign/generate licenses. Never share this! Stored securely in your database.
Public Key Embedded in your protected executable. Used to verify licenses. Safe to distribute.
Modulus (N) Shared component of both keys. Part of the RSA key pair.
HWID Hardware ID - unique identifier of customer's machine. Prevents license sharing.
Offline Verification License is verified locally without internet. The public key in your .exe can validate any license signed by your private key.

Why Offline Verification Matters

Unlike online license servers, VMProtect licenses are cryptographically self-contained:

  • No server dependency - Your software works even if your server is down
  • No latency - Instant verification, no network round-trips
  • Privacy - No "phone home" required
  • Tamper-proof - Mathematical guarantee via RSA (impossible to forge without private key)

The trade-off is that revocation requires issuing new software builds with updated keys or using the HWID change workflow.

Importing Product Keys

  1. In VMProtect: ProjectOptionsLicense ManagerExport
  2. In this app: Products tab → Parse XML → Paste and Add

The exported XML contains Modulus, Private, ProductCode, and Bits which are used for RSA key generation.

Importing Existing Licenses

Two methods supported:

  • XML Format: Paste VMProtect license export XML
  • Text Format: Paste serial keys (one per line)

License Key Format

Generated keys work with VMProtect's VMProtectSetSerialNumber() function and contain:

Block Description
Version Serial format version (always 1)
Customer Name Optional identifier (max ~60 chars for 1024-bit keys)
HWID Base64-encoded hardware fingerprint
Expiry Date License expiration (day/month/year)
Product Code 8-byte product identifier
Checksum SHA-1 based CRC for integrity

The entire payload is RSA-encrypted with PKCS#1 v1.5 padding and Base64-encoded for the final serial number.

🗄️ Database Schema

Table Purpose
users Admin/seller accounts with credit balance (NUMERIC for decimals)
products RSA keys, product codes
seller_products Product-seller assignments
licenses All generated licenses (duration_months, credits_used as NUMERIC)
credit_transactions Credit history with license links
approval_requests Refund/HWID change workflow (stores original HWID and license key)
settings Global app settings

🔒 Security

Current Security Measures

Layer Protection
Database Row Level Security (RLS) enabled, service_role only access, anon/public revoked
API All routes require authentication, role-based authorization
Session HTTP-only cookies, secure flag in production, 7-day expiry
RSA Keys Private keys only accessible to admin via server-side API
Product Access Sellers can only generate licenses for assigned products
Credit System Atomic server-side balance updates prevent race conditions

Production Recommendations

Before deploying to production, consider these enhancements:

Priority Recommendation Status
🔴 High Upgrade from SHA-256 to bcrypt for password hashing TODO
🔴 High Change default admin password immediately after setup Manual
🟡 Medium Add rate limiting to login endpoint (prevent brute force) TODO
🟡 Medium Sign session cookies with HMAC to prevent tampering TODO
🟢 Low Add CSRF tokens for form submissions Optional
🟢 Low Implement account lockout after failed attempts Optional

Environment Variables

Variable Required Description
NEXT_PUBLIC_SUPABASE_URL Yes Your Supabase project URL
SUPABASE_SERVICE_ROLE_KEY Yes Service role key (⚠️ keep secret!)

⚠️ Never expose SUPABASE_SERVICE_ROLE_KEY in client-side code. It bypasses RLS.

🛠️ Tech Stack

Category Technology
Framework Next.js 14 (App Router)
Database Supabase (PostgreSQL)
Styling Tailwind CSS
Language TypeScript
Icons Lucide React
Dates date-fns
CSV PapaParse

📄 API Endpoints

Click to expand API reference
Endpoint Method Access Description
/api/auth/login POST Public Login
/api/auth/logout POST All Logout
/api/auth/session GET All Get current session
/api/licenses GET All List licenses
/api/licenses DELETE Admin Bulk delete
/api/licenses/import POST Admin Import licenses
/api/licenses/renew POST All Renew license
/api/licenses/reparse POST Admin Reparse all keys
/api/generate-licenses POST All Generate new licenses
/api/products GET/POST/DELETE Admin Manage products
/api/seller-products GET/POST/DELETE Admin Product assignments
/api/users GET/POST/PATCH/DELETE Admin Manage users
/api/transactions GET/POST/DELETE Varies Credit transactions
/api/requests GET/POST/PATCH/DELETE Varies Approval requests
/api/settings GET/PATCH All/Admin App settings

🗺️ Roadmap

Phase 1: Redeem Code System (Planned)

A system for pre-generated redeemable codes that customers can activate with their HWID:

Feature Overview

┌─────────────────────────────────────────────────────────────────────────┐
│                         CURRENT WORKFLOW                                 │
├─────────────────────────────────────────────────────────────────────────┤
│  Customer → Seller → "What's your HWID?" → Customer sends HWID          │
│                    → Seller generates license → Sends to customer       │
└─────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────┐
│                         WITH REDEEM CODES                                │
├─────────────────────────────────────────────────────────────────────────┤
│  Seller pre-generates codes → Customer buys code                        │
│  Customer visits redeem page → Enters code + HWID → Gets license key    │
│  (Self-service, no seller interaction needed!)                          │
└─────────────────────────────────────────────────────────────────────────┘

Database Changes

-- New table: redeem_codes
CREATE TABLE redeem_codes (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    code TEXT UNIQUE NOT NULL,              -- e.g., "XXXX-XXXX-XXXX-XXXX"
    product_id UUID NOT NULL REFERENCES products(id),
    seller_id UUID NOT NULL REFERENCES users(id),
    duration_months INTEGER DEFAULT 1,
    is_redeemed BOOLEAN DEFAULT FALSE,
    redeemed_at TIMESTAMPTZ,
    redeemed_license_id UUID REFERENCES licenses(id),
    created_at TIMESTAMPTZ DEFAULT NOW(),
    expires_at TIMESTAMPTZ                  -- Optional: code expiry
);

CREATE INDEX idx_redeem_codes_code ON redeem_codes(code);
CREATE INDEX idx_redeem_codes_seller ON redeem_codes(seller_id);

API Endpoints

Endpoint Method Access Description
/api/redeem-codes GET Seller/Admin List redeem codes
/api/redeem-codes POST Seller/Admin Generate new codes
/api/redeem-codes/redeem POST Public Redeem code with HWID
/api/redeem-codes DELETE Seller/Admin Delete unused codes

UI Components

  1. Admin/Seller Dashboard

    • New "Redeem Codes" tab
    • Bulk generate codes (quantity, product, duration)
    • View/export unredeemed codes
    • Track redeemed codes with license links
  2. Public Redeem Page (/redeem)

    • Simple form: Code input + HWID input
    • No login required
    • Returns license key on success
    • Instructions for getting HWID from your software

Implementation Steps

  1. Database: Add redeem_codes table to schema
  2. Types: Add RedeemCode interface to types.ts
  3. API Routes:
    • POST /api/redeem-codes - Generate codes (deduct seller credits)
    • GET /api/redeem-codes - List codes with filters
    • POST /api/redeem-codes/redeem - Public redeem endpoint
  4. Frontend:
    • Add RedeemCodesTab component to dashboard
    • Create /redeem public page
  5. Integration: Link redeemed codes to generated licenses

Phase 2: License Blocking/Revocation (Planned)

Extend the system to support license blocking for abuse cases:

Feature Overview

  • Add is_blocked and block_reason fields to licenses table
  • Admin can block any license, seller can request blocks
  • Blocked licenses appear in software (requires software update to check)
  • Option: Publish block list API for software to query

Database Changes

ALTER TABLE licenses ADD COLUMN is_blocked BOOLEAN DEFAULT FALSE;
ALTER TABLE licenses ADD COLUMN block_reason TEXT;
ALTER TABLE licenses ADD COLUMN blocked_at TIMESTAMPTZ;
ALTER TABLE licenses ADD COLUMN blocked_by UUID REFERENCES users(id);

Integration with Software

Since VMProtect uses offline verification, blocking requires one of:

  1. Online check: Software queries /api/licenses/check?hwid=XXX on startup
  2. Block list file: Periodically download signed block list
  3. Key rotation: Issue new product keys, invalidating old licenses

Phase 3: Customer Self-Service Portal (Future)

  • Customer accounts with email verification
  • View purchased licenses
  • Request HWID changes directly
  • Download latest software versions

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📜 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • VMProtect for their software protection solution
  • Supabase for the amazing backend-as-a-service
  • Vercel for seamless deployments

About

A full-stack modern license management solution for VMProtect using Next.js 14 and Supabase. Supports secure RSA key generation, admin/reseller roles, and credit-based quota management.

Topics

Resources

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages