为了账号安全,请及时绑定邮箱和手机立即绑定

Bcrypt 加密每次使用相同的输入都不同

Bcrypt 加密每次使用相同的输入都不同

Go
FFIVE 2023-03-29 15:27:42
使用golang.org/x/crypto/bcrypt和 GORM ( http://gorm.io/docs/ ) 我正在尝试加密密码。问题是它的每次加密每次都不一样,所以它永远无法与数据库中的相匹配。var result []stringpassword := []byte(data.Password)encryptedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost) // different every timedb.Where(&User{Username: strings.ToLower(data.Username)}).First(&user).Pluck("password", &result)encryptionErr := bcrypt.CompareHashAndPassword(encryptedPassword, []byte(result[0]))if encryptionErr == nil { // passwords match! }我已经确认每次输入的内容都是一样的,并且数据库中给出的密码是正确的。我在这里做错了什么?
查看完整描述

2 回答

?
白板的微信

TA贡献1883条经验 获得超3个赞

问题是它的每次加密每次都不一样,所以它永远无法与数据库中的相匹配。

这是正常的 bcrypt 行为。

bcrypt 每次都返回不同的散列,因为它将不同的随机值合并到散列中。这被称为“盐”。它可以防止人们使用“彩虹表”攻击您的散列密码,这是一个预先生成的表,将密码散列映射回他们的密码。salt 意味着密码不是一个散列,而是 2^16 个。太多无法存储。

盐作为散列密码的一部分存储。因此bcrypt.CompareHashAndPassword(encryptedPassword, plainPassword)可以plainPassword使用相同的盐进行加密encryptedPassword并进行比较。

我在这里做错了什么?

您正在尝试将生成的散列密码与存储的散列密码进行比较。至少我当然希望它是存储在数据库中的散列密码。

相反,您想要的是将存储的散列密码与用户输入的普通密码进行比较。

// Normally this comes from user input and is *never* stored

plainPassword := "supersekret"


// The encrypted password is stored in the database

db.Where(&User{Username: strings.ToLower(data.Username)}).First(&user).Pluck("password", &result)

encryptedPassword := []byte(result[0])


// Check if the stored encrypted password matches "supersekret"

encryptionErr := bcrypt.CompareHashAndPassword(encryptedPassword, plainPassword)

if encryptionErr == nil {

    fmt.Println("Greetings Professor Falken")

} else {

    fmt.Println(encryptionErr)

}


查看完整回答
反对 回复 2023-03-29
?
德玛西亚99

TA贡献1770条经验 获得超3个赞

bcrypt散列算法在设计上会在您每次调用它时生成一个不同的加密字符串(它是加盐的)。如果您有要检查的明文密码和数据库中的密文,您应该能够将这两件事传递给bcrypt.CompareHashAndPassword. 调整您的代码:


var result []string

db.Where(&User{Username: strings.ToLower(data.Username)})

        .First(&user)

        .Pluck("password", &result)


encryptionErr := bcrypt.CompareHashAndPassword([]byte(result[0]), []byte(data.Password))

您不需要bcrypt.GenerateFromPassword再打电话;正如您所注意到的,它将生成一个不同的加密密码,并且几乎不可能比较两者是否相等。


查看完整回答
反对 回复 2023-03-29
  • 2 回答
  • 0 关注
  • 600 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信