错误:crypto/bcrypt:hashedPassword不是给定密码的哈希值。

huangapple go评论65阅读模式
英文:

error: crypto/bcrypt: hashedPassword is not the hash of the given password

问题

我正在为用户创建身份验证路由。当我创建用户时,我将密码保存为哈希值,并在身份验证中创建了以下函数来验证密码,使用了crypto/bcrypt库:

func (user *User) ValidatePassword(password string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
	if err != nil {
		println(user.Password, password)
		panic(err)
	}
	return err == nil
}

保存用户时一切正常,但在进行身份验证时,密码验证返回以下错误:

// hashes compared
$2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa $2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa

// error
http: panic serving 127.0.0.1:62939: crypto/bcrypt: hashedPassword is not the hash of the given password
goroutine 20 [running]:
net/http.(*conn).serve.func1()

我创建了一个哈希并将其转换为字符串进行保存:

func NewUser(name, email, password string) (*User, error) {
	hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return nil, err
	}

	return &User{
		ID:       entity.NewID(),
		Name:     name,
		Email:    email,
		Password: string(hash),
	}, nil
}

更多信息:
user_domain
user_db
user_handler

根据文档,我认为我正确使用了CompareHashAndPassword,但是我收到了这个错误。

英文:

I'm making a route to authenticate the user, when I create the user, I save the password as a hash and in the authentication I created this function to validate the password using the crypto/bcrypt lib:

func (user *User) ValidatePassword(password string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
	if err != nil {
		println(user.Password, password)
		panic(err)
	}
	return err == nil
}

when saving the user everything works fine, but when I authenticate, the password validation returns this error:

// hashes compared
$2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa $2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa

// error
http: panic serving 127.0.0.1:62939: crypto/bcrypt: hashedPassword is not the hash of the given password
goroutine 20 [running]:
net/http.(*conn).serve.func1()

I create a hash and convert to string to save:

func NewUser(name, email, password string) (*User, error) {
	hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return nil, err
	}

	return &User{
		ID:       entity.NewID(),
		Name:     name,
		Email:    email,
		Password: string(hash),
	}, nil
}

More info:
user_domain
user_db
user_handler

According to the documentation, I think I'm using CompareHashAndPassword correctly, but I get this error

答案1

得分: 2

> // hashes compared
> $2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa $2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa

这里的日志意味着一个哈希密码被传递给(*User).ValidatePasswordbcrypt.CompareHashAndPassword比较两个哈希密码。这是不正确的,bcrypt.CompareHashAndPassword应该比较一个哈希密码和一个明文密码。


附注 这样做Password: string(hash)是一个不好的主意。虽然这在语言规范中是允许的,但生成的字符串可能包含无效的Unicode代码点,其他软件可能无法接受它或正确处理它。例如,无效的代码点会被PostgreSQL拒绝。以下演示将抛出错误消息:ERROR: invalid byte sequence for encoding "UTF8": 0xff (SQLSTATE 22021)。我认为你可以将Password的数据类型更改为[]byte,并将哈希值以二进制数据的形式存储在数据库中。

package main

import (
	"context"
	"fmt"
	"os"

	"github.com/jackc/pgx/v5"
)

func main() {
	urlExample := "postgres://postgres:sa123@localhost:5432/taop"
	conn, err := pgx.Connect(context.Background(), urlExample)
	if err != nil {
		fmt.Fprintf(os.Stderr, "无法连接到数据库:%v\n", err)
		os.Exit(1)
	}
	defer conn.Close(context.Background())

	_, err = conn.Exec(context.Background(), "CREATE TABLE students(password TEXT)")
	if err != nil {
		panic(err)
	}

	_, err = conn.Exec(context.Background(), "INSERT INTO students(name) VALUES ($1)", string([]byte{0xff, 0xfe, 0xfd}))
	if err != nil {
		panic(err)
	}
}
英文:

> // hashes compared
> $2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa $2a$10$gRIPZJZTy3f0KgUjs5eGzeVfVn1fLwkKWL3iSa30OnhLO2VuHkyfa

The logs here means that a hashed password is passed to (*User).ValidatePassword and bcrypt.CompareHashAndPassword compares two hashed passwords. This is incorrect, bcrypt.CompareHashAndPassword is supposed to compare a hashed password and a plain password.


P.S. It's a bad idea to do this Password: string(hash). This is allowed by the language spec, but the resulting string could contain invalid Unicode code points, and other software may not accept it or handle it correctly. For example, invalid code point is rejected by PostgreSQL. The following demo will panic with message: ERROR: invalid byte sequence for encoding "UTF8": 0xff (SQLSTATE 22021). I think you can change the data type of Password to []byte and store the hashed value as binary data in the database.

package main

import (
	"context"
	"fmt"
	"os"

	"github.com/jackc/pgx/v5"
)

func main() {
	urlExample := "postgres://postgres:sa123@localhost:5432/taop"
	conn, err := pgx.Connect(context.Background(), urlExample)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
		os.Exit(1)
	}
	defer conn.Close(context.Background())

	_, err = conn.Exec(context.Background(), "CREATE TABLE students(password TEXT)")
	if err != nil {
		panic(err)
	}

	_, err = conn.Exec(context.Background(), "INSERT INTO students(name) VALUES ($1)", string([]byte{0xff, 0xfe, 0xfd}))
	if err != nil {
		panic(err)
	}
}

huangapple
  • 本文由 发表于 2023年5月17日 18:51:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76271285.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定