Hardware locking
How a key gets tied to a machine, and the one thing most licensing guides get wrong about it.
How it works
The client collects the sources you enabled, normalises them into one string and returns the SHA-256 of
it. On the first successful login the key binds to that digest. Once the device limit is reached, other
machines are refused with HWID_LIMIT.
Sources
| Source | Unique per | Survives |
|---|---|---|
| CPU (CPUID) | Processor model, not machine | Everything except a CPU swap |
| Windows MachineGuid | Windows installation | Hardware changes, not a reinstall |
| System volume serial | Filesystem | Reboots, not a reformat |
| Computer name | Nothing, the user sets it | Trivially changed |
CPU alone does not identify a machine
CPUID reports the processor model, feature bits and core count. It does not report a per chip serial; Intel removed that after the Pentium III. Every customer running the same CPU model produces the same hardware id, so a limit of one device will not stop two people with the same processor from sharing a key.
If you need a real per installation lock, enable MachineGuid as well. CPU only is the right choice if you deliberately want a loose lock that survives disk changes.
Choosing a combination
| Goal | Enable |
|---|---|
| Stop key sharing | CPU + MachineGuid |
| Tolerate reinstalls, still block sharing across different machines | CPU + volume serial |
| Very loose, per hardware family | CPU only |
| No lock at all | Turn hardware locking off |
Changing which sources are enabled changes every client hardware id, so all
previously bound devices stop matching and legitimate customers get HWID_LIMIT. If you
must change it, ship the rebuilt SDK first, then reset devices on affected keys.
Letting customers reset themselves
Hardware changes are the most common support ticket a licensing server generates. Turn on Allow clients to reset their own hardware id in application settings and the client can clear its own binding.
if (!client.login(userKey) && client.error_code() == "HWID_LIMIT") {
if (client.reset_hwid(userKey)) {
client.login(userKey); // rebinds to this machine
} else {
// HWID_RESET_COOLDOWN carries retry_after in seconds
auto wait = client.last_hwid_reset().retry_after;
}
}
hwid.reset deliberately works without a successful login. A key sitting
at its device limit cannot log in, so requiring authentication first would make the feature
impossible to use. It takes the key directly, and refuses banned, revoked or expired keys.
Two settings bound the abuse:
| Setting | Effect |
|---|---|
| Cooldown hours | Time before the next reset. 0 allows resets at any moment. |
| Maximum resets per key | Lifetime cap. 0 means unlimited. |
| Time charged per reset | Minutes taken straight off the key expiry. 0 charges nothing. |
Charging time for a reset
This is the most effective way to give a reset a price. Set Time charged per reset to
120 and each reset takes two hours off the key. Someone genuinely upgrading a machine once
barely notices, while someone alternating between two machines burns their own subscription down.
It never kills a customer's key
When the key has less time left than the charge, the server refuses the reset with
HWID_RESET_WOULD_EXPIRE rather than subtracting past zero and ending the subscription.
The error carries penalty and remaining in seconds so your client can
explain the situation.
Lifetime keys are never charged, because there is no expiry to take from. If you sell lifetime keys, rely on the cooldown and the reset cap instead; the time charge does nothing for them.
The reset response returns the new expires_at and expires_in, and the SDK
updates client.license() at the same time, so you can show the customer their new expiry
immediately.
This is the control a key sharer will abuse
Two people can share one key by resetting between sessions. A cooldown makes that painful; a reset limit makes it finite. With both set to 0 your device limit stops meaning anything at all, because any machine can take the key whenever it likes.
A 24 to 72 hour cooldown with a lifetime cap of 3 to 5 covers genuine hardware upgrades without
enabling rotation. Every reset is written to the activity log as a security event, so
abuse is visible.
Handling support requests yourself
With self service off, or when a customer has used their allowance, open the key in the Keys tab and use the chip icon to clear bound devices. The next login rebinds. That is the correct fix; raising the device limit permanently is how keys end up shared.
A device limit of 0 means unlimited, which effectively disables the lock while still
recording which machines used the key. That is useful for auditing without blocking anyone.