Archive for June 2009
Simple API Key Generation in Python
Summary
I’m creating a REST API for my current Django project, and I want a good psuedo-random way to generate alpha numeric API keys. Outlined is a simple method which I believe makes pretty good psuedo-random keys.
Discussion
Like Session keys, API keys should be sufficiently unpredictable to be psuedo-random. To be unpredictable, no user variables (or timestamps) are encoded into the key.
Specifically, the key starts life as a 256bit number generated by the Mersenne Twister Pseudo Random Number Generator (PRNG).
>> str(random.getrandbits(256))
>>90035287577760653301955374895950037116738729760252440482985364146171806313429
Mersenne Twister itself is not considered cryptographically secure (it has been demonstrated that observing a sufficient number of iterates allows one to predict all future iterates).
To mitigate this problem, the 256bit number is cryptographically hashed using SHA-256.
>> hashlib.sha224( str(random.getrandbits(256)) ).hexdigest()
>> 654c6da8f3b0fd8fe819669daf07996738d21a53c02c731b0aee6373
The result is then Base64 encoded – which results in a string containing only lower and upper case alphabetical characters, and numbers – and also two special characters (usually ‘/’ and ‘+’).
A character-pair (eg: ‘aF’ or ‘zZ’) is then selected randomly (pseudo-randomly) from a pool of character-pairs; these are substituted (salted) for the non-alphanumeric characters left by the Base64 encoding.
The resulting string is a 38 character alphanumeric that is sufficiently large and unpredictable for an API key.
>> base64.b64encode(hashlib.sha256( str(random.getrandbits(256)) ).digest(), random.choice(['rA','aZ','gQ','hH','hG','aR','DD'])).rstrip('==')
>> mwkMqTWFnK0LzJHyfkeBGoS2hr2KG7WhHqSGX0SbDJ4
Conclusion
Without too much complication or any hardware source of randomness, this seems like a reasonable method for API key generation.

