A Rust-based license management system providing comprehensive license generation, verification, and management capabilities. The system supports hardware binding, container binding, and application binding strategies, suitable for physical machines, containers, and development environments.
Features
- Flexible Hardware Binding: Support for multiple hardware identifier combinations with configurable strict or loose binding modes
- Container Environment Support: Specialized identification strategies for containerized applications
- Development Mode: Minimal binding for development and testing environments
- C Interface Support: Auto-generated C header files for multi-language integration
- Command-line Tools:
rlgenandrlinspectutilities for license generation and verification - Secure Signing: Ed25519 signature algorithm for license security
- Time Guard: Anti-tampering mechanism to detect system time rollback
- Cross-platform: Support for Windows and Linux
Host-tag System
The Host-tag system is the core concept of RLicen, defining hardware and system identifiers for license binding through bit flags.
Tag Definitions
| Tag | Bit Value | Description | Stability |
|---|---|---|---|
RL_TAG_CPU |
1 << 0 | CPU identifier | Medium |
RL_TAG_MOTHERBOARD |
1 << 1 | Motherboard serial/UUID | High |
RL_TAG_DISK |
1 << 2 | Disk serial number | Medium |
RL_TAG_MAC |
1 << 3 | Network MAC address | Medium |
RL_TAG_MACHINE_ID |
1 << 4 | System machine ID | High |
RL_TAG_CONTAINER_ID |
1 << 5 | Container ID | Medium |
RL_TAG_OVERLAY_ID |
1 << 6 | Container overlay ID | High |
RL_TAG_APP_UUID |
1 << 8 | Application-generated UUID | Low (app-controlled) |
Predefined Combinations
Physical Machine - Strict Mode
RL_TAG_CPU | RL_TAG_MOTHERBOARD | RL_TAG_DISK | RL_TAG_MAC | RL_TAG_MACHINE_ID
- Binds multiple hardware identifiers
- High security, difficult to forge
Physical Machine - Loose Mode
- Only binds CPU and MAC addresses
Container - Strict Mode
RL_TAG_OVERLAY_ID | RL_TAG_CONTAINER_ID | RL_TAG_APP_UUID
- Strong binding to container instance
- Requires re-issuing license on container rebuild/migration
Container - Loose Mode
RL_TAG_MACHINE_ID | RL_TAG_OVERLAY_ID
- Allows container migration on same host
- Binds host machine ID and container overlay
Development Mode
- Only binds application-generated UUID
- Maximum flexibility for development and testing
- Not suitable for production
Installation
Build from Source
# Clone the repository git clone https://github.com/yourusername/rlicen.git cd rlicen # Build the library and tools cargo build --release # The following will be generated: # - target/release/rlicen.dll / librlicen.so (library) # - target/release/rlgen.exe / rlgen (license generator) # - target/release/rlinspect.exe / rlinspect (license inspector)
C API
The C header file is automatically generated during build:
capi/include/rlicen.h- Auto-generated C header file
Usage
Command-line Tools
1. Generate Key Pairs
# Generate keys in default directory (keys/) rlgen keys # Generate keys in custom directory rlgen keys -o /path/to/keys
Output files:
private-{key_id}.pem- Private key for license signingpublic-{key_id}.pem- Public key for license verification
2. Generate Example Configuration
# Generate default config file rlgen example # Generate config file at custom path rlgen example -o my_config.toml
Example configuration:
product_name = "MyProduct" product_version = "1.0.0" host_uid = "[{\"tag\":1,\"name\":\"CPU\",\"uid\":\"SGVsbG8td29ybGQ\"},{\"tag\":8,\"name\":\"MAC\",\"uid\":\"YWJjZGVmZ2hpams\"}]" valid_from = "2024-01-01" valid_to = "2024-12-31" private_key = "keys/private_key.pem" [extra_data] feature1 = "enable" max_users = "100"
3. Generate License
# Generate license from config rlgen sign -c license_config.toml # Override expiration date and output file rlgen sign -c license_config.toml -e "2025-12-31" -o custom_license.xlic
4. Verify License
# Verify license rlinspect verify -f license.xlic -k keys/public_key.pem # Inspect license details rlinspect info -f license.xlic # Get host identifier rlinspect host -t PHYSICAL_STRICT
C API Usage
#include "rlicen.h" #include <stdio.h> int main() { // Set log file rl_set_log_file("app.log", RLicenLogLevel_INFO); // Get version information size_t version_size = 0; rl_get_version(NULL, &version_size); char* version = malloc(version_size); rl_get_version(version, &version_size); printf("RLicen version: %s\n", version); free(version); // Get current machine identifier uint32_t tag = RL_TAG_PHYSICAL_STRICT; size_t id_size = 0; rl_identify_pc(tag, NULL, &id_size, NULL, NULL); char* identifier = malloc(id_size); rl_identify_pc(tag, (uint8_t*)identifier, &id_size, NULL, NULL); printf("Host UID: %s\n", identifier); free(identifier); // Verify license RLicenVerificationResult result; enum RLicenCApiError error = rl_acquire_license( "license.xlic", "keys/public_key.pem", &result ); if (error == RLicenCApiError_Ok && result.valid) { printf("License valid!\n"); printf("Product: %s\n", result.product_name); printf("Version: %s\n", result.product_version); } else { printf("License invalid: %s\n", result.reason); } return 0; }
Rust API Usage
Add to your Cargo.toml:
[dependencies] rlicen = { path = "./rlicen" }
Example:
use rlicen::{RLicenLicense, RLicenPayload, hardware::identify_pc}; fn main() -> Result<(), Box<dyn std::error::Error>> { // Get host identifier let host_uid = identify_pc(RL_TAG_PHYSICAL_STRICT)?; println!("Host UID: {}", host_uid); // Load and verify license let license = RLicenLicense::from_file("license.xlic")?; let public_key = std::fs::read_to_string("keys/public_key.pem")?; let result = license.verify(&public_key, RL_TAG_PHYSICAL_STRICT)?; if result.valid { println!("License valid for: {}", result.product_name); } else { println!("License invalid: {}", result.reason); } Ok(()) }
License Structure
Complete License (RLicenLicense)
{
"payload": {
"license_version": 1,
"license_uuid": "550e8400-e29b-41d4-a716-446655440000",
"issuer": "MyCompany",
"issued_at": "2024-01-01",
"product_name": "MyApp",
"product_version": "1.0.0",
"valid_from": "2024-01-01",
"valid_to": "2024-12-31",
"host_uid": "[{\"tag\":1,\"name\":\"CPU\",\"uid\":\"SGVsbG8td29ybGQ\"}]",
"extra_data": {
"feature1": "enable",
"max_users": "100"
}
},
"alg": "Ed25519",
"kid": "gvBJSMu2WWC",
"signature": "Base64EncodedSignature..."
}Field Descriptions
| Field | Type | Required | Description |
|---|---|---|---|
payload.license_version |
u32 | Yes | License version number (currently 1) |
payload.license_uuid |
String | Yes | Unique license identifier (UUID v4) |
payload.issuer |
String | Yes | Issuer identifier |
payload.issued_at |
String | Yes | Issue date (YYYY-MM-DD) |
payload.product_name |
String | Yes | Product name |
payload.product_version |
String | No | Product version |
payload.valid_from |
String | Yes | Effective date (YYYY-MM-DD) |
payload.valid_to |
String | No | Expiration date (YYYY-MM-DD), empty means permanent |
payload.host_uid |
String | No | Host unique identifier (JSON format) |
payload.extra_data |
Object | No | Custom data (feature flags, limits, etc.) |
alg |
String | Yes | Signature algorithm (Ed25519) |
kid |
String | Yes | Key ID (for key rotation) |
signature |
String | Yes | Signature (Base64 encoded) |
Verification Status Codes
| Status Code | Value | Description |
|---|---|---|
Ok |
0 | Verification successful |
Invalid |
1 | Invalid (general error not related to verification) |
InvalidSignature |
2 | Invalid signature |
Expired |
3 | License expired |
NotYetValid |
4 | License not yet valid |
HardwareMismatch |
5 | Hardware identifier mismatch |
InvalidFormat |
6 | Invalid license format |
InvalidKey |
7 | Invalid key |
TimeTampered |
8 | Time tampered |
Documentation
- RLicen Overview - Comprehensive overview of RLicen system
- C Interface Usage - C API documentation and usage guide
- rlgen Usage - License generation tool documentation
- rlinspect Usage - License inspection tool documentation
Architecture
RLicen
├── Core Library (lib.rs)
│ ├── License structure definitions (RLicenLicense, RLicenPayload)
│ ├── Verification result structure (RLicenVerificationResult)
│ ├── Status code definitions (RLicenStatusCode)
│ └── C interface exports
├── Hardware Identification Module (hardware/)
│ ├── Hardware identifier collection
│ ├── Host UID generation
│ └── Hardware matching verification
├── Command-line Tools
│ ├── rlgen - License generation tool
│ └── rlinspect - License inspection tool
└── C Interface (capi/)
├── C header auto-generation (cbindgen)
└── C API implementation
Development
Building
# Debug build cargo build # Release build cargo build --release # Build C library cargo build --release
Testing
# Run all tests cargo test # Run specific test cargo test test_name # Run C API tests cd capi make run
Code Style
The project follows Rust standard conventions. Use cargo fmt to format code and cargo clippy for linting.
cargo fmt cargo clippy -- -D warnings
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
Support
For issues, questions, or contributions, please visit the GitHub repository.