[🚀] v0.13.1

This commit is contained in:
2025-12-20 10:45:09 +08:00
parent 9dc56ebe60
commit fe341735dd

View File

@@ -6,6 +6,7 @@ import (
"crypto/x509" "crypto/x509"
"encoding/base64" "encoding/base64"
"encoding/pem" "encoding/pem"
"errors"
) )
var _ Public = (*rsaPub)(nil) var _ Public = (*rsaPub)(nil)
@@ -19,7 +20,6 @@ type Public interface {
type Private interface { type Private interface {
i() i()
Decrypt(decryptStr string) (string, error) Decrypt(decryptStr string) (string, error)
DecryptURLEncoding(decryptStr string) (string, error) DecryptURLEncoding(decryptStr string) (string, error)
} }
@@ -46,86 +46,260 @@ func NewPrivate(privateKey string) Private {
func (pub *rsaPub) i() {} func (pub *rsaPub) i() {}
func (pub *rsaPub) Encrypt(encryptStr string) (string, error) { // parsePublicKey 解析多种格式的公钥
// pem 解码 func parsePublicKey(pemData []byte) (*rsa.PublicKey, error) {
block, _ := pem.Decode([]byte(pub.PublicKey)) block, _ := pem.Decode(pemData)
if block == nil {
return nil, errors.New("failed to decode PEM block containing public key")
}
// x509 解码 // 检查PEM块类型
publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes) switch block.Type {
case "PUBLIC KEY": // PKIX/SPKI 格式 (Node.js生成的格式)
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
if rsaPub, ok := pub.(*rsa.PublicKey); ok {
return rsaPub, nil
}
return nil, errors.New("not an RSA public key")
case "RSA PUBLIC KEY": // PKCS#1 格式
return x509.ParsePKCS1PublicKey(block.Bytes)
default:
// 尝试自动检测格式
// 先尝试PKIX格式
if pub, err := x509.ParsePKIXPublicKey(block.Bytes); err == nil {
if rsaPub, ok := pub.(*rsa.PublicKey); ok {
return rsaPub, nil
}
}
// 再尝试PKCS#1格式
if pub, err := x509.ParsePKCS1PublicKey(block.Bytes); err == nil {
return pub, nil
}
return nil, errors.New("unsupported public key format: " + block.Type)
}
}
func (pub *rsaPub) Encrypt(encryptStr string) (string, error) {
publicKey, err := parsePublicKey([]byte(pub.PublicKey))
if err != nil { if err != nil {
return "", err return "", err
} }
// 类型断言 // 对明文进行加密
publicKey := publicKeyInterface.(*rsa.PublicKey)
//对明文进行加密
encryptedStr, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, []byte(encryptStr)) encryptedStr, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, []byte(encryptStr))
if err != nil { if err != nil {
return "", err return "", err
} }
//返回密文 // 返回密文
return base64.StdEncoding.EncodeToString(encryptedStr), nil return base64.StdEncoding.EncodeToString(encryptedStr), nil
} }
func (pub *rsaPub) EncryptURLEncoding(encryptStr string) (string, error) { func (pub *rsaPub) EncryptURLEncoding(encryptStr string) (string, error) {
// pem 解码 publicKey, err := parsePublicKey([]byte(pub.PublicKey))
block, _ := pem.Decode([]byte(pub.PublicKey))
// x509 解码
publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil { if err != nil {
return "", err return "", err
} }
// 类型断言 // 对明文进行加密
publicKey := publicKeyInterface.(*rsa.PublicKey)
//对明文进行加密
encryptedStr, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, []byte(encryptStr)) encryptedStr, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, []byte(encryptStr))
if err != nil { if err != nil {
return "", err return "", err
} }
//返回密文 // 返回密文
return base64.URLEncoding.EncodeToString(encryptedStr), nil return base64.URLEncoding.EncodeToString(encryptedStr), nil
} }
func (pri *rsaPri) i() {} func (pri *rsaPri) i() {}
func (pri *rsaPri) Decrypt(decryptStr string) (string, error) { // parsePrivateKey 解析多种格式的私钥
// pem 解码 func parsePrivateKey(pemData []byte) (*rsa.PrivateKey, error) {
block, _ := pem.Decode([]byte(pri.PrivateKey)) block, _ := pem.Decode(pemData)
if block == nil {
// X509 解码 return nil, errors.New("failed to decode PEM block containing private key")
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return "", err
} }
decryptBytes, err := base64.StdEncoding.DecodeString(decryptStr)
//对密文进行解密 // 检查PEM块类型
decrypted, _ := rsa.DecryptPKCS1v15(rand.Reader, privateKey, decryptBytes) switch block.Type {
case "RSA PRIVATE KEY": // PKCS#1 格式
return x509.ParsePKCS1PrivateKey(block.Bytes)
//返回明文 case "PRIVATE KEY": // PKCS#8 格式 (Node.js生成的格式)
return string(decrypted), nil priv, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
if rsaPriv, ok := priv.(*rsa.PrivateKey); ok {
return rsaPriv, nil
}
return nil, errors.New("not an RSA private key")
case "ENCRYPTED PRIVATE KEY": // 加密的PKCS#8格式
// 注意对于加密的PKCS#8私钥需要先解密
// 这里返回错误,建议用户先解密再使用
return nil, errors.New("encrypted private key detected. Please decrypt it first before using")
default:
// 尝试自动检测格式
// 先尝试PKCS#1格式
if priv, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil {
return priv, nil
}
// 再尝试PKCS#8格式
if priv, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil {
if rsaPriv, ok := priv.(*rsa.PrivateKey); ok {
return rsaPriv, nil
}
return nil, errors.New("not an RSA private key")
}
return nil, errors.New("unsupported private key format: " + block.Type)
}
}
func (pri *rsaPri) Decrypt(decryptStr string) (string, error) {
return pri.decryptInternal(decryptStr, base64.StdEncoding.DecodeString)
} }
func (pri *rsaPri) DecryptURLEncoding(decryptStr string) (string, error) { func (pri *rsaPri) DecryptURLEncoding(decryptStr string) (string, error) {
// pem 解码 return pri.decryptInternal(decryptStr, base64.URLEncoding.DecodeString)
block, _ := pem.Decode([]byte(pri.PrivateKey)) }
// X509 解码 // decryptInternal 内部解密方法
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) func (pri *rsaPri) decryptInternal(
decryptStr string,
decodeFunc func(string) ([]byte, error),
) (string, error) {
// 解析私钥
privateKey, err := parsePrivateKey([]byte(pri.PrivateKey))
if err != nil { if err != nil {
return "", err return "", err
} }
decryptBytes, err := base64.URLEncoding.DecodeString(decryptStr)
//对密文进行解密 // 解码Base64密文
decrypted, _ := rsa.DecryptPKCS1v15(rand.Reader, privateKey, decryptBytes) decryptBytes, err := decodeFunc(decryptStr)
if err != nil {
return "", err
}
//返回明文 // 对密文进行解密
decrypted, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, decryptBytes)
if err != nil {
return "", err
}
// 返回明文
return string(decrypted), nil return string(decrypted), nil
} }
// DetectKeyFormat 辅助函数:检测密钥格式并提供使用建议
func DetectKeyFormat(key string) (string, string, error) {
block, _ := pem.Decode([]byte(key))
if block == nil {
return "", "", errors.New("invalid PEM format")
}
var format string
var suggestion string
switch block.Type {
case "PUBLIC KEY":
if _, err := x509.ParsePKIXPublicKey(block.Bytes); err == nil {
format = "PKIX/SPKI Public Key"
suggestion = "可以直接使用"
} else {
format = "Unknown Public Key"
}
case "RSA PUBLIC KEY":
format = "PKCS#1 Public Key"
suggestion = "可以直接使用"
case "RSA PRIVATE KEY":
format = "PKCS#1 Private Key"
suggestion = "可以直接使用"
case "PRIVATE KEY":
// 尝试解析以确认是否是PKCS#8
if _, err := x509.ParsePKCS8PrivateKey(block.Bytes); err == nil {
format = "PKCS#8 Private Key"
suggestion = "可以直接使用兼容Node.js生成的格式"
} else {
format = "Unknown PKCS#8 Private Key"
}
case "ENCRYPTED PRIVATE KEY":
format = "Encrypted PKCS#8 Private Key"
suggestion = "请先使用OpenSSL解密openssl pkcs8 -in encrypted.pem -out decrypted.pem -nocrypt"
default:
format = "Unknown Key Type: " + block.Type
suggestion = "请转换为支持的格式"
}
return format, suggestion, nil
}
// ConvertPKCS8ToPKCS1 转换函数PKCS#8 转 PKCS#1如果需要
func ConvertPKCS8ToPKCS1(pkcs8Key string) (string, error) {
block, _ := pem.Decode([]byte(pkcs8Key))
if block == nil {
return "", errors.New("failed to decode PEM block")
}
if block.Type != "PRIVATE KEY" {
return "", errors.New("not a PKCS#8 private key")
}
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return "", err
}
rsaKey, ok := key.(*rsa.PrivateKey)
if !ok {
return "", errors.New("not an RSA private key")
}
// 编码为 PKCS#1
pkcs1Bytes := x509.MarshalPKCS1PrivateKey(rsaKey)
pkcs1Block := &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: pkcs1Bytes,
}
return string(pem.EncodeToMemory(pkcs1Block)), nil
}
// IsEncryptedKey 检查是否是加密私钥
func IsEncryptedKey(key string) bool {
block, _ := pem.Decode([]byte(key))
if block == nil {
return false
}
// 现代加密私钥使用 ENCRYPTED PRIVATE KEY 类型
return block.Type == "ENCRYPTED PRIVATE KEY"
}
// DecryptPrivateKey 解密加密私钥的辅助函数使用OpenSSL命令
func DecryptPrivateKey(encryptedKey, passphrase string) (string, error) {
if !IsEncryptedKey(encryptedKey) {
return "", errors.New("not an encrypted private key")
}
// 注意:这里只提供建议,实际解密应在外部进行
return "", errors.New(`请使用OpenSSL解密
openssl pkcs8 -in encrypted.pem -out decrypted.pem -passin pass:"` + passphrase + `"
或者使用编程方式在外部解密后再传入本库`)
}