// 密码加密 package utils import ( "errors" "golang.org/x/crypto/bcrypt" ) const ( // DefaultCost 默认加密成本,平衡安全性和性能 DefaultCost = bcrypt.DefaultCost // 通常是10 // MinCost 最小加密成本 MinCost = bcrypt.MinCost // 4 // MaxCost 最大加密成本 MaxCost = bcrypt.MaxCost // 31 ) var ( // ErrPasswordTooLong 密码过长错误 ErrPasswordTooLong = errors.New("password is too long") // ErrPasswordEmpty 密码为空错误 ErrPasswordEmpty = errors.New("password cannot be empty") // ErrInvalidCost 加密成本无效错误 ErrInvalidCost = errors.New("invalid cost value") ) // HashPassword 使用bcrypt对密码进行加密 // password: 原始密码 // 返回加密后的密码哈希值和错误信息 func HashPassword(password string) (string, error) { return HashPasswordWithCost(password, DefaultCost) } // HashPasswordWithCost 使用指定成本对密码进行加密 // password: 原始密码 // cost: 加密成本 (4-31),成本越高越安全但速度越慢 // 返回加密后的密码哈希值和错误信息 func HashPasswordWithCost(password string, cost int) (string, error) { // 验证输入 if password == "" { return "", ErrPasswordEmpty } // bcrypt有72字节的限制 if len(password) > 72 { return "", ErrPasswordTooLong } // 验证成本值 if cost < MinCost || cost > MaxCost { return "", ErrInvalidCost } // 生成密码哈希 hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), cost) if err != nil { return "", err } return string(hashedPassword), nil } // CheckPassword 验证密码是否正确 // hashedPassword: 存储的密码哈希值 // password: 用户输入的原始密码 // 返回验证结果 func CheckPassword(hashedPassword, password string) bool { // 验证输入 if hashedPassword == "" || password == "" { return false } // 比较密码 err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) return err == nil } // CheckPasswordWithError 验证密码是否正确,返回详细错误信息 // hashedPassword: 存储的密码哈希值 // password: 用户输入的原始密码 // 返回验证结果和错误信息 func CheckPasswordWithError(hashedPassword, password string) error { // 验证输入 if hashedPassword == "" { return errors.New("hashed password cannot be empty") } if password == "" { return ErrPasswordEmpty } // 比较密码 return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) } // GetCost 获取密码哈希的加密成本 // hashedPassword: 密码哈希值 // 返回加密成本和错误信息 func GetCost(hashedPassword string) (int, error) { if hashedPassword == "" { return 0, errors.New("hashed password cannot be empty") } cost, err := bcrypt.Cost([]byte(hashedPassword)) return cost, err } // NeedsRehash 检查密码是否需要重新哈希(当前成本低于推荐成本时) // hashedPassword: 密码哈希值 // preferredCost: 推荐的加密成本 // 返回是否需要重新哈希 func NeedsRehash(hashedPassword string, preferredCost int) (bool, error) { currentCost, err := GetCost(hashedPassword) if err != nil { return false, err } return currentCost < preferredCost, nil }