Question

I built a web application that is going to launch a beta test soon. I would really like to hand out beta invites and keys that look nice.

i.e. A3E6-7C24-9876-235B

This is around 16 character, hexadecimal digits. It looks like the typical beta key you might see. My question is what is a standard way to generate something like this and make sure that it is unique and that it will not be easy for someone to guess a beta key and generate their own.

I have some ideas that would probably work for beta keys:

  • MD5 is secure enough for this, but it is long and ugly looking and could cause confusion between 0 and O, or 1 and l.
  • I could start off with a large hexadecimal number that is 16 digits in length. To prevent people from guessing what the next beta key might be increment the value by a random number each time. The range of numbers between 1111-1111-1111-1111 and eeee-eeee-eeee-eeee will have plenty of room to spare even if I am skipping large quantities of numbers.

I guess I am just wondering if there is a standard way for doing this that I am not finding with google. Is there a better way?

Was it helpful?

Solution

The canonical "unique identifying number" is a uuid. There are various forms - you can generate one from random numbers (version 4) or from a hash of some value (user's email + salt?) (versions 3 and 5), for example.

Libraries for java, python and a bunch more exist.

PS I have to add that when I read your question title I thought you were looking for something cool and different. You might consider using an "interesting" word list and combining words with hyphens to encode a number (based on hash of email + salt). That would be much more attractive imho: "your beta code is secret-wombat-cookie-ninja" (I'm sure I read an article describing an example, but I can't find it now).

OTHER TIPS

One way (C# but the code is simple enough to port to other languages):

private static readonly Random random = new Random(Guid.NewGuid().GetHashCode());

static void Main(string[] args)
{
    string x = GenerateBetaString();
}

public static string GenerateBetaString()
{
    const string alphabet = "ABCDEF0123456789";

    string x = GenerateRandomString(16, alphabet);

    return x.Substring(0, 4) + "-" + x.Substring(4, 4) + "-"
         + x.Substring(8, 4) + "-" + x.Substring(12, 4);
}

public static string GenerateRandomString(int length, string alphabet)
{
    int maxlen = alphabet.Length;
    StringBuilder randomChars = new StringBuilder(length);

    for (int i = 0; i < length; i++)
    {
        randomChars.Append(alphabet[random.Next(0, maxlen)]);
    }

    return randomChars.ToString();
}

Output:

97A8-55E5-C6B8-959E
8C60-6597-B71D-5CAF
8E1B-B625-68ED-107B
A6B5-1D2E-8D77-EB99
5595-E8DC-3A47-0605

Doing this way gives you precise control of the characters in the alphabet. If you need crypto strength randomness (unlikely) use the cryto random class to generate random bytes (possibly mod the alphabet length).

Computing power is cheap, take your idea of the MD5 and run an "aesthetic" of your own devising over the set. The code below generates 2000 unique keys almost instantaneously that do not have a 0,1,L,O character in them. Modify aesthetic to fit any additional criteria:

import random, hashlib

def potential_key():
    x = random.random()
    m = hashlib.md5()
    m.update(str(x))
    s = m.hexdigest().upper()[:16]
    return "%s-%s-%s-%s" % (s[:4],s[4:8],s[8:12],s[12:])

def aesthetic(s):
    bad_chars = ["0","1","L","O"]
    for b in bad_chars: 
        if b in s: return False
    return True

key_set = set()

while len(key_set) < 2000:
    k = potential_key()
    if aesthetic(k): 
        key_set.add(k)

print key_set

Example keys:

'4297-CAC6-9DA8-625A', '43DD-2ED4-E4F8-3E8D', '4A8D-D5EF-C7A3-E4D5', 
'A68D-9986-4489-B66C', '9B23-6259-9832-9639', '2C36-FE65-EDDB-2CF7', 
'BFB6-7769-4993-CD86', 'B4F4-E278-D672-3D2C', 'EEC4-3357-2EAB-96F5', 
'6B69-C6DA-99C3-7B67', '9ED7-FED5-3CC6-D4C6', 'D3AA-AF48-6379-92EF', ...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top