Select programming language for code examples

linkSecurity

Below you will find various security tips you may find useful.

linkSecret API Tokens

If one of your admin API tokens become compromised, you can quickly revoke it from your admin dashboard.

In Client-facing Software

Do not embed your admin, environment or product API tokens within client- or end-user-facing code. If you're using Keygen client-side, do not embed your admin, environment or product tokens within your product's source code. Doing so exposes your tokens and opens your account up to attackers, regardless of how obfuscated the token is.

Instead, you can perform license and machine creation requests client-side while authenticated as one of your users, or by using a license token which belongs to the license you're activating a machine for.

If you're using Keygen server-side, keep your secret API tokens safe.

In Version Control

We recommend that you do not store your API tokens in version control. It is recommended that you store tokens in an environment file that is never checked into the repository, or directly within the ENV on non-public devices.

linkPublic IDs and Keys

Embedding account, product and policy IDs directly into your product i.e. client-side code is perfectly safe. Inlining your public key is also perfect safe. In fact, you won't be able to communicate with Keygen's API or verify signatures unless you include some of these values. For example, your account ID is required so Keygen's API can route the request to the correct account, and a product ID would be required for automatic upgrades.

With that in mind, it is recommended that you use your account ID over your account slug, as unlike your account slug, your ID is unchangeable.

Resource IDs are standard v4 UUIDs, resembling the following format:

1fddcec8-8dd3-4d8d-9b16-215cac0f9b52

An account's RSA public key will resemble the following:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzPAseDYupK78ZUaSbGw7
YyUCCeKo/1XqTACOcmTTHHGgeHacLK2j9UrbTlhW5h8Vyo0iUEHrY1Kgf4wwiGgF
h0Yc+oDWDhq1bIertI03AE420LbpUf6OTioX+nY0EInxXF3J7aAdx/R/nYgRJrLZ
9ATWaQVSgf3vtxCtCwUeKxKZI41GA/9KHTcCmd3BryAQ1piYPr+qrEGf2NDJgr3W
vVrMtnjeoordAaCTyYKtfm56WGXeXr43dfdejBuIkI5kqSzwVyoxhnjE/Rj6xks8
ffH+dkAPNwm0IpxXJerybjmPWyv7iyXEUN8CKG+6430D7NoYHp/c991ZHQBUs59g
vwIDAQAB
-----END PUBLIC KEY-----

An account's Ed25519 public key will be hex-encoded:

e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788

linkAccount Permissions

If you do not want your users to be able to create and manage their own licenses and machines (which could necessitate listening for webhook events) then you should set your account to protected, which require admin authentication to create user and license resources.

Setting your account to protected can be done within your account settings.

Alternatively, you can set individual licenses policies to protected (which by default is inherited from the account's current protected state), which will only disallow users from creating and managing licenses which implement that particular policy and their associated machines, rather than all resources. For example public user creation would still be enabled, but license creation would be blocked.

You can also set a license to protected, which will disallow a user to activate/deactivate their machines. Similarly to policies, the license's protected attribute is inherited from its policy.

By default, your account is unprotected, which allows user registration as well as the ability for users to manage their own resources.

linkValidation Permissions

If you only need to validate license keys, then you do not need to implement user creation or authentication. The license validate-key action does not require authentication. If you're doing anything else e.g. validating multiple license resources per-user, tracking machines, etc., a form of API authentication will be required in order to perform these API operations client-side.

You can add required validation "scopes" to your policies to, for example, require a machine fingerprint parameter. This helps implement certain license models without the need for any additional validation logic.

linkCrack Prevention

Although all applications are susceptible to cracking (given enough motivation), there are certain things you can do to make cracking harder. Even applications written in a compiled language, such as C, are susceptible to software cracking.

Efforts beyond the prevention measures below have diminishing returns for most software products and time is better spent on legitimate users. Reach out to [email protected] if you need additional anti-cracking measures, we'd be happy to chat with you.

Checksum verification

To help prevent against tampering of application code, you can utilize checksum assertions during license verifications. By hashing an application during release, and hashing the same application during runtime, you can assert that the two checksums match, proving that the end-user has not modified application binaries or code. If there's a mismatch, the application has been modified.

In order to use checksum verification, you need to use Keygen for distribution.

Signature Verification

To help prevent tampering and defend against other attack vectors such as a man-in-the-middle attack, or proxy and replay attacks, you may choose to implement license key signature verification, and response signature verification. Both of these verifications harden your software by ensuring the given data originated from Keygen and that the values have not been modified.

The easiest one of those to implement is response signature verification, which can also be used offline with license validation caching.

User Agent Header

We recommend that you supply a custom User-Agent header with all API requests from your software application. You should include your organization name, the application's name, the running version number of the application, the operating system name, in addition to any other information you may find valuable.

Application-Name/1.33.7 (Org-Name) darwin/10.15.5 (macOS Catalina) Apache-HttpClient/4.5.5 (Java/1.8.0_201)

We will use this value to automatically detect certain crack attempts. We will notify you of all findings and help you secure your application.

We are currently running a 'pilot' for an AI/ML crack detection product. If this is something your organization is interested in, please reach out to us: [email protected]. We'd love to see if you're a good fit.

linkClock Tampering

Protecting your application's licensing system from an end-user changing their local system time, or "clock tampering", for an offline device can be a tough battle. As you could imagine, it's a hard problem. Since the device is offline, there's not much one can do to prevent tampering or "spoofing" the device itself to have its clock be in the past because whatever the device says is the time, frankly, is the time.

There's no concept of a "correct" time for an offline device, since it can't sync to an NTP server to get the real world time. What it has is correct, at least to the device itself, and as such, it's correct for other uses as well, like licensing.

To properly defend against system clock tampering, you would need to periodically validate the license using our API. We don't offer anti-clock-manipulation tools for offline use — that would need to be handled outside of Keygen in your own application code.

In general, defending against system clock tampering is a tough problem — much like defending against other types of cracking/tampering — because it's relying on an "untrusted" value of the system — the clock.

We've seen companies occasionally write an inconspicuous config or log file to disk and then periodically check the file's created (and modified) timestamps to loosely keep track of the clock, updating the modified at value each time the file is checked. If a timestamp for the file is ever in the future more than a couple hours (to account for daylight savings time), then it may be safe to assume that the clock has been tampered with. You can also do the same by writing a timestamp to a secure system registry, for example.

Alternatively, a simpler solution would be to always ensure that the system clock is at least greater than the license's created timestamp. Or even more simply: require your software be periodically connected to the internet to fully revalidate via the API.

No offline-only solution will be 100% effective. When it comes to a licensing implementation, the only thing you can fully "trust" is our API, which is verifiable using cryptographic signatures. Everything else should be considered untrusted.

As such, the only way to know if a license is truly valid is to validate the key using our API, because our API is the only trusted source for this information.