I am looking for guidance on creating a system that will allow me to lock my programs and put them in trial mode. The part I want guidance with is the algorithm to create/check the keys, do you guys have any suggestions on what it should be like? I am using c#.

- 63,008
- 17
- 141
- 172

- 287
- 1
- 6
- 11
-
3don't have an answer to suggest... but an advice, never forget that no protection is invulnerable. You should spent more time to create a good application, that makes customer want to buy, than trying to protect too much. Keep thinks simple and accept the truth, you will be cracked. – Steve B May 03 '12 at 13:01
-
possible duplicate of [Licensing System for .NET](http://stackoverflow.com/questions/5132943/licensing-system-for-net) – user7116 May 03 '12 at 13:07
3 Answers
Well the best way would be to implement your own socket protocol that is really hardcoded so the hackers is unable to decode it and you should constantly change it. Also to check the license you should just contact your socket server and the socket server could simply contact a database and check if the key is valid or not.
This is how I would do it and it can be implemented kinda easy

- 152
- 1
- 3
- 13
You are forgetting that there are tools like dotPeek, JustDecompile or .NET Reflector which can easily disassemble your application into source code. Your protection could easily be removed. There are many similar threads here on SO that deal with obfuscation, serial numbers, etc. Here are two links about code obfuscation.
https://stackoverflow.com/questions/1988451/net-obfuscation
Alternative for Obfuscation in the .NET world
Honestly, you will spend a lot of time on protection which could end up as a waste of time. This is unfortunated but it is reality.
Re-post from : Generating a serial number for product activation
Basically - once the software is on someone elses computer, they have the ability to modify the software as much as they like and you cannot stop them, short of legal action, proving the disassembly and enforcing legal penalties.
If you really wanted to protect functionality, you would keep the secure functionality online, and invoke it through Web Services. That way they are forced to pay, to use your Web Service. If however, you want to find a way of generating serial keys. Below is a post I did describing a way of generating 'difficult' serial keys, which take a long time to make, but a small amount of time to verify. Using this sort of algorithm, you can pre-generate serial keys in a database, then dish them out to customers. The only problem is that once again - someone could disassemble your application and just remove the licensing part of the code. I would instead make it so that the user has to have a valid serial key, in order to download the software, and download any and all updates. This would provide incentives to be a legal and legitimate customer. So, examples of how you could use these serials would be the following: You generate 100 serial combinations with the below code. Save them, and then sell them to customers. Give them the Serial Code, the Product Key (the number).
Then when it comes to activation, they enter it into your website, and then the website sends them the software.
Your website takes the serial key, the product key that they enter, and combines it with a secret code phrase for the software. (Alpha in the example below) If the 3 parts joint together generates a SHA256 hash of appropriate strength/difficulty, then it will consider it a successful registration. Further more, you can check against a database of users to see if that serial is matched to the relevant customer. If you wanted to get really secure, you could create a launcher application that downloads the binaries for your product and load them via Assembly.Load after successfully validating the serial key. Anyway - the re-post is now starting.
Repost:
With serial keys you need to consider a few things.
I have seen links during my hunts that point to using a simple Guid.NewGuid(); approach and then doing some transformations on the string to make a custom styled Serial key. This is easy to do, but puts the onus on you the product owner to keep track of serial keys in a database and at the end of the day there is potential for someone to randomly find serials that work via using Guid.NewGuid(); themselves. If everyone on the planet started generating Guids at the same time, collision chances become very likely.
There is a sort of solution that makes collision events less likely by using a more complex algorithm on top of Guid.NewGuid();
For this, I tend to use:
- Guid.NewGuid(); (First 16 characters only, minus the - (hyphen)
- An ever incrementing or changing value. (Nonce) (an int will work : i++ etc)
- A secret salt that you will keep private and secure in your network.
- A difficulty factor : borrowing this principle from bitcoin.
Ok, lets imagine I am taking the first 16 digits from a guid. I then combine that with the Nonce and the secret salt, then use SHA256 to derive a hash from the values. I can then use the Difficulty factor to determine if the hash begins with the amount of 0's or other character that I desire.
Eg: If the hash has six 0's prefixing it, then I save all of the data off, as I have just found a reasonably secure Serial key.
When I mean secure, I mean I have found a Serial, that when combined with a Product Key (the Nonce) and then used with the secret Salt, it results in a Hash that meets my production criteria.
Some example code is below - done very rough, because I was bored.
The idea would be that your application could send the product key and serial to an activation server. The server knows the secret salt. It then returns true or false to determine if the hash generated meets the security requirement. If it does not : the Serial is not valid, or not valid for the key provided. If it does have the required 0's : its a valid serial.
Guid theGuid;
string Hash = "";
int iAccess = 0;
string PrivateSalt = "Alpha";
string SourceString = "";
string guidString;
while (true)
{
theGuid = Guid.NewGuid();
guidString = theGuid.ToString().Replace("-", "").Substring(0,16);
SourceString = guidString + "|" + iAccess.ToString() + "|" + PrivateSalt;
byte[] data = Encoding.Default.GetBytes(SourceString);
Hash = Crypto.GenerateSHA256(data);
if (Hash.StartsWith(GetDiff()))
{
break;
}
iAccess++;
}
Console.WriteLine(SourceString+" Gives hash "+Hash);
string s1, s2, s3, s4;
s1 = guidString.Substring(0, 4);
s2 = guidString.Substring(4, 4);
s3 = guidString.Substring(8, 4);
s4 = guidString.Substring(12, 4);
string serial = s1 + "-" + s2 + "-" + s3 + "-" + s4;
Console.WriteLine(serial + " :" + SourceString + " Gives hash " + Hash);
GetDiff() is basically just a string : "000000";
Example output from this method looks like this:
d9c9-f6f0-45be-427a :d9c9f6f045be427a|15135|Alpha Gives hash 000000f718f69c8389d496e01d1e992946fe1b8cf72bc4200a7a2b800b40aa0a
fe49-70b9-08d8-40df :fe4970b908d840df|9096414|Alpha Gives hash 000000e29cfccfb54d1e7edc816feb084f1a2cd11a20c3132a965f9048fc9bf4
7f58-0636-c853-4f0a :7f580636c8534f0a|12297217|Alpha Gives hash 0000007bb44f39a964bbe985885451c3dc0e037fcd12951261404e48819bf89b
6f65-82d3-d95b-4882 :6f6582d3d95b4882|15064854|Alpha Gives hash 000000f1a3bed79e441108cfd26d8733d3fc10f5cd66d234ed35fe2b769663a3
edee-b8b7-9f6f-40ab :edeeb8b79f6f40ab|17782415|Alpha Gives hash 000000b70b96e7b008a96a860efc572fe868154ae81e67b9397249a51f2db71c
0948-4bb3-7de4-4054 :09484bb37de44054|21105690|Alpha Gives hash 000000ec7317eccd5fd9bb701759a2b0e77d37099347d9d665f4b492a69ca3ec
bbf5-5119-bf4e-463c :bbf55119bf4e463c|21715642|Alpha Gives hash 000000a134c886d01606da83cd5e8f672fddb6aa061968e9f08202c781514b16
80f6-c9c5-0ddf-436d :80f6c9c50ddf436d|26450310|Alpha Gives hash 00000092305b2956381c23dacba5b8ff9a37ab994148b37677732dc2a0650386
0a4f-143b-b5f5-48ca :0a4f143bb5f548ca|33691865|Alpha Gives hash 00000054ecdae57c6ec686b6084faf68ae49a78f7c07bbe8e51357d76de63870
You can increase the difficulty by adding more 0's to the prefix. It means that finding serial combinations will take longer, but also makes it more secure.
Obviously you would store these data combinations away somewhere so during activation, you can compare the Serial Code, and the Product Key (Nonce).
In my example: I am using Serial Key (16 digits), Incrementing int, and the word Alpha for the secret salt.
This makes generating serial keys slow and cpu intensive, but makes validating them very fast.
IsSerialValid("edee-b8b7-9f6f-40ab", 17782415);
public bool IsSerialValid(string serialCode, int ProductCode)
{
string SourceString = serialCode.Replace("-", "") + "|" + ProductCode.ToString() + "|" + "Alpha";
byte[] data = Encoding.Default.GetBytes(SourceString);
string Hash = Crypto.GenerateSHA256(data);
if (Hash.StartsWith(GetDiff()))
{
return true;
}
return false;
}
The secret Salt could be a code phrase that maps to different products that you may be developing. This allows you to re-use product keys (Nonce) values across multiple product lines.