46 lines
1.4 KiB
Go
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$")
|
|
}
|