Not every environment has internet access. Military installations, factory floor systems, healthcare devices, and financial trading platforms often operate in air-gapped or intermittently connected networks. Your licensing system needs to work without calling home — and it needs to be just as secure offline as it is online. This is how you build it.
Why Offline Validation Matters
Online license validation is straightforward: your software calls your API, your API says yes or no. But at least 15-20% of enterprise software deployments operate in environments where that network call is impossible, unreliable, or forbidden:
- Air-gapped networks — Government, defense, and critical infrastructure systems with zero internet connectivity
- Industrial environments — Factory floor control systems, SCADA networks, and embedded devices
- Intermittent connectivity — Field deployments, ships, aircraft, and remote locations
- Compliance requirements — Healthcare, financial, and legal environments where external API calls violate data policies
- Performance-critical systems — Trading platforms and real-time systems where network latency is unacceptable
The Cryptographic Foundation: Ed25519
Offline validation relies on asymmetric cryptography. You sign license data with your private key (kept on your server), and your client software verifies the signature using your public key (embedded in the application).
// Server-side: generate offline-capable license
import { sign } from '@noble/ed25519'
const licensePayload = {
id: 'lic_offline_001',
customer: 'AcmeCorp',
plan: 'enterprise',
features: ['rbac', 'sso', 'audit-logs'],
activations: 50,
expires: '2027-06-01T00:00:00Z',
domains: ['*.acmecorp.internal']
}
const payloadBytes = new TextEncoder().encode(JSON.stringify(licensePayload))
const signature = await sign(payloadBytes, serverPrivateKey)
// License file = payload + signature
const licenseFile = {
payload: licensePayload,
signature: Buffer.from(signature).toString('base64')
}
// Client-side: verify without any network call
import { verify } from '@noble/ed25519'
const isValid = await verify(
Buffer.from(licenseFile.signature, 'base64'),
new TextEncoder().encode(JSON.stringify(licenseFile.payload)),
embeddedPublicKey // Safe to ship — it's a public key
)
if (isValid && new Date(licenseFile.payload.expires) > new Date()) {
// License is authentic and not expired
unlockFeatures(licenseFile.payload.features)
}
Ed25519 is ideal for offline validation because:
- Signatures are only 64 bytes
- Verification takes under 1ms
- Public key exposure is harmless — it can only verify, not forge
- No certificate chain or CA infrastructure required
Offline Activation Flow
For air-gapped systems that can never reach the internet, use a manual activation flow:
- Customer generates a machine fingerprint on the target device (CPU ID + disk serial + hostname)
- Customer sends the fingerprint to your activation portal via email, USB drive, or out-of-band channel
- Your server generates a signed license file bound to that specific fingerprint
- Customer copies the license file to the air-gapped machine
- Software verifies the signature and fingerprint match on every launch
Handling Expiry Without Connectivity
The biggest challenge with offline licenses is expiry enforcement. If the software can't call your server, how do you prevent clock manipulation?
Strategy 1: Monotonic Clock Checks
Track the last known timestamp and reject time reversals. If the system clock suddenly jumps backward, the license is suspicious.
Strategy 2: Usage-Based Expiry
Instead of calendar expiry, count operations. "This license is valid for 100,000 operations" is enforceable offline with a local counter.
Strategy 3: Periodic Refresh Tokens
For intermittently connected environments, issue short-lived offline tokens (30-90 days) that must be refreshed when connectivity is available. If the token expires and the machine can't phone home, switch to degraded mode.
License File Formats
| Format | Pros | Cons |
|---|---|---|
| JSON + detached signature | Human-readable, easy to debug | Two files to manage |
| JWT | Single string, standard tooling | Size limits, base64 overhead |
| Binary (protobuf) | Compact, fast parsing | Not human-readable |
| XML (legacy) | Enterprise tooling support | Verbose, complex parsing |
Security Considerations
- Never embed the private key — Only the public key should ship with your software. This is the entire point of asymmetric cryptography
- Sign the entire payload — Including plan tier, features, expiry, and device fingerprint. If any field can be modified without invalidating the signature, it will be
- Include a key version — When you rotate signing keys, old licenses need to know which public key to verify against
- Implement revocation lists — For intermittently connected systems, periodically sync a revocation list when connectivity is available
Offline-Ready License Validation
Traffic Orchestrator supports Ed25519 offline verification, air-gapped activation flows, and periodic sync for intermittently connected environments — built into every SDK.
See PlansShip licensing in your next release
5 licenses, 500 validations/month, full API access. Set up in under 5 minutes — no credit card required.