A License Generation and Verification System - Part I

Mar 17, 24

1) Intro


Recently, I’ve been working on a licensing mechanism that should work offline (client’s on-prem environment without internet access). This is an age-old problem, I remember variety of cracking methods & keygens in Windows OS and games. But hopefully, using the concepts I have learned in my cyber security masters degree, I came up with a solution. I want to share a simplified version of it.

In this post, I am roughly specifying the terms, requirements and ideas on the problem. In the future posts, I will share details on how & why we have implemented these in a particular way.

2) Problem


  • We have a product that shall be installed in on-prem environments and there can be no internet access after the installation
  • We want to control which features are enabled in customers according to the license keys that is provided by us
  • We need to do this as secure as possible (focusing specifically: confidentiality, integrity and non-repudiation)
  • Many month later, we may provide another license key to the customer and the verification mechanism should work just fine without an internet connection
  • Customers should not be able to generate their own license, inject it to our product or bypass the license feature checking mechanism anyhow

3) Defining some terms


  • License feature
    • the functionality we want to enable
    • fields such as: feature name, description, start date, expiry date, and other details (such as feature quota)
  • License document
    • a JSON formatted document including required information like start date, expiry date and enabled features
    • if a feature is not included in license document, then it is not enabled
  • License key
    • encrypted version of the license document
    • encryption is necessary to ensure that document is generated by us, not anyone else
    • as a side effect, encryption helps obscuring document details
  • License encryption/decryption key
    • a symmetric key that will be used during both encryption & decryption of the license document
  • License certificates
    • PEM formatted X.509 certificates for storing license decryption key
  • License verification mechanism
    • checking validity of license document and certificates
      • whether certificate chaining is correct and license can be decrypted
      • whether current date is within start-expiry date range of certificates,
    • checking whether current date is within start-expiry date range of license document,
    • checking whether a specific feature is in the license document
    • (optional) checking whether quota is sufficient for the specific feature
  • License feature check
    • checking whether a license feature is enabled & available in the license document

4) Requirements


A license document should be confidential (not in plaintext)

We need an encryption mechanism to ensure confidentiality

A license document should include necessary info

  • Client’s basic info (like company name)
  • Features enabled
  • Start and expiry dates
  • JSON format is good enough

A license document cannot be tampered (if so, it should be detected)

  • The system should accept only the documents/keys that are generated by us
  • Again we can use cryptography for checking license’s validity
  • Digital signatures are an option
  • Also since a plain-text license document is a simple JSON object, JWT comes to mind
  • A JWT can be verified easily with digital signatures

License verification mechanism cannot be bypassed

  • In other words, this is not a good idea: storing boolean fields in a Postgresql table, and using that to mark features as on or off
  • This is not a good idea either: decrypting the license key, storing the plain-text license document in database and using that plain-text version for license feature checks
    • Since the product is in customer’s own environment, they can access database tables and manipulate documents there
  • Ideally, everything should be verified every time we want to check whether a feature is allowed or not
    • Every time we do a license feature check, we should verify every part:
      • license key (to be decrypted and parsed as license document),
      • license certificates,
      • and whether a specific license feature is in the license document
    • In other words, we should only store encrypted data (license key) at rest. We should do decryption & other verifications in run-time
    • Here we are assuming that customers are not able to intercept and manipulate our product’s Linux processes in run-time

If customers share license keys between each other, the system should detect it

If customer A shares the encrypted license key to customer B, system should reject it in customer B’s environment. To implement this, each customer should have their own license encryption/decryption key


In the next blog posts, I will dive into the reasoning that led us to a particular solution.