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

使用golang.org/x/crypto/bcrypt和 GORM ( http://gorm.io/docs/ ) 我正在尝试加密密码。问题是它的每次加密每次都不一样,所以它永远无法与数据库中的相匹配。


var result []string


password := []byte(data.Password)

encryptedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost) // different every time


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

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


if encryptionErr == nil { // passwords match! }

我已经确认每次输入的内容都是一样的,并且数据库中给出的密码是正确的。


我在这里做错了什么?


FFIVE
浏览 604回答 2
2回答

白板的微信

问题是它的每次加密每次都不一样,所以它永远无法与数据库中的相匹配。这是正常的 bcrypt 行为。bcrypt 每次都返回不同的散列,因为它将不同的随机值合并到散列中。这被称为“盐”。它可以防止人们使用“彩虹表”攻击您的散列密码,这是一个预先生成的表,将密码散列映射回他们的密码。salt 意味着密码不是一个散列,而是 2^16 个。太多无法存储。盐作为散列密码的一部分存储。因此bcrypt.CompareHashAndPassword(encryptedPassword, plainPassword)可以plainPassword使用相同的盐进行加密encryptedPassword并进行比较。我在这里做错了什么?您正在尝试将生成的散列密码与存储的散列密码进行比较。至少我当然希望它是存储在数据库中的散列密码。相反,您想要的是将存储的散列密码与用户输入的普通密码进行比较。// Normally this comes from user input and is *never* storedplainPassword := "supersekret"// The encrypted password is stored in the databasedb.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)}

德玛西亚99

bcrypt散列算法在设计上会在您每次调用它时生成一个不同的加密字符串(它是加盐的)。如果您有要检查的明文密码和数据库中的密文,您应该能够将这两件事传递给bcrypt.CompareHashAndPassword. 调整您的代码:var result []stringdb.Where(&User{Username: strings.ToLower(data.Username)})        .First(&user)        .Pluck("password", &result)encryptionErr := bcrypt.CompareHashAndPassword([]byte(result[0]), []byte(data.Password))您不需要bcrypt.GenerateFromPassword再打电话;正如您所注意到的,它将生成一个不同的加密密码,并且几乎不可能比较两者是否相等。
打开App,查看更多内容
随时随地看视频慕课网APP