Files
2026-10-20 19:07:36 +08:00

46 lines
1.4 KiB
Go

package crypto
import (
"crypto/rand"
"encoding/base64"
"golang.org/x/crypto/bcrypt"
)
// ============================== 密码加密与校验 ==============================
// GenerateSalt 生成随机外部盐值
//
// 取 8 字节随机数经 base64url 编码后截取 10 个字符,去除填充
func GenerateSalt() string {
b := make([]byte, 8)
_, _ = rand.Read(b)
return base64.RawURLEncoding.EncodeToString(b)[:10]
}
// HashPassword 双重加盐加密
//
// 使用 bcrypt 对 password 与 salt 拼接后的内容加密,返回哈希值;
// 两值分别写入 password 与 salt 列,salt 为空时等价于直接加密密码,兼容旧数据
func HashPassword(password, salt string) (string, error) {
hash, err := bcrypt.GenerateFromPassword([]byte(password+salt), bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(hash), nil
}
// VerifyPassword 校验密码
//
// 使用 bcrypt 比对哈希值与 password 加 salt 的组合,salt 为空时直接比对,兼容旧数据
func VerifyPassword(hashedPassword, password, salt string) bool {
return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password+salt)) == nil
}
// IsBcrypt 判断是否为 bcrypt 格式
//
// 旧版 md5 加 salt 的数据返回 false
func IsBcrypt(hashed string) bool {
return len(hashed) > 4 && (hashed[:4] == "$2a$" || hashed[:4] == "$2b$" || hashed[:4] == "$2y$")
}