Skip to content

License Generator

This Key Generator was built with the assistance of the article linked below (credit to Brandon Staggs).

Brandon Staggs article provided example in Delphi. Some functionality has been ported to C# to create this key generator.

How it works

To generate a licence key we essentially need two things:

  • A set of arbitrary 'key' bytes that are unique to the application that we want to protect. You are responsible for choosing a random set of bytes to use as your 'keys'
  • A seed that is unique to the context in which a key is being generated, e.g. 1 licence key for 1 user, or 1 licence key for 1 user application id combination.

Together, the seed and the byte keys will control the key that is produced. What is unique to this system, is that when verifying the licence key, you only test a subset of the total byte keys used to generate the full key. This means that the full set of key bytes used to create the licence key does not have to be included in the distributed software, and therefore it is harder to create a keygen to crack the keys you generate. An attacker does not have all the information to fully reverse engineer your key verification system.

With this system, We are able to vary the keys tested on new builds for published versions of your software, and you have the option of generating new byte key sets for new versions.

We can vary the number of byte keys used to make longer, stronger keys. Your validation code will need to know how many keys were used in the generation of a key.

Remember that no distributed software can be protected 100% against attackers. Whatever the technique used to generate a licence key system, all distributed software has the potential to be decompiled and modified to that licence key verification is skipped entirely. Depending on the context in which you distribute your software, you may need to employ obfuscation and other security techniques to make this less likely. Our system provides a simple programming interface, that helps to create a user friendly, attacker resistant means of implementing licence key functionality in your application.

Licence Key Generator

// Here in License Key Generator is the full set of KeyByteSet used to generate the licence key.
var keyByteSets = new[]
{
    new KeyByteSet(keyByteNumber: 1, keyByteA: 154, keyByteB: 19, keyByteC: 121),
    new KeyByteSet(keyByteNumber: 2, keyByteA: 29, keyByteB: 43, keyByteC: 23),
    new KeyByteSet(keyByteNumber: 3, keyByteA: 187, keyByteB: 116, keyByteC: 129),
    new KeyByteSet(keyByteNumber: 4, keyByteA: 55, keyByteB: 93, keyByteC: 46),
    new KeyByteSet(keyByteNumber: 5, keyByteA: 179, keyByteB: 234, keyByteC: 162),
    new KeyByteSet(keyByteNumber: 6, keyByteA: 203, keyByteB: 56, keyByteC: 49),
    new KeyByteSet(keyByteNumber: 7, keyByteA: 11, keyByteB: 199, keyByteC: 142),
    new KeyByteSet(keyByteNumber: 8, keyByteA: 6, keyByteB: 7, keyByteC: 222)
};

// A unique key is needed for the seed value. This value could be a module product id
int seed = new Random().Next(0, int.MaxValue);

// The values output can now be copied to `appsettings.secrets.json` of the service host layer
var key = keyGeneratorService.MakeKey(
  seed: seed,
  keyByteSets: keyByteSets
);

Licence Key Verification

// In your module that is to be distributed to the end user (which needs to verify the module license key), only include a subset of the full keyByteSets array used in License Key Generator.  
var keyByteSets = new[]
{
    new KeyByteSet(keyByteNumber: 1, keyByteA: 154, keyByteB: 19, keyByteC: 121),
    new KeyByteSet(keyByteNumber: 5, keyByteA: 179, keyByteB: 234, keyByteC: 162),
    new KeyByteSet(keyByteNumber: 8, keyByteA: 6, keyByteB: 7, keyByteC: 222)
};

// Read values from `appsettings.secrets.json`
var key = configuration.GetSection("OdmsModuleKey").Value;

var result = licenseChecker.VerifyKey(
    key: key?.Trim(),
    keyByteSetsToVerify: keyByteSets,
    // The TOTAL number of KeyByteSets used to generate the licence key in License Key Generator
    totalKeyByteSets: 8,
    // Add blacklisted seeds here if required (these could be module ids for example)
    blackListedSeeds: null
);

// If the key has been correctly copied, then the key should be reported as valid.
if(result != PkvKeyCheckResult.KeyIsValid)
{
    // Stop OnPreApplicationInitialization step
    throw new UserFriendlyException(
        message: $"{key} is not valid module key",
        code: "LicenseChecker:00001",
        logLevel: Microsoft.Extensions.Logging.LogLevel.Error
    );
}