Engineering
Why I moved the license secret off the client
A code review caught a critical issue: the signing secret was compiled into every .exe. Here is what happened and how I fixed it.
The problem
Web Iron Shield used a classic offline activation scheme. When a customer bought a license, my keygen tool would take their email and hardware ID, run them through SHA-256 with a secret, and output a serial key. The installed app would do the same computation on first activation and compare — if the keys matched, license valid.
The secret: "WIS_2024_SECRET_KEY_TAQI". Hardcoded. In license_system.py. Inside the compiled .exe that every customer downloads.
PyInstaller-packaged executables are not obfuscated. Anyone with pyinstxtractor can extract the Python source in 30 seconds. Once they have the secret, they can generate valid keys for any email plus hardware ID combination — forever, without ever paying.
How I missed it
Honestly? I built the licensing early in the project when I was not thinking about scale. One-person shop, small sales, who is going to bother reverse-engineering a $49.99 tool? That logic works until one copy gets shared on a keygen forum and suddenly you have 5,000 "customers" who paid zero.
During a code review I asked exactly the kind of question I should have asked myself earlier: "if one copy of this leaks, how bad is it?" The answer was "catastrophic", so it became the first thing to fix.
The fix: server-side generation
The signing secret now lives only on webironshield.com. When a payment webhook fires, the server (not the client) generates the serial key using the secret. The secret never leaves the server, never gets shipped, never appears in any binary.
Two PHP endpoints do the work:
/api/generate_license.php (admin-only, mints keys)
/api/verify_license.php (public, validates keys)
The admin endpoint is protected by a separate admin token (different from the signing secret). Only my internal ordering system knows the admin token, so even if someone finds the endpoint URL they cannot generate keys without the token.
Verification flow
Before: client computes the expected key locally, compares.
After: client sends email plus hardware ID plus serial to the verify endpoint. The server re-computes the expected key using the server-side secret. It responds valid or invalid.
For the offline-use case (travelling, no internet), the client caches a successful verification for 14 days. If the server is unreachable after that, the client keeps working — network problems do not lock out paying customers. It just re-verifies when possible.
Trade-offs
The main cost is that first-time activation now requires internet. That is fine — you are buying it on the website, you have internet. The other cost is that I need to keep the verification endpoint alive forever. But it is a 2 KB PHP file with no dependencies, so "forever" is extremely cheap.
The benefit is that the cost of a leaked .exe drops from "catastrophic" to "someone might have one pirated copy until they activate it" — and the server-side verification blocks activation for non-matching keys.
The broader lesson
If you are building a licensed product with offline activation: assume every bit of logic and every constant you ship will be read by a determined attacker. That is what "running on someone else's computer" means. The only trustworthy secrets are the ones that never leave your infrastructure.
This applies beyond licensing:
- API keys for paid services? Do not ship them — put a proxy endpoint on your server.
- Algorithm details you want to hide? They are not hidden if the code runs client-side.
- Feature flags? Client flags are UX hints, not security boundaries. The server must re-check.
Migration for existing customers
Existing v2.6 customers had keys generated with the OLD secret. Those keys will not match the new server's secret, so they would show as invalid after upgrading. The fix was a 30-day transition period where the verify endpoint accepts either secret. After 30 days, I will drop the old secret and anyone still on v2.6 will need to request a new key (free, auto-issued on request).
Scan your site for free
Download Web Iron Shield and run your first vulnerability scan in minutes.