go - 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! }
我已经确认每次输入都是相同的,并且从数据库中给出的密码是正确的。
我在这里做错了什么?
解决方案
The problem is that every encryption of it is different every time, so it can never match the one in the database.
This is normal bcrypt behavior.
bcrypt returns a different hash each time because it incorporates a different random value into the hash. This is known as a "salt". It prevents people from attacking your hashed passwords with a "rainbow table", a pre-generated table mapping password hashes back to their passwords. The salt means that instead of there being one hash for a password, there's 2^16 of them. Too many to store.
The salt is stored as part of the hashed password. So bcrypt.CompareHashAndPassword(encryptedPassword, plainPassword)
can encrypt plainPassword
using the same salt as encryptedPassword
and compare them.
See this answer for more information and Dustin Boswell's excellent Storing User Passwords Securely: hashing, salting, and Bcrypt.
What am I doing wrong here?
You're trying to compare the generated hashed password with the stored hashed password. At least I certainly hope it's the hashed password that's stored in the database.
What you want instead is to compare the stored hashed password with the plain password the user entered.
// 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)
}
推荐阅读
- android - 未解决的参考:AndroidX 中的 setLifecycleOwner
- angular - 使用 Jest 和 Spectator 对以反应形式作为输入的子组件进行单元测试时,如何解决此错误?
- python - 读取 DataFrame 列时的 Nan 值
- mysql - 为什么我的查询中会出现重复的元组?
- python - dash 以编程方式更新 dash_core_components 小部件值
- mongodb - Mongo连接到应用程序时连接被拒绝错误
- javascript - 有没有办法用 JavaScript 隐藏表单的各个部分?
- react-native - 反应导航如何更改底部标签的语言
- excel - 如何修复 VBA 错误“无法将“.xlsm”保存到“.xlsx””?
- typescript - TypeScript 类扩展了 JavaScript 函数