首页 文章

pbkdf2和哈希比较

提问于
浏览
3

我使用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中对其进行编码 . 我有什么理由不这样做并以二进制形式使用盐吗?

1 回答

  • 10

    To answer question 1 :有's no major security difference when comparing bytes vs comparing a base64 encoded string... you'只是比较 nn*4/3 元素 . 使用base64,运行时间将长 4/3 ,但是时间量仍然是微不足道的:)

    也就是说,有一个python开发人员discussion关于类似的"constant time"比较函数,他们遇到了一些VM级别的陷阱 - 如果你的输入是 unicode 字符串而不是 bytes ,特别是如果unicode包含非ASCII字符,那里可能仍然是一些微妙的时间攻击(比短路相等攻击低几个数量级) . 因此,在PBKDF2的情况下,我太过担心,因为比较功能被设计为失败的timing attack更适用于HMAC签名,而不是密码哈希验证...但更安全而不是抱歉 .

    To answer question 2 :对于诸如 md5(salt+password) 之类的不安全结构,首先编码盐将允许攻击者使用现有的ASCII md5表来攻击整个摘要,其中原始二进制盐会使这些表无用 . 然而,PBKDF2-HMAC做了足够的重整,唯一重要的是盐含有 n 位的熵 - 无论是 n/8 原始字节的形式,还是 n/6 base64字符都不会影响安全性 .

    Other notes :我只是想补充一些与你发布的内容有关的其他要点......

    • 出于安全考虑,我强烈建议使用SHA256 / 512而不是SHA1作为PBKDF2-HMAC哈希函数,并且> = 10,000轮(截至2012年),以确保安全性 .

    • 在cookie中发送摘要(甚至没有盐)的想法让我觉得可能不安全......如果有人偷了那个cookie(例如跨站点脚本攻击),他们可能会以用户身份登录(虽然我没有't know the rest your application'的安全设置) . 使用具有随机生成的会话ID的会话层(例如Beaker)可能是一个不错的选择 .

    • 我建议使用Passlib PBKDF2consteq实现,它's PBKDF2 routine is about 5x faster than mitsuhiko' s,并且可以利用M2Crypto(如果存在) . (免责声明:我是Passlib的作者) . 它还有一个现成的pbkdf2-sha256密码散列函数,虽然它赢得了't be quite as much use if you'在cookie中发送摘要 .

相关问题