Implementing software serial numbers

Say I wrote a program and want to distribute it among people. I want to be able to request a serial number from a user during installation, who will verify that they have a licensed copy of the software. In addition, I want the serial number to keep which version of the software they have, and when the license expires.

There are at least two conceptual ways I can come up with for this:

  • Create a series on the server where the user purchases the software and sends it by email. The software connects to the server during installation and activates the product. The server returns license privileges and expiration dates. The serial number does not have specific formats / mathematical rules, it is simply checked against the database on the server.

  • Create a serial number for the customer and send it by email. Series have some special mathematical properties that allow the program to check whether it is valid, which license it matches, and when it expires.

Mostly I'm interested in the second method. What methods are used when encoding this information in a serial number? If you could give a brief overview, that would be great. Otherwise, can you recommend some good books or websites that discuss this?

It seems strange to me that in all the years that I have encoded, I have never seen an implementation or description of these methods.

+4
source share
2 answers

Good, so two weeks unanswered. I am going to answer using a very simple method that I came up with to create relatively safe and scalable serial numbers using elementary methods.

As a mathematician, I’m pretty sure that there are several advanced methods for storing all kinds of information in a serial number, but I'm mostly interested in fast and high-quality files.

Here is considered naive, not mathematical, brute force:

Create a byte[] array containing the characters you want to use. You can use only hex, but there is no reason to limit yourself. Why not use the entire alphanumeric range minus '0' / 'O' and '1' / 'I' (for obvious reasons).

Then write the function as follows (example - C #):

 byte[] genRandomSerial(int length, byte[] characters, Random r) { var sn = new byte[length]; for (int i = 0; i < length; i++) sn[i] = characters[r.Next(0, characters.Length)]; return sn; } 

This will give you a random serial number that we don’t know is valid or not.

Further:

 int sum(byte[] sn, MD5 md5) { val = 0; foreach (byte b in md5.ComputeHash(sn)) val += (int)b; return val; } 

and then

 bool validate(byte[] sn, uint radix, uint expected, MD5 md5) { return (sum(sn, md5) % radix == expected); } 

Now we have a way of summing the 16-byte output of the MD5 hash function and evaluating whether the sum modulo n is equal to some x.

Now determine how many serial numbers you want to use. The more serial numbers there are, the easier it will be to randomly guess a valid combination.

Divide your random serial number into blocks. Let them say 5 blocks of 4, giving 20 characters in the form: ABCD-EFGH-IJKL-MNOP-QRST

Create 5 episodes from the serial number:

{A, B, C, D}, {E, F, G, H}, {I, J, K, L}, {M, N, O, P} and {Q, R, S, T}.

check if your 5 arrays are checked as follows:

 if (validate(block1, radix, expected, md5)) // This block is valid. 

If you set the radius to 2, then the probability that the block will be valid is 1/2. If you set radix to 10, then the probability of 1/10 will be valid. If you have 5 blocks, and each of them is 10, the probability that the entire sequence number will be valid is 0.1 ^ 5 = 0.00001. (In other words, 1 out of every 100,000 random series will be valid. This means that if you use the full alphanumeric range minus '0' / 'O', '1' / 'I', then you have (8 + 24 ) ^ n * 0.00001 = ~ 1.2 * 10 ^ 19 valid keys for serial length 20. That's a lot, but remember that you won’t find them all the same. The higher your raxis, the more secure the serial number will be, but the longer it will take for generation).

Note. The expected value should be somewhere between 0 and radix-1.

So, now we have a way to check a specific serial number as valid, but how can we store what type of series? In fact, we already have a way to do this. Accepting all the random (but verified) serial 'sn':

 int licenseType = sum(sn, md5) % 4; // Where 4 is the number of licenses you want to have if (licenseType == 0) { // Evaluation } else if (licenseType == 1) { // Standard } else if (licenseType == 2) { // Full } else // licenseType == 3 { // Unrestricted } 

The amount of each type of license is gradually equalized as you generate more and more keys.

If you want to store additional information in a key, such as an expiration date, you can use similar methods. For example, you can take the sum of odd characters modulo 12 to get an expiring month, and modulo 31 the sum of odd characters to give an expiring day.

The more of these restrictions and fakes you apply, the more time it will take to generate each type of key.

+1
source

What you are thinking about is basically creating your own licensing module. There is nothing wrong with that, and if you give up your own, it will be free (just your time to encode and debug it). However, it will be extremely easy to hack, so if you do this in order to get some kind of license compliance (for example, copy protection), I would not worry.

Are you going to somehow connect it to a physical machine? One way is to get the processor serial number, HD serial number, MAC address, etc. Or some combination of the above, hash them and use the hash to check at startup to make sure the license is valid. Of course, if the user changes something, the check will fail, and they may be annoyed that their software will no longer work, although they have a valid license.

If you do this to protect against illegal copying or use, the scheme that you offer is usually quite simple to crack - the cracker looks for where you check the correct license, and simply corrects the asm code to branch around it or always return positive. If your application is .NET, they can simply cancel the source code and remove the license verification part.

Disclaimer: I work for a license / copy management company ([Wibu-Systems]) 1 , and that’s all we do, so we know how easy it is to defeat most systems.

I would recommend one of three ways:

  • Leave your application unprotected and hope that your marketing of pirated copies is reasonable.
  • Reset a simple system, but note that if the s / w value matters, someone will quickly crack it. Get ready for some complicated coding and maintenance to make it even half decent.
  • Buy a commercial quality protection system such as CodeMeter , HASP, or KeyLok . Some of them are better than others (we believe that our best, of course), but no one is free.
+3
source

Source: https://habr.com/ru/post/1346863/


All Articles