How to Issue & Verify Offline Licenses for Air-Gapped Apps
If your customers need to run your software on secure, air-gapped machines—or simply without reliable internet—you still need robust licensing. Keymint's Offline Licenses feature lets you issue self-contained .lic
files from the dashboard and verify them purely client-side using Ed25519 signatures.
In this post we'll cover:
- Why offline licenses matter
- Generating licenses in the dashboard
- Understanding the
.lic
file format - Distribution strategies
- Client-side verification steps
- Best practices & tips
1. Why Offline Licenses Matter
You've built great software, but some customers can't—or won't—expose servers to the internet. Typical scenarios include:
- 🔒 Air-gapped networks (military, finance, healthcare)
- 🏢 On-premise deployments behind corporate firewalls
- 🚧 Manufacturing or IoT devices in isolated facilities
Offline licenses give you the same cryptographic security as online API checks, but without the runtime network dependency.
2. Generate an Offline License (Dashboard)
Unlike runtime API calls, offline licenses are created via the Keymint Dashboard:
- Log in → Products → Your Product → Licenses
- Find the license row you want to issue.
- In the Activations column, click the Eye icon (👁️) to open the Offline License modal.
- Machine Code (optional): enter a hardware fingerprint (e.g.
host-ABC123
) to lock this file to one device. - Custom TTL (seconds): required if the license itself has no expiration date.
- Click Generate Signed License.
Note: If your license record lacks an expiry date, you must supply a
TTL
here or generation will fail.
3. Understanding the .lic
File
When you press Generate, your browser downloads a JSON file named like:
license-ABC123-host-ABC123-2025-06-23.lic
The file structure looks like this:
{
"signedDate": "2025-06-23T14:12:00.000Z",
"signedKey": "eyJhbGciOiJFZERTQSJ9.…",
"publicKey": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA…\n-----END PUBLIC KEY-----"
}
Field breakdown:
signedDate
: issuance timestampsignedKey
: EdDSA-signed JWT containing your payloadpublicKey
: PEM-encoded Ed25519 key for verification
This single file is self-contained—no other assets required.
4. Distribution Strategies
Choose how your customers receive the .lic
file:
- 🌐 Web Download: provide a secure link in your portal.
- ✉️ Email: send as an attachment to IT teams.
- 💾 USB/Media: copy onto removable drives for air-gapped sites.
- 📦 Installer Bundle: package into your installer for seamless setup.
Rename files consistently (e.g. MyApp-OfflineLicense-20250623.lic
) and instruct clients not to modify contents.
5. Client-Side Verification (No Network Required)
Implement verification in your app using any Ed25519-capable JWT library. Example in Node.js/browser with jose
:
import { jwtVerify, importSPKI } from "jose";
import fs from "fs";
// 1. Load license file
const { signedKey, publicKey } = JSON.parse(
fs.readFileSync("license.lic", "utf8"),
);
// 2. Import public key
const edKey = await importSPKI(publicKey, "EdDSA");
// 3. Verify signature & decode
const { payload } = await jwtVerify(signedKey, edKey);
// 4. Enforce expiry
const now = Math.floor(Date.now() / 1000);
if (payload.exp < now) {
throw new Error("License has expired");
}
// 5. (Optional) Enforce node-lock
if (payload.machineCode && payload.machineCode !== getLocalMachineCode()) {
throw new Error("License not valid on this machine");
}
// ✅ License is valid
console.log("License payload:", payload);
Payload fields:
sub
/key
(string): License key identifierproductId
(string): Product referencemachineCode
(string, optional): Hardware fingerprint (if node-locked)type
(string): Always "offline"iat
(number): Issued-at timestamp (Unix seconds)exp
(number): Expiry timestamp (Unix seconds)
6. Best Practices & Tips
- Embed public key: in the
.lic
file for true self-containment. - Filename conventions:
license-<KEY>-<machineCode?>-YYYYMMDD.lic
. - Short TTLs: useful for revocable offline licenses (e.g. 7 days).
- Cache & refresh: apps can cache the
.lic
file, only re-download when nearly expired. - Secure storage: instruct clients to lock down file permissions on sensitive systems.
By following these steps, you can deliver a secure, offline-capable licensing experience—no network needed at runtime, yet cryptographically tamper-proof.