a = "qwertzuiopasdfghjklyxcvbnm"
n = "1234567890"
r = "23456qwertasdfgzxcvbQWERTASDFGZXCVOB"
l = "78901yuiophjklnmYUIPHJKLNM"
all = a + n + r + l
Why is this so complicated? By including some characters multiple times, you make those characters more likely to appear in passwords, which weakens the password. By making your password string so complicated, you make it hard to determine how secure the passwords are.
To get an even chance of any character, just list all of them once. Also, you can dramatically simplify this using the string module.
import string
all = string.ascii_letters + string.digits
Another problem is that the random module's documentation says it shouldn't be used for cryptography:
Python uses the Mersenne Twister as the core generator. It produces 53-bit precision floats and has a period of 2**19937-1. The underlying implementation in C is both fast and threadsafe. The Mersenne Twister is one of the most extensively tested random number generators in existence. However, being completely deterministic, it is not suitable for all purposes, and is completely unsuitable for cryptographic purposes.
[...]
Warning: The pseudo-random generators of this module should not be used for security purposes. Use os.urandom() or SystemRandom if you require a cryptographically secure pseudo-random number generator.**
So, use random.SystemRandom()
instead:
import random
import string
# Consider adding string.punctuation
possible_characters = string.ascii_letters + string.digits
def generate_password(length=32):
rng = random.SystemRandom()
return "".join([rng.choice(possible_characters) for i in range(length)])
Since we know exactly how many possible characters there are (62), and we know that they should be randomly distributed, we can say with fairly high confidence that a password generated by this scheme will on average require (62^32) / 2 (about 10^57) attempts to guess.
That said, a 32 character password is probably secure enough, even if it's not optimally random.