Using SSH Keys for License generation and validation in .NET Applications


license_generationpng

This blog post is going to present how can you implement license functionality in your .NET application. Providing license in your .NET application is very challenging because there is no standard procedure for the implementation. You are free to use whatever you want. But be notice, there is no license which is 100% safe and cannot be cracked or bypassed.

For this purpose I have selected the CocoaFob library for registration code generation and verification in Objective-C applications. Mainly the library is for Objective -C based applications, like iQS mobile applications and other OSX based applications.  This is very interesting library but you cannot use it in .NET applications, there is no implementation for .NET Framework.

The library uses DSA to generate registration keys, which is very hard for hackers to produce key generators. The library is also specific because it generates license key in human readable form, when the bytes are converted in to Base32 string to avoid ambiguous characters. It also groups codes in sets of five characters separated by dashes. Also DSA has encryption algorithm generates the license which is different every time because of a random element introduced during the process.

So the License key is produced using a 512-bit DSA key looks like on the following sample:

GAWQE-FCUGU-7Z5JE-WEVRA-PSGEQ-Y25KX-9ZJQQ-GJTQC-CUAJL-ATBR9-WV887-8KAJM-QK7DT-EZHXJ-CR99C-A

More information about CocoaFob can be found at GitHub page: https://github.com/glebd/cocoafob

The library is using BouncyCastle.Crypto Nuget package for DSA encryption and decryption.

The library CocoaFob for .NET contains two classes:

  1. LicenseData class which provide License properties which is used in license generation. It an be anything: Name, Product number, email, date of expiration etc.
  2. LicenseGenerator  class which is responsible for encrypting and validating the license.

For this blog post the License data class has the flowing implementation:

public class LicenseData
{

protected internal string productCode;
protected internal string name;
protected internal string email;

public virtual string toLicenseStringData()
{
 StringBuilder result = new StringBuilder();
 if (productCode != null)
 {
 result.Append(productCode);
 result.Append(',');
 }

 //name is mandatory property
 if (name == null)
 throw new System.Exception("name cannot be null");
 result.Append(name);

 if (email != null)
 {
 result.Append(',');
 result.Append(email);
 }
 return result.ToString();
}
......
}

As can be seen from the code snippet above the License data contains username, product key and email address. Also, only name property is mandatory, which means you can generate license key based on the user name only.

Generating the License Key

One we have License data we can process of License key generation. License is generated using DSA encryption which uses SSH private key.  You can generate public and private SSH keys  using any of the available tools, eg. OpenSSH, GitHub bash, …. More information about private and public key generation you can find at this link. Once we have public and private keys we can generate license and validate it. One important thing to remember is that you have to care about your private key. It should always be secure and no one should have access to it.

The public key is used for license validation, and it is usualy packed with the application as a part of the deployment stuff. So the process of generating the license is show on the flowing code snippet:

public string makeLicense(LicenseData licenseData)
{
     if (!CanMakeLicenses)
     {
       throw new System.InvalidOperationException("The LicenseGenerator cannot make licenses as it was not configured with a private key");
     }
     try
     {
        //
        var dsa = SignerUtilities.GetSigner("SHA1withDSA");
        dsa.Init(true, privateKey);
        //
        string stringData = licenseData.toLicenseStringData();
        byte[] licBytes = Encoding.UTF8.GetBytes(stringData);
        dsa.BlockUpdate(licBytes, 0, licBytes.Length);
        //
        byte[] signed = dsa.GenerateSignature();
        string license = ToLicenseKey(signed);
        return license;
    }
    catch (Exception e)
    {
        throw new LicenseGeneratorException(e);
    }
}

First the DSA encryption is created based on the publicKey we have provided as an argument. Then licBytes is generated from the License data, and converted in to UTF8 formatted bytes. Then we have update DSA provider with licBytes. Now the DSA provider can generate signature in bytes. The signature is converted in to LicenseKey by calling ToLicenseKey method. The method is shown on the following code snippet:

private string ToLicenseKey(byte[] signature)
{
    /* base 32 encode the signature */
    var result = Base32.ToString(signature);

    /* replace O with 8 and I with 9 */
    result = result.Replace("O", "8").Replace("I", "9");

    /* remove padding if any. */
    result = result.Replace("=", "");
           

    /* chunk with dashes */
    result = split(result, 5);
    return result;
}

The magic happen in this method during the conversion of signature from bytes to human readable string. Conversion is done using Base32 string helper method.

Verify the License Key

The License verification process is defined in varifyLicense method. You have to provide SSH publicKey as well as

public virtual bool verifyLicense(LicenseData licenseData, string license)
{
	if (!CanVerifyLicenses)
	{
		throw new System.InvalidOperationException("The LicenseGenerator cannot verify licenses as it was not configured with a public key");
	}
    try
     {
        //Signature dsa = Signature.getInstance("SHA1withDSA", "SUN");
        var dsa = SignerUtilities.GetSigner("SHA1withDSA");
        dsa.Init(false, publicKey);

        //
        string stringData = licenseData.toLicenseStringData();
        byte[] msgBytes = Encoding.UTF8.GetBytes(stringData);
        dsa.BlockUpdate(msgBytes, 0, msgBytes.Length);


        var dec = FromLicenseKey(license);
        var retVal = dsa.VerifySignature(dec);
        //
        return retVal; 
	}
    catch (Exception e)
    {
        throw new LicenseGeneratorException(e);
    }
}

As can be seen from the code above, the validation process is done by generating licenseData, converting the license Key in to signatere and the validation process return true is the license is valid, otherwize return false.

The whole project is published at git hub, an can be downloaded from http://github.com/bhrnjica/cocoafob

 

Testing the Library

The Library solution contains unit test project which you can see how to use this library in the real scenario in order to implement licensing in .NET app.

Happy programming!

Advertisements

About Bahrudin Hrnjica

PhD in Mechanical Engineering, Microsoft MVP for .NET. Likes .NET, Math, Mechanical Engineering, Evolutionary Algorithms, Blogging.

Posted on 06/12/2016, in .NET, CodeProject, Windows and tagged , , , , , . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s