wom*_*ire 3 python hash comparison pbkdf2
我使用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]
Run Code Online (Sandbox Code Playgroud)
此函数返回二进制摘要,然后在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
Run Code Online (Sandbox Code Playgroud)
我想知道在安全性方面二进制哈希和base64字符串的比较是否有任何区别?例如,当用户登录时,我计算提交密码的二进制摘要,从数据库解码base64字符串,然后比较两个二进制哈希,但是如果用户有一个带有base64字符串的cookie,我直接将它与来自的字符串进行比较数据库.
第二个问题是盐:
os.urandom返回二进制字符串,但在用于哈希生成之前,我还在base64中对其进行编码.我有什么理由不这样做并以二进制形式使用盐吗?
Eli*_*ins 10
回答问题1:比较字节与比较base64编码的字符串没有重大的安全性差异...你只是比较n或n*4/3元素.4/3使用base64 运行时间会更长,但是时间量仍然很小:)
也就是说,有一个关于类似"常量时间"比较函数的python开发人员讨论,他们遇到了一些VM级别的陷阱 - 如果你的输入是unicode字符串而不是bytes,特别是如果unicode包含非ASCII字符,可能仍然存在一些微妙的定时攻击(比短路等级攻击低几个数量级).因此,如果可能的话,我会坚持使用字节(无论是二进制数据还是ASCII编码的base64数据).但是,在PBKDF2的情况下我不会太担心,因为比较功能被设计为失败的定时攻击更多地适用于HMAC签名,而不是密码哈希验证......但更好的是安全而不是遗憾.
回答问题2:对于不安全的结构,例如md5(salt+password),首先编码盐将允许攻击者使用现有的ASCII md5表来攻击整个摘要,其中原始二进制盐会使这些表无用.然而,PBKDF2-HMAC做了足够的重整,唯一重要的是盐包含n熵 - 无论是n/8原始字节的形式,还是n/6base64字符都不影响安全性.
其他说明:我只想添加一些与你发布的内容有关的其他要点......
出于安全考虑,我强烈建议使用SHA256/512而不是SHA1作为PBKDF2-HMAC哈希函数,并且> = 10,000轮(截至2012年),以确保安全性.
在cookie中发送摘要(甚至没有盐)的想法让我觉得可能不安全......如果有人窃取了那个cookie(例如跨站点脚本攻击),他们可能会以用户身份登录(尽管我不知道你的应用程序的安全设置其余部分).使用具有随机生成的会话ID的会话层(例如Beaker)可能是一个不错的选择.
我推荐使用Passlib PBKDF2和consteq实现,它的PBKDF2程序比mitsuhiko快5倍,如果存在,可以利用M2Crypto.(免责声明:我是Passlib的作者).它还有一个现成的pbkdf2-sha256密码散列函数,但如果你在cookie中发送摘要,这将不会有太多用处.