为什么golang软件包bcrypt在对密码进行哈希处理后能够检索盐?

问题描述

我无法理解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
}

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

关键是将密码和盐一起哈希化

hash(password + salt)

强迫黑客重新生成专门用于盐的彩虹表

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

换句话说,一旦黑客获得hashedSecret = hashedSecret[encodedSaltSize:],他就可以使用Rainbow攻击来找回密码,使盐变得毫无用处。

我弄错了吗?

解决方法

他可以删除盐,并获得不加盐的哈希密码。

除此部分以外的所有内容都是正确的。

想象一下,您有一个密码 pass 和两个盐: s1 s2

  • 哈希(s1 + pass)= 123

  • 哈希(s2 + pass)= 456

因此您将在数据库中存储两条记录:

  • s1 $ 123

  • s2 $ 456

删除盐份不会让对手感到困惑,因为他仍然需要破解两个不同的哈希摘要 123 456

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

想象一下,他们向您发送了通行证。您要做的是从存储在数据库中的哈希值中获取salt子字符串,例如 s2 $ 456,然后将其与明文连接起来,然后将哈希(s2 + pass)与上面的456比较。没有将盐存储在数据库中,您将无法执行此操作,因此这是必需的。

,

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

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

由于上述bcrypt代码中的每个密码都具有自己的 ,因此您不能使用 one 彩虹表:您必须创建一个Rainbow每种盐的表。渲染“彩虹攻击”毫无用处。