Using .NET build-in cryptography to RSA sign a software license

 “Do we really need that?”

Recently I was asked if I could add something like a software license key to an application. It should also be possible to create keys or “licenses” which would expire at a certain date.

For business I normally suggest to have a good customer relationship and have your usage terms on paper without an implementation of any checks or keys in the software itself. This way you do not start a fight between protecting and cracking your application and establish trust with your customer.
As said, this applies to business where you know your customers. On mass customer markets things are different.

Nevertheless, this was the requirement brought infront of me.

Solution: Sign your license contract

software-licenseFor the solution I decided not to go for a simple key and maybe name input. It would require to build some sort of algorhythm which would not only have to validate the key but also check if it has a expiration date or not. If the customer wants more protection attributes like license taker name, device id or more, things get even more complicated.

What works very well out there is to have a plain text license agreement which has the necessary information and could contain anything you would like:

SampleApp License
Name: Test User
Expires:

This is human readable and could easily be enhanced with more lines with more attributes. Sending the license to someone is as easy as to send a plain text email. Copy and paste from an email, a website or any other transfer is simple.

Of course – when you look at this, this is easily to fake. So we need some kind of validation, a secure hash. A hash which can be validated easily but generation is hard and limited to the license giver.

Implementation

Those of you familiar with cryptography will already know what I am after: Asynchronous cryptography to create a signature for the license with a private key which can be validated with a public key. This is not a new idea, it is one of the basic usages of RSA everywhere out there, like the certificates for secured web connections (HTTPS) many of you use for online banking.

So if we would sign our license, the complete license text could be:

SampleApp License
Name: Test User
Expires:
FJ7xBShqfMqJuvFKdCje6o3pLq7Y9pKC
O4D2BSl7vy9jvvUfG9WByEFTgdeSOYSB
QShfIs/4Jm3mErLmE0DElqgivRAmnKHO
09RA5B7neiP1KqJOxAfmEBIxMsV9PjhJ
tB7s9XQJdkkG1C582imwO/PCQI9hcbOC
mUxj71Iys2c=

The trick is: If you change any character here to change your expiration date, name or anything else (even in the hash) the license will be detected to be invalid. This works as the license generator uses a private key to generate the signature hash and your application uses a public key to validate that hash. There are some more things to consider to make this safe but that is the basic idea.

Does this look similar to you? Yeah, the whole thing is not a new idea to me, there is much software out there already using this kind of approach!

The implementation of RSA is quite old and well-known. It is based on prime factorisation like many cryptography algorithms today. And if you would like to do it in .NET, it is even build-in! Unfortunately the web lacks some well-documented example on how to generate a key-pair and how use it for signing and validating (and even encrypting and decrypting).

Use RSACryptoServiceProvider for key generation, import and export

So basically, we need to generate a RSACryptoServiceProvider. You can use the default constructor and import your RSA settings into the new object or create one with a new keypair with keys of the given size:

keypairNormally you would just create a keypair once and save it. That is one of two things the LicenseGenerator project in the example solution attached to this post does. How you save the key is up to you. The RSACryptoServiceProvider has a method ExportParameters which can give you a RSAParameters object with or without the private key. You can serialize that object in any way you would like or use ExportCspBlob/ImportCspBlob methods of the Provider. The sample solution uses JSON to save the key which is makes it most easy for you to take a look at the contents of the files.

Your license generator and your application should be completly seperated for obvious reasons. While the generator will require the private key (only you can generate licenses!) and the software will need the public key to validate the given licenses. You might want to embedded the keys as a resource or another way. The example solution only opens files to enable you (and me) to play around with the keys.

Sign your license

Let us now create a String containing our license text which has so be signed. In this sample we will also include a seed to make the hash more unpredictable and making cracking the app with exchanging the public key for your own one harder (not impossible!).

Now lets get the signature hash. You can decide which hash algorithm to use – here we use SHA256.

Print out the public license where we will not tell them our seed:

This is the text we can send to our license taker.

Validate the license in your app

Your application should have the license saved in its settings and validate it at least on startup. If there is an error or no license is present it should ask the user to enter (copy & paste) one.

When you have the license, extract your attributes (e.g. name, expiration date, etc.) and the hash into separate variables.

We will take these values and the seed to rebuild the text for the internal license and validate that one against the hash.

If you have additional attributes like an optional expiration date (nullable DateTime used here) you have to check that one as well.

There are many other considerations to make this really safe and get the crackers to have a hard job. Question is how to balance effort and outcome. It depends also on how many customers use your application and how trustworthy those are. But that is not the discussion here today. Basic recommendation here only include: Duplicate the important “constants” like hash algorhythm and seed. Make sure you only deliver the public key with your application.

Summary

Here we see that utilizing RSA signing only involves a few lines of code in .NET and some conversion to and from byte arrays. There is much you can do in addition to increase safety (sign your assembly, check NTP server, e.g.) and to increase user comfort (break the hash into multiple nice lines and put back together, trim whitespace, generate keys and validate in background threads). But the basic is just: Create CSP and generate keys or import them, sign some data, validate some data.

Note: This post and example can also be a start to use the .NET RSACryptoServiceProvider to implement encryption and decryption.

Download sample: RsaSigning Sample Solution (2 sample projects, one to generate keys and licenses, one to represent a protected application; both with simple WPF user interface powered by Caliburn.Micro; will require nuget package restore)

You may also like...

  • Victor

    Nice Information