1 stable release
Uses new Rust 2024
| 1.1.0 | Feb 10, 2026 |
|---|
#445 in Cryptography
160KB
954 lines
Librnxlic - Professional License Management System for Rust
TABLE OF CONTENTS
- Librnxlic - Professional License Management System for Rust
- TABLE OF CONTENTS
- 1. OVERVIEW
- 2. FEATURES
- 3. INSTALLATION
- 4. QUICK START
- 5. CORE CONCEPTS
- 6. MODULE REFERENCE
- 7. EXAMPLES
- 8. CONFIGURATION GUIDE
- 9. SECURITY BEST PRACTICES
- 10. TROUBLESHOOTING
- 11. API REFERENCE
- 12. CONTRIBUTING
- 13. LICENSE
- 14. SUPPORT
- APPENDIX: COMMON USE CASES
- VERSION HISTORY
- ACKNOWLEDGMENTS
1. OVERVIEW
Librnxlic is a comprehensive, production-ready license management library for Rust applications. It provides everything you need to implement robust software licensing, activation, and validation systems. Whether you're building desktop applications, SaaS platforms, or enterprise software, Librnxlic offers the tools to protect your intellectual property and manage customer licenses effectively.
2. FEATURES
- Cryptographic license signing and verification using Ed25519
- Hardware fingerprint generation for device binding (Windows, macOS, Linux)
- Online and offline license validation modes
- Configurable grace periods and expiration policies
- License activation with server communication
- Revocation checking capabilities
- Structured feature management and validation
- Comprehensive error handling
- Async/await ready for modern applications
- Zeroized memory management for cryptographic keys
- Platform-specific hardware identification
- JSON and CBOR serialization support
3. INSTALLATION
Add to Cargo.toml
[dependencies]
librnxlic = "0.1.0"
chrono = "0.4"
uuid = { version = "1.0", features = ["serde", "v4"] }
tracing = "0.1"
tokio = { version = "1.0", features = ["full"] }
Supported Rust Versions
Minimum Supported Rust Version: 1.70.0
Platform Support
- Windows 10/11 (fully supported)
- macOS 10.15+ (fully supported)
- Linux (glibc/musl) (fully supported)
- WebAssembly (limited support, no hardware fingerprint)
- Android/iOS (experimental)
4. QUICK START
Basic License Creation and Validation
use librnxlic::*;
use chrono::{Utc, Duration};
fn main() -> Result<(), LicenseError> {
// Create license engine
let engine = LicenseEngine::new(LicenseConfig::default());
// Generate cryptographic keys
let keypair = engine.generate_keypair()?;
// Create license payload
let payload = LicensePayload {
license_id: Uuid::new_v4(),
customer_id: "customer-123".to_string(),
product_id: "myapp-pro".to_string(),
expires_at: Utc::now() + Duration::days(365),
issued_at: Utc::now(),
max_activations: 3,
features: vec!["premium".to_string(), "api-access".to_string()],
metadata: serde_json::json!({}),
};
// Sign and create license
let license = engine.create_license(&keypair, payload)?;
// Save public key for distribution
keypair.save_to_file("public_key.json")?;
// Save license
let license_json = engine.license_to_json(&license)?;
std::fs::write("license.json", license_json)?;
// Later, verify the license
let public_key = KeyPair::load_public_from_file("public_key.json")?;
let result = engine.verify_license(&public_key, &license)?;
if result.is_valid() {
println!("✅ License valid!");
println!(" Features: {:?}", result.features);
println!(" Days remaining: {:?}", result.days_remaining);
} else {
println!("❌ License invalid:");
for violation in result.violations {
println!(" - {}", violation);
}
}
Ok(())
}
Online Activation Flow
use librnxlic::*;
use chrono::Utc;
#[tokio::main]
async fn main() -> Result<(), LicenseError> {
// Generate hardware fingerprint
let fingerprint = HardwareFingerprint::generate()?;
println!("Hardware fingerprint: {}", fingerprint);
// Load existing license
let engine = LicenseEngine::new(LicenseConfig::default());
let license_json = std::fs::read_to_string("license.json")?;
let license = engine.license_from_json(&license_json)?;
// Create activation request
let request = ActivationRequest {
license_id: license.license_id(),
hardware_fingerprint: fingerprint,
machine_name: hostname::get()?.to_string_lossy().to_string(),
ip_address: None,
user_agent: Some(format!("MyApp/1.0.0")),
timestamp: Utc::now(),
nonce: Uuid::new_v4().to_string(),
};
// Send to license server
let client = LicenseClient::new("https://license.example.com")
.with_api_key("your-api-key");
match client.activate_license(&request).await {
Ok(response) => {
println!("✅ Activation successful!");
println!(" Activation ID: {}", response.activation_id);
println!(" Token expires: {}", response.expires_at);
// Store activation token securely
save_token("activation_token", &response.activation_token);
}
Err(LicenseError::ActivationLimitExceeded) => {
println!("❌ Activation limit reached");
println!(" Max: {}, Current: {}",
response.max_activations, response.current_activations);
}
Err(e) => {
println!("❌ Activation failed: {}", e);
}
}
Ok(())
}
5. CORE CONCEPTS
License Structure
A license consists of three main components:
- Payload: The actual license data (customer info, features, expiration)
- Signature: Cryptographic proof that the payload hasn't been tampered with
- Algorithm: The signing algorithm used (currently only "ed25519")
Cryptographic Flow
- Key Generation: Create an Ed25519 key pair
- Signing: Hash the license payload and sign with private key
- Verification: Verify signature against payload using public key
- Distribution: Only distribute public key to clients
Activation Process
- Client generates hardware fingerprint
- Client sends activation request to license server
- Server validates license and checks activation limits
- Server creates activation record and returns tokens
- Client stores tokens for future validations
- Periodic validation checks with server
6. MODULE REFERENCE
activation.rs
Structures for license activation:
- ActivationRequest: Client request to activate license
- ActivationResponse: Server response with tokens
- ActivationRecord: Server-side activation tracking
client.rs
HTTP client for license server communication:
- LicenseClient: Async client for server operations
- Methods: activate_license, validate_license, check_revocation
crypto.rs
Cryptographic operations:
- KeyPair: Ed25519 key pair with zeroization
- PrivateKey: Secure private key storage
- PublicKey: Public key for verification
- Features: Key generation, signing, verification, serialization
engine.rs
Core license engine:
- LicenseEngine: Main entry point for license operations
- LicenseConfig: Validation configuration
- ValidationResult: Detailed validation results
- Methods: create_license, verify_license, validate_license_content
error.rs
Comprehensive error handling:
- LicenseError enum with 20+ error variants
- Automatic conversions from common error types
- Serialization support for API responses
hardware.rs
Hardware fingerprint generation:
- HardwareFingerprint: Platform-specific hardware identification
- HardwareInfo: Collected hardware data structure
- Supported platforms: Windows, macOS, Linux
license.rs
License data structures:
- License: Complete license with signature
- LicensePayload: License data without signature
- LicenseFeatures: Structured feature representation
- Methods: expiration checking, feature validation
validation.rs
Validation logic:
- LicenseValidator: Configurable validation engine
- ValidationResult: Validation outcome with details
- Rules: expiration, hardware binding, online requirements
7. EXAMPLES
Example 1: Desktop Application License Check
use librnxlic::*;
fn check_application_license() -> Result<(), LicenseError> {
// Load vendor's public key
let public_key = KeyPair::load_public_from_file("vendor_public_key.json")?;
// Load user's license file
let license_path = get_license_path(); // e.g., ~/.myapp/license.json
let license_json = std::fs::read_to_string(license_path)?;
// Parse and verify license
let engine = LicenseEngine::new(LicenseConfig::default());
let license = engine.license_from_json(&license_json)?;
let result = engine.verify_license(&public_key, &license)?;
if !result.is_valid() {
return Err(LicenseError::ValidationFailed(
result.violations.join(", ")
));
}
// Check for required features
if !license.has_feature("premium") {
disable_premium_features();
}
if license.has_feature("export") {
enable_export_functionality();
}
Ok(())
}
Example 2: Web Service License Validation Middleware
use librnxlic::*;
use axum::{extract::State, http::Request, middleware::Next, response::Response};
struct AppState {
license_client: LicenseClient,
}
async fn license_middleware<B>(
State(state): State<AppState>,
request: Request<B>,
next: Next<B>,
) -> Result<Response, LicenseError> {
// Extract license ID and token from headers
let license_id = get_header(&request, "X-License-ID")?;
let activation_token = get_header(&request, "X-Activation-Token")?;
// Validate with license server
let license = state.license_client
.validate_license(&license_id, &activation_token)
.await?;
// Check if license has required feature
if !license.has_feature("api-access") {
return Err(LicenseError::InvalidLicense(
"API access not authorized".to_string()
));
}
// Attach license to request for handlers
let mut request = request;
request.extensions_mut().insert(license);
Ok(next.run(request).await)
}
Example 3: Command Line License Management Tool
use librnxlic::*;
use clap::{Parser, Subcommand};
#[derive(Parser)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// Generate a new license
Generate {
#[arg(short, long)]
customer_id: String,
#[arg(short, long)]
days: u32,
#[arg(short, long)]
features: Vec<String>,
},
/// Validate a license file
Validate {
#[arg(short, long)]
license_file: String,
},
/// Activate license online
Activate {
#[arg(short, long)]
license_file: String,
#[arg(short, long)]
server_url: String,
},
}
fn main() -> Result<(), LicenseError> {
let cli = Cli::parse();
match cli.command {
Commands::Generate { customer_id, days, features } => {
generate_license(customer_id, days, features)?;
}
Commands::Validate { license_file } => {
validate_license_file(&license_file)?;
}
Commands::Activate { license_file, server_url } => {
activate_license(&license_file, &server_url).await?;
}
}
Ok(())
}
8. CONFIGURATION GUIDE
LicenseConfig Options
use librnxlic::engine::LicenseConfig;
// Strict configuration (security-focused)
let strict_config = LicenseConfig {
allow_offline: false, // Require online validation
grace_period_days: 0, // No grace period
max_clock_skew_seconds: 60, // Strict time sync (1 minute)
require_hardware_binding: true, // Enforce hardware binding
enable_revocation_check: true, // Check revocation status
};
// Flexible configuration (user-friendly)
let flexible_config = LicenseConfig {
allow_offline: true, // Allow offline use
grace_period_days: 30, // 30-day grace period
max_clock_skew_seconds: 3600, // Lenient time sync (1 hour)
require_hardware_binding: false, // No hardware binding
enable_revocation_check: false, // Skip revocation checks
};
// Development configuration
let dev_config = LicenseConfig {
allow_offline: true,
grace_period_days: 365, // 1 year grace for testing
max_clock_skew_seconds: 86400, // 24 hour clock skew tolerance
require_hardware_binding: false,
enable_revocation_check: false,
};
Environment Variables
# Application environment variables
export LICENSE_SERVER_URL="https://license.example.com"
export LICENSE_API_KEY="your-api-key-123"
export LICENSE_VALIDATION_MODE="strict" # strict, flexible, or development
export LICENSE_CACHE_DIR="/var/lib/myapp/licenses"
export LICENSE_GRACE_PERIOD_DAYS="7"
# Hardware fingerprint settings (optional)
export LICENSE_HARDWARE_SALT="custom-salt-value"
export LICENSE_EXCLUDE_VIRTUAL_HARDWARE="true"
9. SECURITY BEST PRACTICES
Key Management
- Private Keys: Never embed in client applications
- Key Storage: Use HSMs or encrypted key stores in production
- Key Rotation: Implement regular key rotation policies
- Key Backup: Secure backups with proper access controls
License Security
- Signature Verification: Always verify before trusting license data
- Tamper Detection: Monitor for signature validation failures
- Revocation Lists: Maintain and check revocation lists
- Rate Limiting: Implement activation and validation rate limits
Network Security
- HTTPS: Always use TLS for license server communication
- Token Security: Store activation tokens securely
- Request Signing: Consider signing activation requests
- IP Whitelisting: Restrict license server access
Hardware Fingerprint Considerations
- Privacy: Hash hardware data, don't transmit raw identifiers
- Stability: Some hardware identifiers may change (network cards, etc.)
- Virtualization: Virtual machines may have identical fingerprints
- Grace Periods: Allow hardware changes with verification
10. TROUBLESHOOTING
Common Issues and Solutions
Issue: "Signature validation failed"
- Cause: License file corrupted or tampered with
- Solution: Regenerate license from original source
Issue: "License has expired"
- Cause: License past expiration date
- Solution: Check system clock, renew license
Issue: "Hardware fingerprint required"
- Cause: Configuration requires hardware binding but none provided
- Solution: Enable hardware fingerprint generation or adjust configuration
Issue: "Online validation required"
- Cause: Network unavailable but configuration requires online validation
- Solution: Check network connection or adjust allow_offline setting
Issue: "Activation limit exceeded"
- Cause: Too many devices activated with same license
- Solution: Deactivate unused devices or upgrade license
Issue: Hardware fingerprint changes
- Cause: Hardware upgrades or virtualization changes
- Solution: Implement grace period for hardware changes
Debugging Tips
- Enable tracing for detailed logs:
tracing_subscriber::fmt::init();
- Check system clock synchronization:
# Linux
timedatectl status
# Windows
w32tm /query /status
# macOS
systemsetup -getnetworktimeserver
- Verify hardware fingerprint generation:
let fingerprint = HardwareFingerprint::generate()?;
println!("Debug fingerprint: {}", fingerprint);
11. API REFERENCE
LicenseEngine
Main entry point for license operations:
impl LicenseEngine {
// Creation
pub fn new(config: LicenseConfig) -> Self;
pub fn create_license(&self, keypair: &KeyPair, payload: LicensePayload) -> Result<License, LicenseError>;
pub fn generate_keypair(&self) -> Result<KeyPair, LicenseError>;
// Verification
pub fn verify_license(&self, public_key: &PublicKey, license: &License) -> Result<ValidationResult, LicenseError>;
// Serialization
pub fn license_to_json(&self, license: &License) -> Result<String, LicenseError>;
pub fn license_from_json(&self, json: &str) -> Result<License, LicenseError>;
pub fn license_to_bytes(&self, license: &License) -> Result<Vec<u8>, LicenseError>;
pub fn license_from_bytes(&self, bytes: &[u8]) -> Result<License, LicenseError>;
}
LicenseClient
HTTP client for server communication:
impl LicenseClient {
// Construction
pub fn new(base_url: &str) -> Self;
pub fn with_api_key(self, api_key: &str) -> Self;
// Operations
pub async fn activate_license(&self, request: &ActivationRequest) -> Result<ActivationResponse, LicenseError>;
pub async fn validate_license(&self, license_id: &Uuid, activation_token: &str) -> Result<License, LicenseError>;
pub async fn check_revocation(&self, license_id: &Uuid) -> Result<bool, LicenseError>;
}
KeyPair
Cryptographic key management:
impl KeyPair {
// Generation
pub fn generate() -> Self;
pub fn from_seed(seed: &[u8]) -> Result<Self, LicenseError>;
// Persistence
pub fn save_to_file(&self, path: &std::path::Path) -> Result<(), LicenseError>;
pub fn load_public_from_file(path: &std::path::Path) -> Result<PublicKey, LicenseError>;
}
HardwareFingerprint
Device identification:
impl HardwareFingerprint {
pub fn generate() -> Result<String, LicenseError>;
}
12. CONTRIBUTING
Development Setup
- Clone repository:
git clone https://github.com/yourorg/librnxlic.git
cd librnxlic
- Install dependencies:
cargo build
- Run tests:
cargo test --all-features
- Run lints:
cargo clippy -- -D warnings
cargo fmt --check
Testing Strategy
- Unit tests for individual modules
- Integration tests for full workflows
- Platform-specific tests for hardware fingerprinting
- Fuzz testing for cryptographic operations
- Performance benchmarks for critical paths
Code Standards
- Follow Rust naming conventions
- Document all public APIs
- Use meaningful error messages
- Include examples in documentation
- Maintain backward compatibility
- Use zeroize for cryptographic data
13. LICENSE
This project is dual-licensed under:
- Apache License, Version 2.0
- MIT License
Choose the license that best fits your needs. See LICENSE-APACHE and LICENSE-MIT files for details.
14. SUPPORT
Getting Help
- Documentation: https://docs.rs/librnxlic
- GitHub Issues: https://github.com/yourorg/librnxlic/issues
- Discussions: https://github.com/yourorg/librnxlic/discussions
- Email: support@example.com
Reporting Bugs
When reporting bugs, please include:
- Operating system and version
- Rust version (rustc --version)
- Library version
- Steps to reproduce
- Expected vs actual behavior
- Relevant error messages and logs
Feature Requests
We welcome feature requests! Please:
- Check existing issues first
- Describe the use case
- Explain the expected benefit
- Suggest implementation approach if possible
Security Issues
For security vulnerabilities, please contact: security@example.com
Do not disclose security issues publicly until they are resolved.
APPENDIX: COMMON USE CASES
Use Case 1: Desktop Software Licensing
Scenario: Commercial desktop application with offline capability
Implementation:
- Generate hardware-bound licenses
- Allow offline validation with grace period
- Implement activation limit (e.g., 2 devices per license)
- Provide license renewal mechanism
Use Case 2: SaaS Application Add-ons
Scenario: Feature gating in web application
Implementation:
- License server validates feature access
- Token-based validation for API calls
- Real-time license updates
- Usage tracking and reporting
Use Case 3: Enterprise Software Deployment
Scenario: Large organization with centralized license management
Implementation:
- Bulk license generation
- Centralized activation server
- Usage reporting and analytics
- Automated renewal workflows
Use Case 4: Mobile Application Features
Scenario: In-app purchases and premium features
Implementation:
- Store activation tokens securely
- Periodic validation with server
- Graceful degradation when offline
- Cross-platform compatibility
VERSION HISTORY
v1.0.0 (Current)
- Initial release with core functionality
- Ed25519 cryptographic signing
- Hardware fingerprint generation
- Basic license validation
- Async HTTP client
Planned Features:
- License encryption at rest
- Advanced revocation mechanisms
- License pooling and floating
- WebAssembly support
- Docker container licensing
- Cloud license server reference implementation
ACKNOWLEDGMENTS
- Rust Crypto team for Ed25519 implementation
- Tokio team for async runtime
- All contributors and users
- Open source community for inspiration and tools
Dependencies
~22–58MB
~887K SLoC