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!

Advertisement

C# Implementation of the Finite Element method


I have just published the source code for Finite element method at GitHub. You can find it at https://github.com/bhrnjica/bhmke.

The project is at very beginign stage, and contains very few samples and implementation.

Currently you can solve simple plane load problem, and calculate node displacement.

The more code will be added soon.

The project will be Cross OS and Cross Platform, and will be complatible with .NET Core.

 

How to Install Windows 10 on Microsoft Azure


win10Azuresl00

It is great time Windows 10 is released and there are huge amount of hype everywhere on the internet. I am using Windows 10 from the beginning through the Insider program, and all I can say the Windows 10 is the greatest and the best OS ever made.
There are plenty of blog posts and articles about the Windows 10, and everybody who is using previous version of the Windows OS should upgrade to Windows 10. As soon as you upgrade you will see the difference and better experience in all aspects.
For this blog post I would show you how to install Windows 10 on Azure, and how to enable some of the great feature. So lets start.

1. First of all go to your Microsoft Azure Subscription Portal.

win10Azuresl0

2. Create New Azure Virtual Machine

win10Azuresl01

3. Start defining Virtual Machine Parameters  by defining OS version. Select Windows 10 Enterprise (x64)

win10Azuresl1

4. Define Virtual Machine Name, username, and password.

Note: This User name should not be developer username, because you have some restriction for Administrator when developing Windows Application. For this reason I have defined bhrnjica_admin user name. My developer username will be bhrnjica, which will be defined later.

win10Azuresl2

5. Define Cloud service name, DNS Name and Region. In this step it is also neccessery to open all port you will need. In my case I have opened the following port:

  • Remote Desktop – this is default without this port you are not able to connect to this machine.
  • PowerShell in case you are working on PowerShell.
  • MSSQL port if you are planning to install Microsoft SQL Server on this machine.
  • MySQL is you are planning to install MySQL server.

win10Azuresl3

6. The last step is to enable some components to be installed on the virtual machine. You have option to include some Antimalware software as well as some Virtual Machine Agent.

win10Azuresl4

7. After you click on the last OK button, wait some time (few minutes) and you should see the following status on you Microsoft Azure Portal.

win10Azuresl5

8. To connect to your created Windows 10 machine, click Connect button to download RDP connection (See picture above). Double click to downloaded RDP file, enter your credentials.

win10Azuresl6

9. Then you have your Windows 10 Azure Machine.

win10Azuresl7

 

10. Enjoy on your Windows 10 Azure Machine

How to manually fix content error in Microsoft Word


Word2013_error1

Today while I was editing a document suddenly Word crashed and the document became unable to be opened. Every time I wanted to open it the same error was:

We’re sorry. We can’t open DocumentName.docx because we found a problem with its contents.
When I want to see Details the following message shows:
Unspecified error
Location: Part: /word/document.xml, Line 2, Column: 0.

Then I wanted to open auto-saved version of the document, the same error appeared. So I changed the DocumentName.docx  file in to DocumentName.zip, and extract the content, found document.xml file and opened it in Notepad++.

The picture below shows the content of the DocumentName.docx file, renamed in to zip and extracted:

Word2013_error2

If you didn’t know the word document with doc or docx extension is actually zip file, which you can extract.

I have opened the docuemnt.xml and try to find error in second line. This was mission impossible because all xml content is placed in this line. As you can see on the picture below:

Word2013_error3

To find which element cause the content problem we have to format XML content. I prefer using Notepad++ and XML Tool PlugIn. It can be installed through Plungins menu of Notepad++.

Word2013_error4

To format xml content choose option Pretty print (XML only – with line breaks) . After the content is formatted, back the Document.xml to zip, change the extension from zip to docx, and open the word document.

The same error appear, but when you choose for details you can read in which line is the error. Find the line in Notepad++ and delete whole tag element:

Word2013_error7

Copy document.xml back in to zip file, rename the extension and try to open. If you have another error, repeat the process again, otherwise your document is opened.

Word2013_error8