Join me in the fight against weak password hashes.
A PBKDF2 password hash should contain the salt, the number of iterations, and the hash itself so it's possible to verify later. Is there a standard format, like RFC2307's {SSHA}, for PBKDF2 password hashes? BCRYPT is great but PBKDF2 is easier to implement.
Apparently, there's no spec. So here's my spec.
>>> from base64 import urlsafe_b64encode
>>> password = u"hashy the \N{SNOWMAN}"
>>> salt = urlsafe_b64decode('s8MHhEQ78sM=')
>>> encoded = pbkdf2_hash(password, salt=salt)
>>> encoded
'{PBKDF2}1000$s8MHhEQ78sM=$hcKhCiW13OVhmLrbagdY-RwJvkA='
Update: http://www.dlitz.net/software/python-pbkdf2/ defines a crypt()
replacement. I updated my little spec to match his, except his starts with $p5k2$
instead of {PBKDF2}
. (I have the need to migrate away from other LDAP-style {SCHEMES}).
That's {PBKDF2}
, the number of iterations in lowercase hexadecimal, $
, the urlsafe_base64
encoded salt, $
, and the urlsafe_base64
encoded PBKDF2 output. The salt should be 64 bits, the number of iterations should be at least 1000, and the PBKDF2 with HMAC-SHA1 output can be any length. In my implementation it is always 20 bytes (the length of a SHA-1 hash) by default.
The password must be encoded to utf-8 before being sent through PBKDF2. No word on whether it should be normalized into Unicode's NFC.
This scheme should be on the order of iterations
times more costly to brute force than {SSHA}.