Golang中密码哈希与比较的实现方法
Golang中密码哈希与比较的实现方法 我尝试比较数据库密码和表单值密码时遇到以下错误: crypto/bcrypt: hashedPassword 不是给定密码的哈希值。我已附上相关代码函数
6 回复
继续使用bcrypt,SHA1非常不安全。Bcrypt默认还会对密码进行加盐处理。
感谢George的回复,我使用了Yamil的代码并且成功了。
您也可以尝试直接从 SQL 命令进行身份验证,例如:
func sqlAuthenticateUser(u *User) error {
if err := db.QueryRow("SELECT * FROM user WHERE email=? AND password=SHA1(?)", u.Email, u.Password).Scan(&u.Id, &u.Name, &u.Email, &u.Password, &u.isActive); err != nil {
log.Println(err)
return err
}
return nil
}
当然,在此之前您必须类似地插入加密密码。
在Go语言中,使用bcrypt包进行密码哈希和比较时,常见的错误是直接比较哈希后的字节数组或字符串,而不是使用bcrypt.CompareHashAndPassword函数。根据你提供的代码,问题可能出现在密码比较的方式上。以下是正确的实现方法:
密码哈希生成
首先,使用bcrypt.GenerateFromPassword生成密码的哈希值。这个函数会自动处理盐值,并返回哈希后的字节数组。
package main
import (
"golang.org/x/crypto/bcrypt"
"fmt"
)
func HashPassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(bytes), nil
}
密码比较
使用bcrypt.CompareHashAndPassword函数来比较哈希密码和明文密码。这个函数会验证密码是否匹配,并返回错误(如果密码不匹配,则返回bcrypt.ErrMismatchedHashAndPassword)。
func CheckPasswordHash(password, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}
完整示例
以下是一个完整的示例,展示如何生成密码哈希并在登录时进行比较:
package main
import (
"golang.org/x/crypto/bcrypt"
"fmt"
)
func main() {
password := "secretpassword"
// 生成哈希密码
hash, err := HashPassword(password)
if err != nil {
fmt.Println("Error hashing password:", err)
return
}
fmt.Println("Hashed Password:", hash)
// 模拟从数据库获取的哈希密码
storedHash := hash
// 检查密码是否匹配
match := CheckPasswordHash(password, storedHash)
if match {
fmt.Println("Password matches!")
} else {
fmt.Println("Password does not match!")
}
// 测试错误密码
wrongPassword := "wrongpassword"
match = CheckPasswordHash(wrongPassword, storedHash)
if match {
fmt.Println("Wrong password matched (unexpected)!")
} else {
fmt.Println("Wrong password correctly rejected.")
}
}
func HashPassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(bytes), nil
}
func CheckPasswordHash(password, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}
关键点说明
- 不要直接比较哈希字符串:
bcrypt生成的哈希包含盐值和成本参数,直接字符串比较会失败。 - 使用
CompareHashAndPassword:这个函数内部处理了哈希解析和比较逻辑。 - 错误处理:如果密码不匹配,
CompareHashAndPassword会返回一个错误,你可以检查err == bcrypt.ErrMismatchedHashAndPassword来具体处理不匹配的情况。
在你的代码中,确保在比较时使用bcrypt.CompareHashAndPassword而不是直接比较字符串或字节数组。如果问题仍然存在,检查从数据库获取的哈希值是否正确存储和检索,没有额外的空格或编码问题。


