Generic License Generation and Validation

// May 19th, 2011 // Useful Code

This was thrown together to see how quickly I could come up with something simple to allow for offline license validation. Up until now I previously used an online system. As well as this works it requires that the user access the internet in order to validate the key (which opens itself to traffic sniffing and server simulation in order to hack). This is by no means a perfect system but it should stump people long enough that they will feel better off just buying a key.

//Code To Generate A License Key


/// <summary>
/// GENERATE A UNIQUE KEY THAT CAN BE REVERESED TO VALIDATE WITHOUT INTERNET CONNECTION
/// </summary>
/// <param name="AppID">APPLIATION GUID THE KEY SHOULD BE GERNEATED FOR</param>
/// <returns>STRING VALUE REPRESENTING A VALID KEY</returns>
static string GenerateKey(string AppID)
{
    int curSegment = 1;
    string newLicense = "";
    string License = new string(Guid.NewGuid().ToString().Replace("-", "").ToUpper().ToCharArray().Take(12).ToArray());

    //GENERATE 4 BYTE SEGMENTS WHICH ARE [HASH,HASH][KEY,KEY]
    //VALUES ARE TAKEN FROM THE HASH AT A MATHIMATICALLY COMPUTED LOCATION [(FIRST CHAR ASCII VALUE + SEGMENT) % 32] TO MAKE IT DEPENDENT ON SEGMENT LOCATION AND VALUE
    //THIS SHOULD MAKE IT HARDER TO "GUESS" A KEY OR BRUTE FORCE ONE OUT OF THE SYSTEM
    foreach (Match tmpMatch in Regex.Matches(License, "[a-zA-Z0-9]{2}"))
        newLicense += (newLicense != "" ? "-" : "") + BitConverter.ToString(SHA256.Create().ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(tmpMatch.Value + AppID)).Skip((tmpMatch.Value.ToCharArray()[0] + curSegment++) % 32).Take(1).ToArray()).Replace("-", "") + tmpMatch.Value;

    //RETURN THE NEW LICENSE VALUE TO THE CALLING FUNCTION
    return newLicense;
}

//Code To Validate A License Key


/// <summary>
/// VALIDATES A KEY THAT HAS BEEN GENERATED FOR THE GIVEN APPLICATION ID
/// </summary>
/// <param name="AppID">APPLICATION THE KEY SHOULD BE VALIDATED AGAINST</param>
/// <param name="Key">UNIQUE KEY TO COMPARE AGAINST</param>
/// <returns>TRUE OR FALSE REPRESENTING THE VALIDATION OF THE GIVEN KEY AND APPLICATION ID</returns>
public static bool ValidateKey(string Key)
{
    try
    {
        int curSegment = 1;
        string[] segments = Key.ToUpper().Split(new char[] { '-' });
        string AppID = ((GuidAttribute)Assembly.GetCallingAssembly().GetCustomAttributes(typeof(GuidAttribute), false)[0]).Value;

        foreach (string segment in segments)
        {
            //SPLIT THE SEGMENT INTO HASH VALUE AND KEY VALUE
            string hashedValue = segment.Substring(0, 2);
            string keyValue = segment.Substring(2, 2);

            //COMPUTE THE HASH USING THE REVERSE ALGORITHM FROM CREATING A HASH
            string hash = BitConverter.ToString(SHA256.Create().ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(keyValue + AppID)).Skip((keyValue.ToCharArray()[0] + curSegment++) % 32).Take(1).ToArray());

            //IF THE HASH DOES NOT MATCH WHAT IS BELIEVED SHOULD BE A MATCH THEN DROP OUT BECAUSE THE KEY IS INVALID
            if (hash != hashedValue)
                return false;
        }

        //IF WE MADE IT THIS FAR THEN THE KEY IS VALID
        return true;
    }
    catch
    {
        //IF THERE WAS AN ERROR WHILE ATTEMPTING TO VALIDATE THEN THE KEY MUST BE INVALID
        return false;
    }
}
Be Sociable, Share!
  • RSS
  • Twitter
  • Facebook
  • LinkedIn
  • DeviantArt