67 lines
1.8 KiB
Go
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
|
|
}
|