rust-license-key 0.1.0

A production-grade Rust library for creating and validating offline software licenses using Ed25519 cryptography
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
# Security Best Practices

This guide covers security considerations and best practices for using rust-license-key in production environments.

## Table of Contents

1. [Security Model Overview]#security-model-overview
2. [Key Management]#key-management
3. [License Distribution]#license-distribution
4. [Client-Side Security]#client-side-security
5. [What This Library Does NOT Protect Against]#what-this-library-does-not-protect-against
6. [Security Checklist]#security-checklist

---

## Security Model Overview

### Cryptographic Foundation

rust-license-key uses **Ed25519** digital signatures, which provide:

| Property | Value |
|----------|-------|
| Algorithm | Ed25519 (Curve25519 + SHA-512) |
| Security Level | 128-bit (equivalent to RSA-3072) |
| Key Size | 32 bytes (private), 32 bytes (public) |
| Signature Size | 64 bytes |
| Resistance | Quantum-resistant concerns ongoing |

### Trust Model

```
┌─────────────────────────────────────────────────────────────────┐
│                     TRUSTED ZONE                                 │
│                (Your secure infrastructure)                      │
│                                                                  │
│  ┌──────────────────┐                                           │
│  │   Private Key    │ ← NEVER leaves this zone                  │
│  │   (32 bytes)     │                                           │
│  └────────┬─────────┘                                           │
│           │                                                      │
│           ▼                                                      │
│  ┌──────────────────┐                                           │
│  │ License Signing  │                                           │
│  │     Server       │                                           │
│  └────────┬─────────┘                                           │
│           │                                                      │
└───────────│─────────────────────────────────────────────────────┘
            ▼ (signed license)
┌─────────────────────────────────────────────────────────────────┐
│                    UNTRUSTED ZONE                                │
│            (Customer environment, public internet)               │
│                                                                  │
│  ┌──────────────────┐    ┌──────────────────┐                   │
│  │   Public Key     │    │  Signed License  │                   │
│  │  (embedded)      │    │  (from file)     │                   │
│  └────────┬─────────┘    └────────┬─────────┘                   │
│           │                       │                              │
│           ▼                       ▼                              │
│  ┌────────────────────────────────────────┐                     │
│  │         License Validation             │                     │
│  │   (signature verification + checks)    │                     │
│  └────────────────────────────────────────┘                     │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

### Security Guarantees

| Guarantee | Description |
|-----------|-------------|
| **Authenticity** | Only holder of private key can create valid licenses |
| **Integrity** | Any modification to license invalidates signature |
| **Non-repudiation** | Publisher cannot deny creating a valid license |

### What Is NOT Guaranteed

| Aspect | Limitation |
|--------|------------|
| **Confidentiality** | License content is readable by anyone |
| **Copy Protection** | Licenses can be copied between machines |
| **Reverse Engineering** | Public key in binary can be extracted |
| **Runtime Protection** | Validation can be bypassed in memory |

---

## Key Management

### Private Key Security

The private key is the most critical security asset. If compromised, attackers can generate unlimited valid licenses.

#### DO

- Store private keys in a Hardware Security Module (HSM) for high-value products
- Use encrypted storage (e.g., HashiCorp Vault, AWS KMS, Azure Key Vault)
- Restrict access to key material to minimal personnel
- Enable audit logging for all key access
- Use separate keys for development/testing and production
- Rotate keys periodically (with license re-issuance)

#### DON'T

- Store private keys in source control
- Store private keys in plaintext files
- Email or transmit private keys over insecure channels
- Share private keys between team members
- Use the same key for multiple products
- Store private keys on internet-facing servers

### Key Storage Examples

#### Environment Variable (Development Only)

```rust
let private_key = std::env::var("LICENSE_PRIVATE_KEY")
    .expect("LICENSE_PRIVATE_KEY must be set");
let key_pair = KeyPair::from_private_key_base64(&private_key)?;
```

#### File with Restricted Permissions (Simple Production)

```bash
# Create key file with restricted permissions
chmod 600 /etc/myapp/private_key.txt
chown root:root /etc/myapp/private_key.txt
```

```rust
let private_key = std::fs::read_to_string("/etc/myapp/private_key.txt")?;
let key_pair = KeyPair::from_private_key_base64(private_key.trim())?;
```

#### AWS Secrets Manager (Recommended for Cloud)

```rust
use aws_sdk_secretsmanager::Client;

async fn get_key_pair(client: &Client) -> Result<KeyPair, Box<dyn Error>> {
    let response = client
        .get_secret_value()
        .secret_id("myapp/license-private-key")
        .send()
        .await?;

    let private_key = response.secret_string().unwrap();
    Ok(KeyPair::from_private_key_base64(private_key)?)
}
```

### Public Key Distribution

The public key is safe to distribute but should be embedded carefully.

#### Embedding in Rust Binary

```rust
// This key will be compiled into your binary
const PUBLIC_KEY: &str = "your-base64-public-key";

fn validate(license: &str) -> bool {
    is_license_valid(license, PUBLIC_KEY)
}
```

#### Obfuscation (Defense in Depth)

While not a security measure, splitting the key can deter casual inspection:

```rust
fn get_public_key() -> String {
    let parts = [
        "Bp7Y2xK9",
        "mN4vL8qR",
        "3tH6wE5j",
        "A0cF2gI1",
    ];
    parts.join("")
}
```

---

## License Distribution

### License File Security

Licenses are **signed but not encrypted**. Anyone with the file can read its contents.

#### What to Include

- License ID
- Customer ID
- Expiration date
- Allowed features
- Technical constraints

#### What NOT to Include

- Customer passwords or API keys
- Sensitive business information
- Personal identifiable information (PII)
- Payment or financial data

### Secure Delivery

| Method | Security | Recommendation |
|--------|----------|----------------|
| HTTPS download portal | Good | Recommended for most cases |
| Email attachment | Poor | Avoid; email is not secure |
| In-app delivery | Good | Use HTTPS with certificate pinning |
| Physical media | Varies | Acceptable for air-gapped systems |

### License Revocation

rust-license-key operates offline and does not support automatic revocation. Strategies for revocation:

1. **Short-lived licenses**: Issue licenses with shorter expiration periods
2. **Version constraints**: New software versions reject old licenses
3. **Hybrid approach**: Online check at startup with offline fallback

```rust
// Example: Check online revocation list, fall back to offline validation
async fn validate_with_revocation(license: &str) -> bool {
    // Try online check first
    if let Ok(is_revoked) = check_revocation_server(license).await {
        if is_revoked {
            return false;
        }
    }

    // Fall back to offline validation
    is_license_valid(license, PUBLIC_KEY)
}
```

---

## Client-Side Security

### Validation Best Practices

#### Validate Early and Often

```rust
fn main() {
    // Validate at startup
    let license_result = validate_license(&read_license(), PUBLIC_KEY, &context());

    if !license_result.map(|r| r.is_valid).unwrap_or(false) {
        eprintln!("Invalid license. Exiting.");
        std::process::exit(1);
    }

    // Re-validate periodically
    std::thread::spawn(|| {
        loop {
            std::thread::sleep(Duration::from_secs(3600)); // Every hour
            if !is_license_valid(&read_license(), PUBLIC_KEY) {
                eprintln!("License no longer valid");
                // Handle gracefully
            }
        }
    });
}
```

#### Check Features at Point of Use

```rust
fn premium_feature() -> Result<(), &'static str> {
    let result = validate_license(&license, PUBLIC_KEY,
        &ValidationContext::new().with_feature("premium"))?;

    if !result.is_valid {
        return Err("Premium feature not licensed");
    }

    // Execute premium feature
    Ok(())
}
```

### Handling Validation Failures

```rust
fn handle_validation(result: &ValidationResult) {
    if result.is_valid {
        return;
    }

    for failure in &result.failures {
        match failure.failure_type {
            ValidationFailureType::Expired => {
                // Show renewal prompt
                show_renewal_dialog();
            }
            ValidationFailureType::InvalidSignature => {
                // Potential tampering - log and exit
                log_security_event("Invalid license signature detected");
                std::process::exit(1);
            }
            ValidationFailureType::FeatureConstraint => {
                // Disable feature gracefully
                disable_feature(&failure.message);
            }
            _ => {
                show_license_error(&failure.message);
            }
        }
    }
}
```

### Defensive Coding

```rust
// Bad: Trusts any license that parses
fn bad_check(license: &str) -> bool {
    parse_license(license, PUBLIC_KEY).is_ok()
}

// Good: Full validation with context
fn good_check(license: &str) -> bool {
    let context = ValidationContext::new()
        .with_hostname(&get_hostname())
        .with_software_version(get_version());

    validate_license(license, PUBLIC_KEY, &context)
        .map(|r| r.is_valid)
        .unwrap_or(false)
}
```

---

## What This Library Does NOT Protect Against

### Binary Patching

An attacker can modify your compiled binary to:
- Skip license validation entirely
- Replace the embedded public key with their own
- Patch out feature checks

**Mitigation**: Code signing, integrity checks, obfuscation (defense in depth)

### Memory Manipulation

An attacker can modify running process memory to:
- Change validation return values
- Modify license data after parsing

**Mitigation**: Limited; this is a fundamental limitation of offline validation

### Key Extraction

The public key embedded in your binary can be extracted and used to:
- Understand license validation logic
- Create tools that parse your licenses

**Note**: This does NOT allow creating valid licenses (requires private key)

### License Sharing

Customers can share their license files with others.

**Mitigation**:
- Bind licenses to machine IDs or hostnames
- Limit concurrent connections
- Monitor for unusual usage patterns

### Reverse Engineering

Determined attackers can reverse engineer your application to understand and bypass license checks.

**Mitigation**:
- Consider the threat model for your product
- High-value products may need additional protection (hardware dongles, online-only features)
- Accept that perfect protection is impossible for offline software

---

## Security Checklist

### Before Production Deployment

- [ ] Private key stored in HSM or encrypted vault
- [ ] Private key access restricted and audited
- [ ] Separate keys for development and production
- [ ] Public key embedded (not loaded from external file)
- [ ] License validation occurs at startup
- [ ] License validation occurs before feature access
- [ ] Validation failures are logged
- [ ] No sensitive data in license payload
- [ ] Licenses delivered over HTTPS

### Periodic Review

- [ ] Review key access logs
- [ ] Audit license issuance records
- [ ] Test validation with expired/invalid licenses
- [ ] Update library to latest version
- [ ] Review for newly discovered vulnerabilities

### Incident Response

- [ ] Plan for key compromise (re-issue all licenses)
- [ ] Plan for mass license revocation (version update)
- [ ] Monitoring for unusual license patterns
- [ ] Customer communication plan

---

**Previous:** [API Reference]./api-reference.md | **Next:** [Examples]./examples.md