I use mitsuhiko's implementation of pbkdf2 for password hashing:
def pbkdf2_bin(data, salt, iterations=1000, keylen=24, hashfunc=None):
"""Returns a binary digest for the PBKDF2 hash algorithm of `data`
with the given `salt`. It iterates `iterations` time and produces a
key of `keylen` bytes. By default SHA-1 is used as hash function,
a different hashlib `hashfunc` can be provided.
"""
hashfunc = hashfunc or hashlib.sha1
mac = hmac.new(data, None, hashfunc)
def _pseudorandom(x, mac=mac):
h = mac.copy()
h.update(x)
return map(ord, h.digest())
buf = []
for block in xrange(1, -(-keylen // mac.digest_size) + 1):
rv = u = _pseudorandom(salt + _pack_int(block))
for i in xrange(iterations - 1):
u = _pseudorandom(''.join(map(chr, u)))
rv = starmap(xor, izip(rv, u))
buf.extend(rv)
return ''.join(map(chr, buf))[:keylen]
This function returns binary digest which is then encoded in base64 and saved to database. Also that base64 string is set as a cookie when a user logs in.
This function is used for password hashes comparison:
def comparePasswords(password1, password2):
if len(password1) != len(password2):
return False
diff = 0
for x, y in izip(password1, password2):
diff |= ord(x) ^ ord(y)
return diff == 0
I wonder if there is any difference in comparison of binary hashes and base64 strings in terms of security? For example when a user logs in, I calculate binary digest of submitted password, decode base64 string from the database and then compare two binary hashes, but in case the user has a cookie with base64 string, I directly compare it with the a string from the database.
The second question is about salt:
os.urandom returns binary string, but before it is used in hash generation I also encode it in base64. Is there any reason why I shouldn't do this and use salt in binary form?