问题描述
我无法理解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每种盐的表。渲染“彩虹攻击”毫无用处。