Files
arenax-server/utility/rsa/rsa.go

127 lines
3.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package rsa
import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"os"
"sync"
"github.com/gogf/gf/v2/frame/g"
)
type rsaClient struct {
publicKey *rsa.PublicKey
privateKey *rsa.PrivateKey
}
var (
instance *rsaClient
once sync.Once
)
// init 会在包初始化时自动调用,用于加载默认的 RSA 公钥和私钥。
func init() {
ctx := context.Background()
once.Do(func() {
instance = &rsaClient{}
err := instance.loadKeys(g.Config().MustGet(ctx, "rsa.publickey").String(), g.Config().MustGet(ctx, "rsa.privatekey").String())
if err != nil {
panic("加载 RSA 密钥失败: " + err.Error())
}
})
}
// GetRsaClient 返回 RSA 客户端的单例实例。
//
// 通常用于执行加解密操作。
func GetRsaClient() *rsaClient {
return instance
}
// EncryptWithRsaPublicKey 使用加载的 RSA 公钥对原始数据进行加密。
//
// 参数:
// - plain: 待加密的明文数据。
//
// 返回值:
// - 加密后的密文数据。
// - 如果加密失败,则返回错误。
func (c *rsaClient) EncryptWithRsaPublicKey(plain []byte) ([]byte, error) {
if c.publicKey == nil {
return nil, errors.New("公钥未加载")
}
return rsa.EncryptPKCS1v15(rand.Reader, c.publicKey, plain)
}
// DecryptWithRsaPrivateKey 使用加载的 RSA 私钥对密文数据进行解密。
//
// 参数:
// - cipher: 加密后的密文数据。
//
// 返回值:
// - 解密后的明文数据。
// - 如果解密失败,则返回错误。
func (c *rsaClient) DecryptWithRsaPrivateKey(cipher []byte) ([]byte, error) {
if c.privateKey == nil {
return nil, errors.New("私钥未加载")
}
return rsa.DecryptPKCS1v15(rand.Reader, c.privateKey, cipher)
}
// loadKeys 从指定文件中加载 RSA 公钥和私钥。
//
// 参数:
// - publicKeyPath: 公钥 PEM 文件路径。
// - privateKeyPath: 私钥 PEM 文件路径。
//
// 返回值:
// - 成功返回 nil否则返回错误信息。
func (c *rsaClient) loadKeys(publicKeyPath, privateKeyPath string) error {
// 加载公钥
pubBytes, err := os.ReadFile(publicKeyPath)
if err != nil {
return err
}
pubBlock, _ := pem.Decode(pubBytes)
if pubBlock == nil {
return errors.New("无法解析公钥 PEM 文件")
}
pubKey, err := x509.ParsePKIXPublicKey(pubBlock.Bytes)
if err != nil {
return err
}
var ok bool
if c.publicKey, ok = pubKey.(*rsa.PublicKey); !ok {
return errors.New("公钥不是 RSA 公钥")
}
// 加载私钥
privBytes, err := os.ReadFile(privateKeyPath)
if err != nil {
return err
}
privBlock, _ := pem.Decode(privBytes)
if privBlock == nil {
return errors.New("无法解析私钥 PEM 文件")
}
// 尝试解析 PKCS#8 格式
privKey, err := x509.ParsePKCS8PrivateKey(privBlock.Bytes)
if err != nil {
// 回退尝试 PKCS#1 格式
privKey, err = x509.ParsePKCS1PrivateKey(privBlock.Bytes)
if err != nil {
return errors.New("解析私钥失败: 既不是 PKCS#8 也不是 PKCS#1 格式")
}
}
var ok2 bool
if c.privateKey, ok2 = privKey.(*rsa.PrivateKey); !ok2 {
return errors.New("私钥不是 RSA 私钥")
}
return nil
}