How Foliox License stops a fake server from unlocking your app

The usual way people crack a licensed tool is not clever. They point it at a server that always says yes. Here is how I made that stop working.

The Foliox License landing page

The most common way a licensed tool gets cracked isn’t clever reverse engineering. Someone points the app at their own little server that answers every license check with "valid": true. That’s it. That’s the whole crack.

If your licensing is a plain HTTP request that returns yes or no, that trick works on you. Here’s how I shut it down when I built Foliox License, the license system I use for the tools I sell.

Sign every answer

The server holds an Ed25519 private key. Every response it sends is signed with it, the “no” answers included. Your app ships with only the public key.

When the app gets a response, it checks the signature before it believes anything inside it. A fake server can return whatever JSON it likes, but it can’t produce a valid signature without the private key. So the check fails and the app stays locked.

In the Python SDK that whole dance is one call:

result = client.check(license_key)
if not result.valid:
    exit("Not licensed: " + result.reason)

The signature check happens inside check(). You don’t have to think about it, which is the point. Security that needs the developer to remember an extra step usually gets skipped.

Lock the key to one machine

Signing stops fake servers. It doesn’t stop someone buying one key and handing it to ten friends.

So on first run, the app sends the key along with a hashed machine ID. The server binds the two together. When the same key shows up from a different machine, it gets refused. The raw hardware details never leave the user’s PC, only the hash.

Real people do change computers though, so customers can ask for a device reset from a self-service page, and you approve it with one click.

Don’t punish people for bad Wi-Fi

Strict licensing gets annoying fast if the app dies every time the internet blinks. Foliox gives the app up to 72 hours of offline grace, so a dropped connection on a train doesn’t lock out someone who paid.

Always return 200

One small decision I like: the API always answers with HTTP 200 and puts the real outcome in the signed body. “Expired”, “revoked”, “wrong device” are all just fields inside a response you can verify. There’s one code path to handle in the SDKs, and every outcome carries a signature.

What I’d tell you if you’re building your own

  1. Never trust an unsigned “yes”.
  2. Bind keys to something about the machine, and hash it.
  3. Make revoking instant, because refunds and leaks happen.
  4. Leave room for honest users with bad internet.

If you’d rather not build it, Foliox License has a free plan with SDKs for Python, Node.js, Go and Rust. That’s the reason I opened it up.

Written by Mohit Kamboj, a full-stack developer in Chandigarh, Punjab, India. Need something like this built? Tell me about it.