我使用 mitsuhiko 的 pbkdf2 实现进行密码散列:
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]
此函数返回二进制摘要,然后将其编码为 base64 并保存到数据库。此外,当用户登录时,该 base64 字符串被设置为 cookie。
此函数用于密码哈希比较:
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
我想知道二进制哈希和base64字符串在安全性方面的比较是否有任何区别?例如,当用户登录时,我计算提交密码的二进制摘要,从数据库中解码 base64 字符串,然后比较两个二进制哈希,但如果用户有一个带有 base64 字符串的 cookie,我直接将它与来自的字符串进行比较数据库。
第二个问题是关于盐的:
os.urandom 返回二进制字符串,但在它用于哈希生成之前,我还将它编码为 base64。有什么理由我不应该这样做并以二进制形式使用盐吗?