Predictable Random Numbers

Well that title is odd, right?


What I’m wanting to do here is demonstrate one way to generate random numbers using a seed . The requirement here is we need to test a number at any given time, this will be useful if we intend to use the process as a token of sort, think RSA SecureID .

Anyways I wanted to make a implementation that used Python and didn’t cost me hundreds of dollars.

The first thing I needed was a changing number, but one that only changed every 60 seconds. I decided to use a timestamp here of Year, Month, Day, Hour, Minute in UTC format. To do this I used the Python time function’s strftime method:

In [1]: import time

In [2]: timestamp = time.strftime('%Y%m%d%H%M', time.gmtime())

In [3]: timestamp
Out[3]: '201312101409'

Creating a random number using this format is useless since anyone who knows the time can recreate the output token. To resolve this I’m going to use a salt mixed in with this time string.

A 4 digit key can be used as our salt just fine:

In [1]: key = '1234'

Now we can combine the two in order to make our seed :

In [1]: myseed = key + timestamp

In [2]: myseed
Out[2]: '1234201312101409'

Excellent we have a salted number we can use as a seed, lets go ahead and use the Python random library to generate some random ranges using this seed:

In [1]: r = random.Random(myseed)

In [2]: r.randrange(000000, 999999)
Out[2]: 807766

The beauty about Python’s Random class is it takes a seed for generating random number, this way we can always guess randomness of the numbers. I also used a output number of 000000 through 999999 (that is a 6 digit random number starting with all 0s and ending with all 9s).

Below is a few functions thrown together:

import time
import random

def get_timestamp():
    return time.strftime('%Y%m%d%H%M', time.gmtime())

def get_token(key):
    r = random.Random('%s%s' % (key, get_timestamp()))
    return r.randrange(000000, 999999)

def check_token(key, token):
    cur = get_token(key)
    if token == cur:
        return True
    return False

Using these functions lets create a token and track at what time it was created.

In [1]: !date
Tue Dec 10 08:37:19 CST 2013

In [2]: token = get_token(1234)

In [3]: token
Out[3]: 771259

Lets check if this token is valid right after creating it:

In [1]: !date
Tue Dec 10 08:37:23 CST 2013

In [2]: check_token(1234, token)
Out[2]: True

And finally lets wait about a minute and check again:

In [1]: !date
Tue Dec 10 08:38:11 CST 2013

In [2]: check_token(1234, token)
Out[2]: False

And there you have it, a working proof of concept.

I would like to mention this is purely concept code, it is not very secure. I am also not sure if the python random library is portable from Python version to version, or even instance to instance.