Tuesday, February 07, 2006

In one of the comments to the post “Licensing classes in the SDF v2 (part 2)” a user asked a question about a way to tie up the license to the particular device and prevent coping licensed component or application between different user devices. This requirement would make the licensing process a little bit more complicated by adding a few more steps. It is driven by the fact that you will need to include the device id into the license key which later is signed with your private key. Evidently, you will have to add some code in your application that:


1. Will retrieve this device id (that's the easy part - just use the OpenNETCF.WindowsCE.DeviceManagement.GetDeviceid) and either automatically send it to your server or display it to the user.
2. Generate and sign the license that includes the device id with your private key.
3. Send this license to the user.
4. During validation of the license, retrieve the device id and include it into validation.

In order to utilize the Licensing library, you will need to create a new license provider by inheriting from the LicenseProvider class. Also you can either modify the .lic file by adding the DeviceID tag into the xml or append the device id to the contents of the .lic file during validation. If my schedule permits I'll try to add this implementation to the base library.

2/7/2006 2:11:21 PM (GMT Standard Time, UTC+00:00)  #     | 
 Thursday, January 26, 2006

In my previous post I showed you the class diagram and the usage for the Licensing classes that are available as a part of SDF v2.

Today I'll explain a few other steps that you will be required to do in order to have licensing enabled in your application.

Attentive readers had probably noticed from looking at the class diagram that I have provided implementation of a concrete class PublicKeyLicenseProvider that inherits from the abstract LicenseProvider. The internal implementation of the PublicKeyLicenseProvider class is based on the asymmetric encryption such as RSACryptoServiceProvider. This was made possible by the fact that Microsoft has provided the implementation of the System.Security.Cryptography namespace to the CF v2.

Little bit of the background information on the asymmetric encryption. Asymmetric Encryption is a form of encryption where keys come in pairs. What one encrypts, only the other can decrypt. Asymmetric Encryption is also known as Public Key Cryptography, since users typically create a matching key pair, and make one public while keeping the other secret.

This fact has brought me to the idea of possibility to implement an almost fool proof system for licensing of components and applications in the CF v2. Even considering an "openness" of the .NET assemblies through the tools like Reflector, as long as your private key will stay unknown to a possible hacker, they will have a little chance to break the encryption.

And now after you have digested this information, you should be able to understand the other steps that are required:

1. You will have to generate a pair of the Public and Private keys. I have created a class LicenseKeyGenerator to help you with this task. Here's the CreateKeyPair method that you can use on either Windows CE or a desktop to generate these keys:

public static void CreateKeyPair( string path, int keySize )

{

      RSACryptoServiceProvider rsa = new RSACryptoServiceProvider( keySize );

      // Open the file stream for writing of the public key

      FileStream keyWriter = new FileStream(Path.Combine(path, "Pub.key"), FileMode.Create);

      // Get the key from provider

      byte[] key1 = rsa.ExportCspBlob(false);

      //Write it to the file

      keyWriter.Write(key1, 0, key1.Length);

      keyWriter.Close();

 

      // Open the file stream for writing of the private key

      keyWriter = new FileStream(Path.Combine(path, "Priv.key"), FileMode.Create);

      // Get the key from provider

      byte[] key2 = rsa.ExportCspBlob(true);

      //Write it to the file

      keyWriter.Write(key2, 0, key2.Length);

      keyWriter.Close();

}

2. Add the generated public key file Pub.key to the root (this is very important) of your project and set its Build Action to the Embedded Resource.

3. Add the LicenseProviderAttribute to your component as I had already shown to you in the previouse post.

4. Generate the license file based on the user data. The license is a simple XML file in the following format:

<licenseKey version="1.0">

    <product version="1.0.3.2489">NewControlproduct>

    <customerInfo>

        <Name>John DoeName>

        <Email>john.doe@mail.comEmail>

    customerInfo>

    <key>f4/WgB2JhgR9bQibFa6rbGDugM+4wqbyM/ES+6W17gxx+x//G9at5he3yT0wZGwk2okSAzqrRJoNfsakEDMlFg==key>

licenseKey>

 

The value of the key tag is the public key that we have generated in the previouse step. Here is the method Generate from the LicenseKeyGenerator class:

public void Generate(string publicKeyFile, string licenseFile)

{

      //Open public key file

      FileStream fs = new FileStream(licenseFile, FileMode.Open);

      BinaryReader keyReader = new BinaryReader(fs);

      // Create encryptor

      RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();

      rsaProvider.ImportCspBlob(keyReader.ReadBytes((int)keyReader.BaseStream.Length));

 

      // sign and save.

      this.Sign(rsaProvider);

      this.Save(licenseFile);

}

And you will use it like so:

private void cmdGenerate_Click(object sender, EventArgs e)

{

       // Create new license key.

       LicenseKeyGenerator licenseKey = new LicenseKeyGenerator();

       licenseKey.ProductName = txtProduct.Text;

       licenseKey.ProductVersion = txtVersion.Text;

       licenseKey.CustomerName = txtCustName.Text;

       licenseKey.CustomerEmail = txtCustEmail.Text;

 

       licenseKey.Generate((Application.ExecutablePath) + @"\Keys\Priv.Key", "MyCompany.NewControl.lic");

}

You can download the full version for the LicenseKeyGenerator class and a sample project from here:

GenLicense.zip (23.81 KB)

After you are done with these steps, the result is simple and effective - you've got a licensing system in place that would be rather hard to brake and easy to use.

1/26/2006 1:52:45 PM (GMT Standard Time, UTC+00:00)  #     |