3
James Gregory Blog Archives GitHub RSS Rhino Licensing As one of the last things on my to-do list for Inca, licensing has been delayed and delayed; finally, with me making the announcement on Twitter the other day I felt I should probably get it sorted. I was going to write a nice long post about my thoughts on anti-piracy measures, but the Balsamiq team have already done it nicely . Instead, here’s a guide to using Rhino Licensing. Your mileage may vary. Rhino Licensing is an open-source licensing framework by Ayende Rahien, and it grew out of his frustration with other license providers while creating NHibernate Profiler . Rhino Licensing uses asymmetric encryption–also known as public-key cryptography–specifically the RSA algorithm. In cryptography, asymmetric means there are two parts to each key, one public and one private. You encrypt a value using the one key, and it can only be decrypted using the other key. In the case of license key generation, we store our private key on the server (and never tell anyone it!), and distribute the public key with our application. When the user receives a license key, the application is able to verify that it came from us by using the public key. If someone tries to use a license key they’ve generated themselves, it wouldn’t work unless they had our exact private key. Other systems that use asymmetric encryption include SSH, SSL, PGP, and among others, Git uses asymmetric encryption for its security due to it using SSH. The format of the license that Rhino Licensing generates is an XML document, plain and simple. By default, it includes the user’s name, an expiration date, the type of license (trial, standard, floating, etc…), and most importantly the cryptographic signature. Below is an example Rhino Licensing generated license. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?xml version="1.0" encoding="utf-8"?> <license id="ae4c05b5-c188-47f8-852f-b4e5375621f7" expiration="2011-01-01T00:00:00.0000000" type="Standard"> <name>Bilbo</name> <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> <SignedInfo> <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /> <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /> <Reference URI=""> <Transforms> <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <DigestValue>sKDT7gzgedzmh1AMxxLbfcF1Hsw=</DigestValue> </Reference> </SignedInfo> <SignatureValue> SfkvCGv1+EdLTvaROv27ymDumS0y02fPANTVhr0Yxd/ AxxVH0q0BQ6w8Ou5L7gyLYLvnSckgjhrGnGpiifdvbg== </SignatureValue> </Signature> </license> What’s a signature? A cryptographic signature is a string of bytes used to aid in verification of the source of a document. In most cases–and in the case of Rhino Licensing–the signature is generated by hashing the content of the file using SHA1 (or another suitable hashing algorithm), and encrypting that hash using the private key. The resulting string of bytes is the signature. When the client receives a file with a signature, it creates a hash of the file (sans-signature) and compares that hash Rhino Licensing - James Gregory http://www.jagregory.com/writings/rhino-licensing/ 1 de 3 09/05/2013 9:17

Rhino Licensing - James Gregory

Embed Size (px)

Citation preview

Page 1: Rhino Licensing - James Gregory

James GregoryBlogArchives

GitHub RSS

Rhino Licensing

As one of the last things on my to-do list for Inca, licensing has been delayed and delayed; finally, with me makingthe announcement on Twitter the other day I felt I should probably get it sorted. I was going to write a nice longpost about my thoughts on anti-piracy measures, but the Balsamiq team have already done it nicely.

Instead, here’s a guide to using Rhino Licensing. Your mileage may vary.

Rhino Licensing is an open-source licensing framework by Ayende Rahien, and it grew out of his frustration with other licenseproviders while creating NHibernate Profiler.

Rhino Licensing uses asymmetric encryption–also known as public-key cryptography–specifically the RSA algorithm. Incryptography, asymmetric means there are two parts to each key, one public and one private. You encrypt a value using the onekey, and it can only be decrypted using the other key. In the case of license key generation, we store our private key on theserver (and never tell anyone it!), and distribute the public key with our application. When the user receives a license key, theapplication is able to verify that it came from us by using the public key. If someone tries to use a license key they’ve generatedthemselves, it wouldn’t work unless they had our exact private key.

Other systems that use asymmetric encryption include SSH, SSL, PGP, and among others, Git uses asymmetricencryption for its security due to it using SSH.

The format of the license that Rhino Licensing generates is an XML document, plain and simple. By default, it includes theuser’s name, an expiration date, the type of license (trial, standard, floating, etc…), and most importantly the cryptographicsignature. Below is an example Rhino Licensing generated license.

1234567891011121314151617181920212223

<?xml version="1.0" encoding="utf-8"?><license id="ae4c05b5-c188-47f8-852f-b4e5375621f7" expiration="2011-01-01T00:00:00.0000000" type="Standard"> <name>Bilbo</name> <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> <SignedInfo> <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /> <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />

<Reference URI=""> <Transforms> <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <DigestValue>sKDT7gzgedzmh1AMxxLbfcF1Hsw=</DigestValue> </Reference> </SignedInfo> <SignatureValue> SfkvCGv1+EdLTvaROv27ymDumS0y02fPANTVhr0Yxd/ AxxVH0q0BQ6w8Ou5L7gyLYLvnSckgjhrGnGpiifdvbg== </SignatureValue> </Signature></license>

What’s a signature?

A cryptographic signature is a string of bytes used to aid in verification of the source of a document. In mostcases–and in the case of Rhino Licensing–the signature is generated by hashing the content of the file using SHA1(or another suitable hashing algorithm), and encrypting that hash using the private key. The resulting string of bytesis the signature.

When the client receives a file with a signature, it creates a hash of the file (sans-signature) and compares that hash

Rhino Licensing - James Gregory http://www.jagregory.com/writings/rhino-licensing/

1 de 3 09/05/2013 9:17

Page 2: Rhino Licensing - James Gregory

to the decrypted value of the signature. Baring in mind that the signature is an encrypted hash of the file, if either ofthe public or private keys were invalid or the file had been tampered with, then the decrypted string would notmatch the hash of the file. When the client generated hash and the decrypted signature match, you can be confidentthe sender of the message is who you think it is.

The great part about using the hash of the document as the signature is that if the user tampers with the license–such as changingthe expiration date or the licensee name–the signature will no longer match the hash the client generates, and BAM, instantinvalid license.

One particular aspect I like with this approach is that the licensee name is clearly visible in the license. This simpleact can be quite dissuasive when it comes to piracy; after all, who would want their name visible on all the torrentwebsites out there?

Enough with the waffle, let’s start using Rhino Licensing.

Create your key

The first thing we need to do is generate a public/private key pair for us to use in our license generation. Rhino Licensing usesthe RSACryptoServiceProvider for it’s keys, so we can use that ourselves to generate our keys. One of the simplest ways to dothat is to knock up a really quick console application.

12345678910111213

class Program{ static void Main(string[] args) { var rsa = new RSACryptoServiceProvider(1024);

File.WriteAllText("publicKey.xml", rsa.ToXmlString(false)); File.WriteAllText("privateKey.xml", rsa.ToXmlString(true));

Console.WriteLine("Done"); Console.ReadKey(); }}

That program will generate a new key for you and write out the public and private parts to two separate XML files(publicKey.xml and privateKey.xml). Keep these two files handy!

You will probably want to change the 1024 value in the RSACryptoServiceProvider constructor to somethinglarger. This is the size of the key that will be generated. The larger the better really, but larger numbers requirelonger to generate.

Update your application

Now we’ll update your application to complain if it doesn’t have a license. In your entry-point for your application you need toassert the license. Before we do that, make sure you’ve got your public key handy from the previous step. Rhino Licensingneeds the content of this file, so you can either embed it directly into a constant or as a resource. Secondly, it needs to knowwhere to look for a license that the user will have been given.

Assuming a really simple app, here’s a Program.cs with Rhino Licensing:

12345678910111213

class Program{ static void Main() { var publicKey = File.ReadAllText("publicKey.xml");

new LicenseValidator(publicKey, "license.xml") .AssertValidLicense();

Console.WriteLine("Hello"); Console.ReadKey(); }}

If the license.xml file doesn’t exist, or if it’s invalid, Rhino Licensing will throw an exception. Of course, as we haven’tgenerated a license yet we’ll get an exception. That’s the client done though, so we can move on to our final step now. Once wecomplete that step, you will be able to just drop a license.xml into the same directory as your application and everything will

Rhino Licensing - James Gregory http://www.jagregory.com/writings/rhino-licensing/

2 de 3 09/05/2013 9:17

Page 3: Rhino Licensing - James Gregory

Tweet 1

work as expected.

Create the license generator

We need something to actually generate a license for your users. If you were being all fancy you could do this as a web-servicethat gets integrated with your payment provider; however, for simplicity’s sake we’ll just create another console application thatspits out a license.

Rhino Licensing has a few prerequisites for a license: A name, an id of the license, an expiration date, and a license type. Youcan also supply a dictionary of custom values, but we wont be using that in this example.

For a really simple license generator all you need is the above for each license, and the private key. We’ll wrap that up in asimple console app which’ll prompt for the required info:

1234567891011121314151617181920212223242526

class Program{ static void Main(string[] args) { var privateKey = File.ReadAllText("privateKey.xml");

var id = Guid.NewGuid(); var generator = new LicenseGenerator(private_key);

Console.Write("Name: "); var name = Console.ReadLine();

Console.Write("Date: "); var expirationDate = DateTime.Parse(Console.ReadLine());

Console.Write("Type: "); LicenseType licenseType = (LicenseType)Enum.Parse(typeof(LicenseType), Console.ReadLine());

// generate the license var license = generator.Generate(name, id, expirationDate, licenseType);

Console.WriteLine(); Console.WriteLine(license); Console.ReadKey(); }}

That’s it, you’ve got a license generator. Remember, this will exist behind your firewall, the users will (and must) never see yourprivate key.

If you take the output of this application and save it in a license.xml file in your client, your application should stop throwinglicense exceptions and run normally! You’ve officially just licensed your app.

What have we just done?

Created a private key generator, purely for convenience than anything else. We should only need to run this once beforewe start generating our keys. You could run it once per major release to ensure your 1.0 licenses are never compatiblewith 2.0.Updated our client application to validate the presence and validity of a license (and to explode if there isn’t one).Created a “server” to generate licenses for us. This is very primitive but could easily be adapted to a web server. Youmight want to look at the Rhino Licensing LicensingService before you continue.

Jan 11th, 2011

Copyright © 2012 James Gregory

Rhino Licensing - James Gregory http://www.jagregory.com/writings/rhino-licensing/

3 de 3 09/05/2013 9:17