I'm interested in creating a very simple, high (cryptographic) quality random password generator. Is there a better way to do this?
import os, random, string
length = 13
chars = string.ascii_letters + string.digits + '!@#$%^&*()'
random.seed = (os.urandom(1024))
print ''.join(random.choice(chars) for i in range(length))
The difficult thing with passwords is to make them strong enough and still be able to remember them. If the password is not meant to be remembered by a human being, then it is not really a password.
You use Python's os.urandom()
: that's good. For any practical purpose (even cryptography), the output of os.urandom()
is indistinguishable from true alea. Then you use it as seed in random
, which is less good: that one is a non-cryptographic PRNG, and its output may exhibit some structure which will not register in a statistical measurement tool, but might be exploited by an intelligent attacker. You should work with os.urandom()
all along. To make things simple: choose an alphabet of length 64, e.g. letters (uppercase and lowercase), digits, and two extra punctuation characters (such as '+' and '/'). Then, for each password character, get one byte from os.urandom()
, reduce the value modulo 64 (this is unbiased because 64 divides 256) and use the result as index in your chars
array.
With an alphabet of length 64, you get 6 bits of entropy per character (because 26 = 64). Thus, with 13 characters, you get 78 bits of entropy. This is not ultimately strong in all cases, but already very strong (it could be defeated with a budget which will be counted in months and billions of dollars, not mere millions).