How Machine Fingerprinting Stops Software Piracy
Every desktop app developer faces the same question: how do I stop people from copying my software? The answer is machine fingerprinting — locking a license to a specific device using unique hardware characteristics.
No system is 100% piracy-proof. But server-side enforcement with device fingerprinting covers 95%+ of casual piracy.
What Is Machine Fingerprinting?
A machine fingerprint is a stable, unique identifier derived from hardware components:
- BIOS / UEFI serial
- Motherboard serial
- CPU ID
- Disk drive serial
Keymint's SDKs combine these into a single hashed hostId. This ID is salted and hashed before transmission — the raw hardware identifiers never leave the device.
Node-Locking: Binding a License to a Machine
The flow is straightforward:
- User enters their license key.
- Your app calls the activate endpoint with the key + machine's
hostId. - Keymint validates the key, checks the host is allowed, and confirms the activation limit isn't exceeded.
- Future verifications confirm the same
hostId.
curl -X POST "https://api.keymint.dev/key/activate" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"productId": "prod_100",
"licenseKey": "T8XTR-AI21B-2990H-85SB5",
"hostId": "MACHINE-A1B2C3"
}'Offline Licenses with Ed25519
For air-gapped environments, Keymint's POST /key/sign endpoint returns a cryptographically signed license file. Generate this file from your backend or release tooling with an admin API key; your app stores the file and verifies it locally at startup using a public key — no network call needed.
curl -X POST "https://api.keymint.dev/key/sign" \
-H "Authorization: Bearer YOUR_ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"productId": "prod_100",
"licenseKey": "T8XTR-AI21B-2990H-85SB5",
"hostId": "MACHINE-A1B2C3"
}'The response contains a file field: a signed JWT. Your app ships a Key Registry mapping key IDs to public PEMs and verifies the JWT locally using a standard library like jose (Node.js) or PyJWT (Python).
Server-Side Enforcement (The Golden Rule)
Never trust the client. A user who modifies your binary can skip any client-side check:
| Check Type | Where | Security Level |
|---|---|---|
| License validity | Server (API call) | High |
| Machine binding | Server (API call) | High |
| Trial expiration | Server (API call) | High |
| Offline signature | Client (local) | Medium |
| Feature flag | Client only | Low |
For high-value software, add a periodic re-verification call every 24-48 hours.
Deactivating Machines Remotely
Let users manage their own activations:
curl -X POST "https://api.keymint.dev/key/deactivate" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"productId": "prod_100",
"licenseKey": "T8XTR-AI21B-2990H-85SB5",
"hostId": "MACHINE-A1B2C3"
}'This frees up a slot so the license can move to another machine.
Anti-Tamper Techniques
Layer in these protections:
- Keep admin/read-only keys server-side — Only client-scoped keys should ever be bundled into app runtime code.
- Certificate pinning — Prevent MitM attacks on activation calls.
- Checksum your binary — Detect tampering at runtime.
- Spread verification points — Don't check in one place. Multiple checks make it harder to patch around.
Transparency Matters
Machine fingerprinting works best when you're honest with users:
- Explain why you collect a hardware ID: license enforcement, not surveillance.
- Let users deactivate old machines from a customer portal.
- Provide a grace period if hardware changes (e.g., after an OS reinstall).
Summary
Machine fingerprinting is the foundation of desktop app license enforcement. Combined with server-side validation, cryptographic offline signatures, and transparent deactivation management, it stops casual piracy while keeping legitimate customers happy.
See the API reference for the complete endpoint docs.