How can I add license to my C# desktop application? I need to find a suitable free method to prevent unauthorised users installing my software.
A category C license allows drivers to drive vehicles over 3.5 tonnes, but must not exceed 32 tonnes. Category C license typically covers a vehicle with a cab and trailer fixed permanently together.
A Class C license is a basic license and the class most private citizens have. Despite this, it affords many driving privileges. A Class C license allows the holder to drive two-axel vehicle under 26,000, a vehicle towing a trailer or semitrailer, a housecar and three-axel vehicles less than 6,000 pounds.
'C1 and 'C' licences If the vehicle has a MAM between 3.5 tonnes and 7.5 tonnes then a category 'C1' LGV driving licence is needed, however, if the (MAM) is more than 7.5 tonnes then a category 'C' LGV driving licence is needed.
I'm probably a bit late, but I spent a bit of time trying to work out a quick and effective method of securing a little C# application, and I would like to share my results.
It seems you can build your own, fairly secure licensing system using RSA reasonably easily.
Obviously, nothing is bullet-proof when it comes to protecting software (It's like protecting your house from burglars: alarms, barking dogs and fences make it more trouble than it's worth, but they won't stop someone determined to get in)
So, making it more trouble than it's worth is the key phrase in software protection: if you are offering a $1,000,000 E.R.P. system, you would want to have really good protection that authorized via a web-service (and users paying that much for a system would not have a problem with allowing that system constant internet access)
However, if you are charging only $5-$30 for a little app, users are not going to put up with very heavy handed authorization.
I think the simplest system to produce is to digitally sign a license-file that contains the details of product, the user and it's duration.
This means any modification of the license file makes the digital signature invalid.
The digital signature can be obtained from the DSACryptoServiceProvider class, using the SignData method.
A private key is required to sign the data, and the public part of that key can be used to validate the signature: (thus the public key must be accessible by the application)
The DSAXCryptoServiceProvider has methods for creating and using keys:
DSACryptoServiceProvider.ToXMLString(bool includePrivate);
returns the Public or Public & Private keys currently in the service provider as an XML string.
DSACryptoServiceProvider.FromXMLString(String xmlString)
This method sets up a new DSACryptoServiceProvider with existing private or public keys obtained from DSACryptoServiceProvider.ToXMLString()
The only flaw in the security of this system would be the possibility of a user breaking in an supplying their own public-key. This would allow them to generate their own license files from their own private-key.
This can be gotten around by additionally signing a required resource for the application (like a .dll that contains essential logic for the application, or even the .exe itself) - thus if the public key is changed, this additional (hidden) signature will become invalid.
Other ways to improve this include obscuring the license terms (serializing a data-structure containing the license terms using the binary-formatter to a byte array, then using Convert.ToBase64String() will quite effectively obscure the licensing terms, and even if the user was able to replace the public-key they would still need to work out the representation of the data)
I have an example system I wrote, but it is too big to quote entirely, but this is the CreateLicense method from it:
/// <summary> /// use a private key to generate a secure license file. the private key must match the public key accessible to /// the system validating the license. /// </summary> /// <param name="start">applicable start date for the license file.</param> /// <param name="end">applicable end date for the license file</param> /// <param name="productName">applicable product name</param> /// <param name="userName">user-name</param> /// <param name="privateKey">the private key (in XML form)</param> /// <returns>secure, public license, validated with the public part of the key</returns> public static License CreateLicense(DateTime start, DateTime end, String productName, String userName, String privateKey) { // create the licence terms: LicenseTerms terms = new LicenseTerms() { StartDate = start, EndDate = end, ProductName = productName, UserName = userName }; // create the crypto-service provider: DSACryptoServiceProvider dsa = new DSACryptoServiceProvider(); // setup the dsa from the private key: dsa.FromXmlString(privateKey); // get the byte-array of the licence terms: byte[] license = terms.GetLicenseData(); // get the signature: byte[] signature = dsa.SignData(license); // now create the license object: return new License() { LicenseTerms = Convert.ToBase64String(license), Signature = Convert.ToBase64String(signature) }; }
Verify Method:
/// <summary> /// validate license file and return the license terms. /// </summary> /// <param name="license"></param> /// <param name="publicKey"></param> /// <returns></returns> internal static LicenseTerms GetValidTerms(License license, String publicKey) { // create the crypto-service provider: DSACryptoServiceProvider dsa = new DSACryptoServiceProvider(); // setup the provider from the public key: dsa.FromXmlString(publicKey); // get the license terms data: byte[] terms = Convert.FromBase64String(license.LicenseTerms); // get the signature data: byte[] signature = Convert.FromBase64String(license.Signature); // verify that the license-terms match the signature data if (dsa.VerifyData(terms, signature)) return LicenseTerms.FromString(license.LicenseTerms); else throw new SecurityException("Signature Not Verified!"); }
The License Terms Class:
/// <summary> /// terms of the license agreement: it's not encrypted (but is obscured) /// </summary> [Serializable] internal class LicenseTerms { /// <summary> /// start date of the license agreement. /// </summary> public DateTime StartDate { get; set; } /// <summary> /// registered user name for the license agreement. /// </summary> public String UserName { get; set; } /// <summary> /// the assembly name of the product that is licensed. /// </summary> public String ProductName { get; set; } /// <summary> /// the last date on which the software can be used on this license. /// </summary> public DateTime EndDate { get; set; } /// <summary> /// returns the license terms as an obscure (not human readable) string. /// </summary> /// <returns></returns> public String GetLicenseString() { using (MemoryStream ms = new MemoryStream()) { // create a binary formatter: BinaryFormatter bnfmt = new BinaryFormatter(); // serialize the data to the memory-steam; bnfmt.Serialize(ms, this); // return a base64 string representation of the binary data: return Convert.ToBase64String(ms.GetBuffer()); } } /// <summary> /// returns a binary representation of the license terms. /// </summary> /// <returns></returns> public byte[] GetLicenseData() { using (MemoryStream ms = new MemoryStream()) { // create a binary formatter: BinaryFormatter bnfmt = new BinaryFormatter(); // serialize the data to the memory-steam; bnfmt.Serialize(ms, this); // return a base64 string representation of the binary data: return ms.GetBuffer(); } } /// <summary> /// create a new license-terms object from a string-representation of the binary /// serialization of the licence-terms. /// </summary> /// <param name="licenseTerms"></param> /// <returns></returns> internal static LicenseTerms FromString(String licenseTerms) { using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(licenseTerms))) { // create a binary formatter: BinaryFormatter bnfmt = new BinaryFormatter(); // serialize the data to the memory-steam; object value = bnfmt.Deserialize(ms); if (value is LicenseTerms) return (LicenseTerms)value; else throw new ApplicationException("Invalid Type!"); } } }
There are plenty of license management systems out there for .NET (there's even one built-in for licensing controls). A quick Google around for ".NET licence manager" threw up the Open License system, which is free.
I expect you can easily find more.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With