The code below generates pseudo-random IDs in the same way as the Google Authenticator applications. The algorithm this implements is available as an open source project, but is so simple to implement using the Python libraries that there seems little point in introducing an external dependency.
The code is shamelessly stolen from this SO question.
The secret key is a base-32 encoded string which the Python libraries require to be padded if it's not a multiple of 8 characters. To avoid this issue, the server should only generate keys that are such a multiple - I suggest the base-32 encoding of 10 random bytes, which should yield a 16-byte base-32 key.
int, which the Google applications zero-pad to 6 digits as required - bear this in mind if doing a string comparison.
import hmac, base64, struct, hashlib, time def get_hotp_token(secret, intervals_no): key = base64.b32decode(secret, True) msg = struct.pack(">Q", intervals_no) h = hmac.new(key, msg, hashlib.sha1).digest() o = ord(h) & 15 h = (struct.unpack(">I", h[o:o+4]) & 0x7fffffff) % 1000000 return h def get_totp_token(secret): return get_hotp_token(secret, intervals_no=int(time.time())//30)
Until I get chance to put it somewhere else, here's an unrelated snippet to generate fairly secure keys from pycrypto:
>>> import Crypto.Hash.SHA256 >>> import Crypto.Protocol.KDF >>> myprf = lambda p,s: Crypto.Protocol.KDF.HMAC.new(p, s, Crypto.Hash.SHA256).digest() >>> Crypto.Protocol.KDF.PBKDF2("password", "salt", dkLen=32, count=5000, prf=myprf) '\x8f\xc2\xbc\xff\xbbK\x1a\xc9\xb9\xde\x03X\x8d9\x0f=\x9b\xf36\xc2\xc4B,\x90\xc1X\xccqB%\xf6)'