#validation #online-activation #licensing #hardware #key-pair #public-key #revocation #fingerprint #grace

librnxengine

implement robust software licensing, activation, and validation systems

1 stable release

Uses new Rust 2024

1.1.0 Feb 10, 2026

#445 in Cryptography

AGPL-3.0-only

160KB
954 lines

Librnxlic - Professional License Management System for Rust

TABLE OF CONTENTS

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:

  1. Payload: The actual license data (customer info, features, expiration)
  2. Signature: Cryptographic proof that the payload hasn't been tampered with
  3. Algorithm: The signing algorithm used (currently only "ed25519")

Cryptographic Flow

  1. Key Generation: Create an Ed25519 key pair
  2. Signing: Hash the license payload and sign with private key
  3. Verification: Verify signature against payload using public key
  4. Distribution: Only distribute public key to clients

Activation Process

  1. Client generates hardware fingerprint
  2. Client sends activation request to license server
  3. Server validates license and checks activation limits
  4. Server creates activation record and returns tokens
  5. Client stores tokens for future validations
  6. 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

  1. Private Keys: Never embed in client applications
  2. Key Storage: Use HSMs or encrypted key stores in production
  3. Key Rotation: Implement regular key rotation policies
  4. Key Backup: Secure backups with proper access controls

License Security

  1. Signature Verification: Always verify before trusting license data
  2. Tamper Detection: Monitor for signature validation failures
  3. Revocation Lists: Maintain and check revocation lists
  4. Rate Limiting: Implement activation and validation rate limits

Network Security

  1. HTTPS: Always use TLS for license server communication
  2. Token Security: Store activation tokens securely
  3. Request Signing: Consider signing activation requests
  4. IP Whitelisting: Restrict license server access

Hardware Fingerprint Considerations

  1. Privacy: Hash hardware data, don't transmit raw identifiers
  2. Stability: Some hardware identifiers may change (network cards, etc.)
  3. Virtualization: Virtual machines may have identical fingerprints
  4. 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

  1. Enable tracing for detailed logs:
tracing_subscriber::fmt::init();
  1. Check system clock synchronization:
# Linux
timedatectl status

# Windows
w32tm /query /status

# macOS
systemsetup -getnetworktimeserver
  1. 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

  1. Clone repository:
git clone https://github.com/yourorg/librnxlic.git
cd librnxlic
  1. Install dependencies:
cargo build
  1. Run tests:
cargo test --all-features
  1. 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

  1. Follow Rust naming conventions
  2. Document all public APIs
  3. Use meaningful error messages
  4. Include examples in documentation
  5. Maintain backward compatibility
  6. Use zeroize for cryptographic data

13. LICENSE

This project is dual-licensed under:

  1. Apache License, Version 2.0
  2. MIT License

Choose the license that best fits your needs. See LICENSE-APACHE and LICENSE-MIT files for details.

14. SUPPORT

Getting Help

Reporting Bugs

When reporting bugs, please include:

  1. Operating system and version
  2. Rust version (rustc --version)
  3. Library version
  4. Steps to reproduce
  5. Expected vs actual behavior
  6. Relevant error messages and logs

Feature Requests

We welcome feature requests! Please:

  1. Check existing issues first
  2. Describe the use case
  3. Explain the expected benefit
  4. 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