offline-license-validator 0.1.1

Offline license validation library using Ed25519 signatures
Documentation
# ๐Ÿ” Offline License Validator

A simple, secure Rust library for offline license validation using Ed25519 signatures.

## โœจ Features

- โœ… **Ed25519 Cryptography** - Industry-standard digital signatures
- โœ… **HWID Binding** - Licenses tied to specific hardware
- โœ… **Expiration Checking** - Automatic validation
- โœ… **Persistent Storage** - Saves to `~/.offline-license/`
- โœ… **Zero Dependencies on Runtime** - Pure Rust, no network required
- โœ… **Easy Integration** - Just 3 lines of code

## ๐Ÿ“ฆ Installation

Add to your `Cargo.toml`:

```toml
[dependencies]
offline-license-validator = "0.1.0"
```

## ๐Ÿš€ Quick Start

```rust
use offline_license_validator::{LicenseValidator, storage};

// 1. Initialize with your public key (from admin app)
let validator = LicenseValidator::new(
    "913d5e19269699e51bcdb5c5a7106c278ef0e0fe92d31b76b6daf5bb00594fcf"
).expect("Invalid public key");

// 2. Validate license
match validator.validate(license_string, hardware_id) {
    Ok(info) => {
        println!("โœ“ License valid until: {}", info.expires_at);

        // 3. Save for offline use
        storage::save_license(&info, license_string).ok();
    }
    Err(e) => eprintln!("โœ— License invalid: {}", e),
}
```

## ๐Ÿ“– Usage Examples

### Basic Validation

```rust
use offline_license_validator::LicenseValidator;

const PUBLIC_KEY: &str = "your_public_key_hex_here";

fn main() {
    let validator = LicenseValidator::new(PUBLIC_KEY).unwrap();

    let license = "eyJod2lkIjoiYWJjMTIzLi4uIiwi...";
    let hwid = "8b83180aa8f4ed018cb2991e0ff7e9b4...";

    match validator.validate(license, hwid) {
        Ok(info) => {
            println!("License Type: {}", info.license_type);
            println!("Expires: {}", info.expires_at);
        }
        Err(e) => eprintln!("Error: {}", e),
    }
}
```

### With Persistent Storage

```rust
use offline_license_validator::{LicenseValidator, storage};

fn verify_and_save(license: &str, hwid: &str) -> Result<(), Box<dyn std::error::Error>> {
    let validator = LicenseValidator::new(PUBLIC_KEY)?;
    let info = validator.validate(license, hwid)?;

    // Save to ~/.offline-license/license.json
    storage::save_license(&info, license)?;

    println!("License saved successfully!");
    Ok(())
}

fn load_cached_license() -> Option<String> {
    storage::load_saved_license()
        .ok()?
        .map(|(license_string, _)| license_string)
}
```

### Tauri Integration

```rust
use offline_license_validator::{LicenseValidator, storage};

const PUBLIC_KEY: &str = "913d5e19269699e51bcdb5c5a7106c278ef0e0fe92d31b76b6daf5bb00594fcf";

#[tauri::command]
fn verify_license(license: String, hwid: String) -> Result<String, String> {
    let validator = LicenseValidator::new(PUBLIC_KEY)
        .map_err(|e| e.to_string())?;

    let info = validator.validate(&license, &hwid)
        .map_err(|e| e.to_string())?;

    // Save validated license
    storage::save_license(&info, &license)
        .map_err(|e| e.to_string())?;

    Ok(format!("Valid until: {}", info.expires_at))
}

#[tauri::command]
fn get_cached_license() -> Result<Option<String>, String> {
    storage::load_saved_license()
        .map(|opt| opt.map(|(s, _)| s))
        .map_err(|e| e.to_string())
}
```

## ๐Ÿ”’ Security

- **Public key** is hardcoded in your application (safe)
- **Ed25519 signatures** prevent tampering (64-byte signatures)
- **HWID binding** prevents license sharing across devices
- **No network** required for validation (fully offline)
- **Expiration checks** prevent use after expiry date

## ๐Ÿ“ Storage Location

Validated licenses are saved to:

| Platform | Path |
|----------|------|
| **Linux/macOS** | `~/.offline-license/license.json` |
| **Windows** | `%USERPROFILE%\.offline-license\license.json` |

## ๐Ÿ› ๏ธ API Reference

### `LicenseValidator`

```rust
// Create new validator
LicenseValidator::new(public_key_hex: &str) -> Result<Self, LicenseError>

// Validate license
validate(&self, license_string: &str, hwid: &str) -> Result<ValidLicenseInfo, LicenseError>
```

### `storage` module

```rust
// Save validated license
save_license(info: &ValidLicenseInfo, license_string: &str) -> Result<(), std::io::Error>

// Load saved license
load_saved_license() -> Result<Option<(String, ValidLicenseInfo)>, std::io::Error>

// Delete saved license
delete_saved_license() -> Result<(), std::io::Error>
```

### Error Types

```rust
pub enum LicenseError {
    InvalidFormat(String),
    InvalidEncoding(base64::DecodeError),
    InvalidSignature,
    InvalidJson(serde_json::Error),
    HwidMismatch { expected: String, actual: String },
    Expired(DateTime<Utc>),
    InvalidPublicKey(String),
}
```

## ๐Ÿงช Testing

```bash
cargo test
```

## ๐Ÿ“ License Format

Licenses use the format: `Base64(JSON_Payload).Base64(Ed25519_Signature)`

Example payload:
```json
{
  "hwid": "8b83180aa8f4ed018cb2991e0ff7e9b4...",
  "issued_at": "2026-03-12T14:17:53Z",
  "expires_at": "2027-03-09T23:59:59Z",
  "license_type": "PRO",
  "metadata": null
}
```

## ๐Ÿค Integration Workflow

1. **Admin App** generates Ed25519 keypair
2. **Admin App** creates signed license for specific HWID
3. **Your App** hardcodes public key
4. **Your App** validates license using this library
5. **Library** saves validated license to `~/.offline-license/`

## ๐Ÿ“„ License

MIT License - See LICENSE file for details

## ๐Ÿ™ Credits

Developed by **[Krakiun](https://krakiun.com)** - Expert Software Development & Security Solutions

Built with:
- [`ed25519-dalek`]https://crates.io/crates/ed25519-dalek - Ed25519 signatures
- [`base64`]https://crates.io/crates/base64 - Base64 encoding
- [`chrono`]https://crates.io/crates/chrono - Date/time handling
- [`serde`]https://crates.io/crates/serde - Serialization

---

**Need custom licensing solutions or security consulting?** Visit [krakiun.com](https://krakiun.com)