bcrypt比对密码报错crypto/bcrypt: hashedPassword is not the hash of the given password求助
问题排查方向
- 检查数据库密码字段长度:bcrypt生成的哈希固定为60字符,若
user.Password对应字段长度设置小于60,哈希存入时会被截断,导致比对失败。 - 检查注册环节哈希生成逻辑:确认注册时是对用户传入的明文密码直接生成bcrypt哈希,没有额外拼接其他字段(如手机号、自定义盐未同步到比对逻辑)、没有误哈希空值/错误值,生成哈希后的错误要做捕获处理,避免生成失败时存入无效值。
- 检查密码是否存在不可见字符:登录时打印
len(body.Password)确认长度是否和预期一致,排除前端传入/BodyParser解析时带入的换行、空格、转义符等肉眼不可见字符。 - 检查哈希值完整性:查看数据库中实际存储的密码哈希是否和打印出的
$2a$14$AphYClfW8V1HZh4.6kSD1OpkTzvS9dTc/1qgKesbCUW5.9BMDmzMW完全一致,排除日志输出时拼接了额外内容(你日志末尾的!exclude .idea属于异常输出,需排查是否污染了密码变量)。 - 最小demo验证:单独运行以下代码验证当前哈希是否为
123456的bcrypt哈希,若仍报错则可确认该哈希与123456不匹配,问题出在注册存库环节:
package main import ( "fmt" "golang.org/x/crypto/bcrypt" ) func main() { hash := []byte("$2a$14$AphYClfW8V1HZh4.6kSD1OpkTzvS9dTc/1qgKesbCUW5.9BMDmzMW") pass := []byte("123456") fmt.Println(bcrypt.CompareHashAndPassword(hash, pass)) }
替代密码加密方案
Argon2(行业优先推荐,抗暴力破解能力优于bcrypt)
依赖库:golang.org/x/crypto/argon2
哈希生成代码
import ( "crypto/rand" "crypto/subtle" "encoding/base64" "errors" "fmt" "golang.org/x/crypto/argon2" "strings" ) func HashPassword(password string) (string, error) { // 生成16位随机盐 salt := make([]byte, 16) if _, err := rand.Read(salt); err != nil { return "", err } // 生成argon2id哈希 hash := argon2.IDKey([]byte(password), salt, 1, 64*1024, 4, 32) b64Salt := base64.RawStdEncoding.EncodeToString(salt) b64Hash := base64.RawStdEncoding.EncodeToString(hash) // 拼接成标准格式存储 return fmt.Sprintf("$argon2id$v=19$m=65536,t=1,p=4$%s$%s", b64Salt, b64Hash), nil }
密码比对代码
func ComparePassword(password, storedHash string) (bool, error) { parts := strings.Split(storedHash, "$") if len(parts) != 6 { return false, errors.New("无效的哈希格式") } // 解析版本号 var version int if _, err := fmt.Sscanf(parts[2], "v=%d", &version); err != nil || version != argon2.Version { return false, errors.New("不兼容的Argon2版本") } // 解析参数 var memory uint32, time uint32, parallelism uint8 if _, err := fmt.Sscanf(parts[3], "m=%d,t=%d,p=%d", &memory, &time, ¶llelism); err != nil { return false, err } // 解码盐和哈希值 salt, err := base64.RawStdEncoding.DecodeString(parts[4]) if err != nil { return false, err } decodedHash, err := base64.RawStdEncoding.DecodeString(parts[5]) if err != nil { return false, err } // 计算当前密码的哈希做比对 computedHash := argon2.IDKey([]byte(password), salt, time, memory, parallelism, uint32(len(decodedHash))) return subtle.ConstantTimeCompare(computedHash, decodedHash) == 1, nil }
PBKDF2(兼容性高,适合需要兼容旧系统的场景)
依赖库:golang.org/x/crypto/pbkdf2,可搭配sha256/sha512作为哈希函数使用,核心逻辑为生成随机盐、迭代计算哈希、拼接参数存储后比对即可。
内容的提问来源于stack exchange,提问作者Saifullah Shahen
相关产品推荐
相关产品推荐

