Files
2025-11-03 23:03:17 +08:00

67 lines
1.8 KiB
Go

package pbkdf2x
import (
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"golang.org/x/crypto/pbkdf2"
)
// GenerateSalt 生成随机盐值
func GenerateSalt(length int) (string, error) {
if length <= 0 {
return "", fmt.Errorf("盐值长度必须大于0")
}
salt := make([]byte, length)
_, err := rand.Read(salt)
if err != nil {
return "", fmt.Errorf("生成盐值失败: %v", err)
}
return hex.EncodeToString(salt), nil
}
// DeriveKeyFromPassword 使用PBKDF2从密码派生密钥
// password: 原始密码
// saltHex: 十六进制格式的盐值
// iterations: 迭代次数,推荐至少10000次
// keyLength: 派生密钥的长度(字节)
func DeriveKeyFromPassword(password, saltHex string, iterations, keyLength int) (string, error) {
// 解码盐值
salt, err := hex.DecodeString(saltHex)
if err != nil {
return "", fmt.Errorf("盐值解码失败: %v", err)
}
// 使用PBKDF2派生密钥
key := pbkdf2.Key([]byte(password), salt, iterations, keyLength, sha256.New)
// 返回十六进制格式的密钥
return hex.EncodeToString(key), nil
}
// DeriveKeyFromPasswordWithRandomSalt 使用PBKDF2从密码派生密钥,并自动生成随机盐值
// password: 原始密码
// saltLength: 盐值长度(字节)
// iterations: 迭代次数,推荐至少10000次
// keyLength: 派生密钥的长度(字节)
// 返回值: 密钥(十六进制), 盐值(十六进制), 错误
func DeriveKeyFromPasswordWithRandomSalt(password string, saltLength, iterations, keyLength int) (string, string, error) {
// 生成随机盐值
saltHex, err := GenerateSalt(saltLength)
if err != nil {
return "", "", err
}
// 派生密钥
keyHex, err := DeriveKeyFromPassword(password, saltHex, iterations, keyLength)
if err != nil {
return "", "", err
}
return keyHex, saltHex, nil
}