2

我无法理解golang crypto bcrypt repo中的以下代码

func newFromHash(hashedSecret []byte) (*hashed, error) {
    if len(hashedSecret) < minHashSize {
        return nil, ErrHashTooShort
    }
    p := new(hashed)
    n, err := p.decodeVersion(hashedSecret)
    if err != nil {
        return nil, err
    }
    hashedSecret = hashedSecret[n:]
    n, err = p.decodeCost(hashedSecret)
    if err != nil {
        return nil, err
    }
    hashedSecret = hashedSecret[n:]

    // The "+2" is here because we'll have to append at most 2 '=' to the salt
    // when base64 decoding it in expensiveBlowfishSetup().
    p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2)
    copy(p.salt, hashedSecret[:encodedSaltSize])

    hashedSecret = hashedSecret[encodedSaltSize:]
    p.hash = make([]byte, len(hashedSecret))
    copy(p.hash, hashedSecret)

    return p, nil
}

据我了解,加盐用于防止攻击者入侵数据库并获取哈希密码列表,为了从哈希中获取原始密码,黑客可以遍历所有有效的密码组合并对其中的每一个进行哈希处理,如果其中一个生成的哈希与黑客数据库中的哈希匹配,黑客可以取回密码。在哈希之前添加盐会迫使对手重新生成彩虹表。

关键是将密码与盐一起散列

hash(password + salt)

迫使黑客专门为盐重新生成彩虹表

但似乎bcrypt能够取回盐,所以从技术上讲,如果对手知道系统正在使用bcrypt,他可以删除盐并获取未加盐的哈希密码。

换句话说,一旦黑客得到hashedSecret = hashedSecret[encodedSaltSize:],他可以使用彩虹攻击来取回密码,使盐无用。

我有什么问题吗?

4

2 回答 2

6

他可以删除加盐,得到没有加盐的哈希密码。

除了这部分之外的一切都是正确的。

想象一下,你有一个密码通行证和两个盐:s1s2

  • 哈希(s1 + 通过)= 123

  • 哈希(s2 + 通过)= 456

因此,您的数据库中将有两条存储记录:

  • s1$123

  • s2$456

删除盐部分不会让对手在任何地方得到攻击,因为他仍然需要破解两个不同的哈希摘要123456 。

另一方面,一旦您从用户那里获得明文,它将使您无法重建您的哈希值。

想象一下他们给你发pass。您要做的是从存储在您的数据库中的哈希中获取盐子字符串,例如s2 $456,然后将其与明文连接,然后将哈希(s2 + pass)与上面的 456 进行比较。如果没有将盐存储在数据库中,您将无法执行此操作,这就是它的必要性。

于 2020-11-11T06:34:27.360 回答
2

您可以取回盐,但这并不意味着您可以获得未加盐的密码哈希。“换句话说,一旦黑客得到 hashedSecret = hashedSecret[encodedSaltSize:] 他就可以使用彩虹攻击来取回密码,使盐变得无用。” 具有误导性。攻击者可以获得盐和散列密码,但这不允许“彩虹攻击”。

“彩虹攻击”中的攻击是:一次生成一个巨大的彩虹表,预先。该列表是一对 (cleartextpassword,passwordhash) 条目。生成此表非常耗时(如果包含大量密码,可能会变得很大,如果包含所有密码,则可能会变得很大!)。“彩虹攻击”中的攻击是:您只需生成此彩虹表一次,并且可以使用它非常快速地查找数百万个密码哈希的明文密码。

由于上面 bcrypt 代码中的每个密码都有自己的 ,因此您不能使用一个彩虹表:您必须为每个盐创建一个彩虹表。使“彩虹攻击”无用。

于 2020-11-11T06:39:04.237 回答