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.