How to Generate License Keys Securely
This article provides an insight on how to correctly generate uncrackable and flexible license keys, as well as what's going on behind the scenes of product activation. Strong product keys means less piracy and less lost revenue for a software publisher.
So what makes a good product key ?
- A third party must not be able to generate product keys even if it has full access to the software by reverse engineering, etc. If a software product is successful, it will be reverse engineered in a matter of days.
- License keys should be able to be "locked" on a specific computer, such that each license key can be used on only one computer.
- The generated product keys must small and readable
Securing Generated License Keys
When generating a product key, one of the biggest challenges is to ensure that the key was generated by the product publisher and not by an unwanted party like a pirated key generator. In offline scenarios (when the key cannot be validated over the Internet against a database of generated keys) the key must somehow carry within itself the proof that it is “authentic”.
An approach is to layout the key binary data like this:
KEY = KEY_DATA | ENCRYPTED(HASH(KEY_DATA))
In order to validate the key, the key data is hashed, and the encrypted hash is decrypted. If the computed data hash is identical to the decrypted data hash, it means that the key used to decrypt the data is the correct decryption key. Now this is where it starts to get interesting.
Using symmetrical encryption to secure product keys
Many software authors resort to using a symmetrical encryption algorithm for generating product keys, and validating the product keys using an encryption/decryption key that is “hidden” within their product. This means that once a malicious party obtains the symmetric encryption key by reverse engineering the software, they are able to create key generators. Aside from the financial losses due to piracy, this also leads to big logistical problems for the software publisher. It usually means changing the symmetrical encryption key and releasing a new version of the product which only works with the newer generated keys. Which in turn means many support calls from customers trying to enter a newly purchased product key into an old version of the product, etc.
Regarding this approach, it’s worth mentioning that not all the symmetrical encryption algorithms are suitable to use in encrypting product keys, because some of them product large encryption data sizes, which leads to unusably large product keys. AES for example is not a good approach because the block size has 128-256 bits so it’s too large. Blowfish is a good algorithm for this because the block size is 64 bits.
Using public key cryptography to Generate License Keys
A much better approach for ensuring the authenticity of the product keys is the use public key cryptography, like the well-known RSA. This uses different keys for encryption and decryption. In this approach, HASH(KEY_DATA) is encrypted using a secret key and concatenated with the key data. To validate the key, the ENRYPTED(HASH(KEY_DATA)) is decrypted using a public key embedded with the product. If the decrypted data matches the key’s data, it means that the key was encrypted (“signed”) with the private key which is only held by the product publisher and not hidden into the product. The public key cannot be used to encrypt, it can only be used for decryption, so this means that even if a malicious party knows this key, it cannot generate product keys.
So why doesn’t everyone use public key cryptography to secure their license keys ? The answer is that in public key cryptography, the digital signatures are very large. This means that the resulting product keys are very large, and no one would want a license key to be 200+ characters long.
However, some developers use license files, instead of product keys. A license file contains a very large product key, sometimes in binary form, sometimes encoded using Base64 or other encodings. WinRAR is such an example. When you buy the product you receive a license file instead of a product key. This approach has severe usability limitations though. You can’t spell the product key over the phone, you can’t print it on a sticker or on a DVD, you can’t easily give license keys to your resellers, etc.
Elliptic Curve Cryptography in License Key Generation
Elliptic Curve Cryptography (ECC) is an approach to public key cryptography based on the algebraic structure of elliptic curves over finite fields. It was invented in 1985 by Neal Koblitz and Victor S. Miller.
One of the key advantages of ECC over RSA is that the keys are very small and just as cryptographically strong as the larger RSA keys. When using digital signature algorithms using ECC, the signatures are much smaller compared to the RSA signatures, making this approach suitable for using to generate product keys.
One other important advantage of ECC is that there are many different valid signatures for the same data and signed with the same private key. This is of outmost importance, allowing to create many different keys without variating the input data via random salt values. This keeps the license keys small.
The disadvantages of this approach are the difficulty of implementation and some patents held by various companies (notably Certicom) regarding various ECC techniques. However, there are some ECC implementations unencumbered by patents, like ECC over GF(2^n) with a polynomial base representation. This approach, combined with the Schnorr digital signature algorithm (patent expired in 2008) is used in our library to generate small, secure product keys.
SoftActivate License Management SDK complies with the above guidelines and helps generate license keys that are secure and virtually uncrackable.
Enhancing Software License Management using License Activation
License activation ensures a better control over licensing by using a centralized activation server to "lock" eack license key to a specific computer. This can also be accomplished with public key cryptography and digital signatures.
So, How is it done ? First, a unique hardware id string is generated for each computer. This hardware id takes into account as many hardware components from the computer as possible, like network adapters, hard drives, processors, etc. This hardware id must be "change resistant", in that if a single hardware component is replaced, the hardware id still matches the computer. This prevents the need for new product activation at every litte change in the computer's hardware.
The product key (purchased with the product) is sent to the activation server together with the hardware id. These are included in an "activation data" message which is signed by the activation server and the signed activation data is then returned to the product. From that moment on, the product does not check the validity of the license key at startup, but the validity of the activation data. The validation of the activation data is done using the public key included in the product
and it consists of verifying the activation data signature with the public key included in the product, followed by the hardware id matching with the computer's hardware. An optional expiration period can be included in the activation data, and checked at product startup. This can be useful in implementing expiring licenses or subscription-based lincensing.
SoftActivate Licensing SDK has full suport for license activation, including an activation server included with full C#/.NET source code.
Making Generated Product Keys Readable
The string encoding of product keys should omit confusing characters like “O”, “o”, “0”, “I”, “1”, etc. Using such characters in the key encoding makes it very easy for the user to enter the wrong key and then call the technical support department complaining that the purchased key does not work. For the same reason, product keys should also be case-insensitive, if possible.
One possibility is to use a Base32-like encoding (each character encodes 5 bits) with the alphabet "ABCDEFGHJKLMNPQRSTUVWXYZ23456789".