Salt is just two random characters from [./A-Za-z0-9], giving 4096
possibilities.
from random import randint
import crypt
import string
salt_chars = './' + string.ascii_letters + string.digits
def crypt_password(password):
salt = salt_chars[randint(0, 63)] + salt_chars[rand_int(0, 63)]
return crypt(password, salt)
Ok, so the paranoids would point out that random.randint() might not be
sufficiently random... but we don't need cryptographically strong
random numbers. No attack on crypt() depends on guessing the salt, the
salt is in the output anyway. [see for yourself...
crypt.crypt('foobar','//') => '//f1Jm145Q9jA']
So to check a password you would...
def check_password(crypted_password, password):
salt = crypted_password[:2]
return crypt(password, salt) == crypted_password
If you're writing something new (i.e. you are not using existing
password databases) then crypt() is a poor choice. It's only available
on Unix, and ignores characters past the first 8. MD5 and SHA-1 are
better choices, but you'll have to handle the salt yourself.
For example, you could do...
import sha
def crypt_password(username, password):
return sha.sha('%i %s%i %s' % (len(username), username,
len(password), password))
Putting the username with the password serves the same function as salt.