Generating a serial number for product activation

前端 未结 3 860
情书的邮戳
情书的邮戳 2021-02-09 05:27

First and foremost, this is not a question about generating a serial number for other products. I am not looking to \"hack\" other products.

Here are my

3条回答
  •  借酒劲吻你
    2021-02-09 05:45

    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:

    1. Guid.NewGuid(); (First 16 characters only, minus the - (hyphen)
    2. An ever incrementing or changing value. (Nonce) (an int will work : i++ etc)
    3. A secret salt that you will keep private and secure in your network.
    4. 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.

提交回复
热议问题