调整 rsa 密钥解析函数
This commit is contained in:
@ -88,14 +88,15 @@ func (s *gamelifeClient) GetUserKeyIV(ctx context.Context, popenId string) (cach
|
||||
// base64编码
|
||||
base64Encode := encrypt.Base64Encode(key)
|
||||
// 向游戏人生发送请求
|
||||
result := struct {
|
||||
secret string `json:"secret"`
|
||||
key string `json:"key"` // 该用户的token,后续的账号绑定、登录态携带都需要此参数。
|
||||
}{}
|
||||
type httpResult struct {
|
||||
Secret string `json:"secret"`
|
||||
Key string `json:"key"` // 该用户的token,后续的账号绑定、登录态携带都需要此参数。
|
||||
}
|
||||
var result httpResult
|
||||
resp, err := resty.New().R().SetBody(map[string]string{
|
||||
"plat_id": s.PlatId,
|
||||
"key": base64Encode,
|
||||
}).SetResult(result).Post(s.keyivUrlMap[s.Mode])
|
||||
}).SetResult(&result).Post(s.keyivUrlMap[s.Mode])
|
||||
if err != nil {
|
||||
err = ecode.Fail.Sub("获取用户信息失败")
|
||||
return
|
||||
@ -107,7 +108,7 @@ func (s *gamelifeClient) GetUserKeyIV(ctx context.Context, popenId string) (cach
|
||||
|
||||
}
|
||||
|
||||
decode, err := encrypt.Base64Decode(result.secret)
|
||||
decode, err := encrypt.Base64Decode(result.Secret)
|
||||
if err != nil {
|
||||
err = ecode.Fail.Sub("解密用户信息失败")
|
||||
return
|
||||
@ -121,15 +122,15 @@ func (s *gamelifeClient) GetUserKeyIV(ctx context.Context, popenId string) (cach
|
||||
|
||||
}
|
||||
aesResult := struct {
|
||||
key string `json:"key"`
|
||||
iv string `json:"iv"`
|
||||
Key string `json:"key"`
|
||||
IV string `json:"iv"`
|
||||
}{}
|
||||
if err = json.Unmarshal(plain, &aesResult); err != nil {
|
||||
err = ecode.Fail.Sub("解密用户信息失败")
|
||||
return
|
||||
}
|
||||
|
||||
gamelifeCache := model.UserGamelifeCache{Aes: aesResult.key, IV: aesResult.iv, Token: result.key}
|
||||
gamelifeCache := model.UserGamelifeCache{Aes: aesResult.Key, IV: aesResult.IV, Token: result.Key}
|
||||
// 将用户的 aeskey 和 iv 存储到缓存当中,用于后续请求数据加密, 固定时间 2 小时同时不同用户加上一个随机时间
|
||||
if err = g.Redis().SetEX(ctx, fmt.Sprintf(consts.GameLifeUserKey, popenId), gamelifeCache, int64(consts.GameLifeUserExpire+grand.Intn(1000))); err != nil {
|
||||
err = ecode.Fail.Sub("设置用户信息失败")
|
||||
|
||||
@ -7,10 +7,11 @@ import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type rsaClient struct {
|
||||
@ -28,7 +29,7 @@ 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())
|
||||
err := instance.loadKeys(g.Config().MustGet(ctx, "gamelife.rsaKey").String())
|
||||
if err != nil {
|
||||
panic("加载 RSA 密钥失败: " + err.Error())
|
||||
}
|
||||
@ -80,47 +81,94 @@ func (c *rsaClient) DecryptWithRsaPrivateKey(cipher []byte) ([]byte, error) {
|
||||
//
|
||||
// 返回值:
|
||||
// - 成功返回 nil,否则返回错误信息。
|
||||
func (c *rsaClient) loadKeys(publicKeyPath, privateKeyPath string) error {
|
||||
// 加载公钥
|
||||
pubBytes, err := os.ReadFile(publicKeyPath)
|
||||
func (c *rsaClient) loadKeys(keyFilePath string) error {
|
||||
// 读取密钥文件
|
||||
keyBytes, err := os.ReadFile(keyFilePath)
|
||||
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 公钥")
|
||||
return fmt.Errorf("读取密钥文件失败: %w", err)
|
||||
}
|
||||
|
||||
// 加载私钥
|
||||
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 pubFound, privFound bool
|
||||
rest := keyBytes
|
||||
|
||||
for {
|
||||
var block *pem.Block
|
||||
block, rest = pem.Decode(rest)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
|
||||
// 转换为小写以匹配你的密钥格式
|
||||
blockTypeLower := strings.ToLower(block.Type)
|
||||
|
||||
switch blockTypeLower {
|
||||
case "rsa public key":
|
||||
// 尝试解析 PKCS#1 格式的公钥
|
||||
pubKey, err := x509.ParsePKCS1PublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
// 尝试 PKIX 格式(兼容性处理)
|
||||
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("无法解析 RSA 公钥: %w", err)
|
||||
}
|
||||
var ok bool
|
||||
if c.publicKey, ok = pub.(*rsa.PublicKey); !ok {
|
||||
return errors.New("解析的公钥不是 RSA 公钥")
|
||||
}
|
||||
} else {
|
||||
c.publicKey = pubKey
|
||||
}
|
||||
pubFound = true
|
||||
|
||||
case "rsa private key":
|
||||
// 解析 PKCS#1 格式的私钥
|
||||
privKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("无法解析 RSA 私钥: %w", err)
|
||||
}
|
||||
c.privateKey = privKey
|
||||
privFound = true
|
||||
|
||||
default:
|
||||
// 忽略未知的 PEM 块
|
||||
continue
|
||||
}
|
||||
}
|
||||
var ok2 bool
|
||||
if c.privateKey, ok2 = privKey.(*rsa.PrivateKey); !ok2 {
|
||||
return errors.New("私钥不是 RSA 私钥")
|
||||
|
||||
if !pubFound {
|
||||
return errors.New("未找到有效的 RSA 公钥")
|
||||
}
|
||||
if !privFound {
|
||||
return errors.New("未找到有效的 RSA 私钥")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncryptWithPublicKey 使用公钥加密数据
|
||||
func (c *rsaClient) EncryptWithPublicKey(plaintext []byte) ([]byte, error) {
|
||||
if c.publicKey == nil {
|
||||
return nil, errors.New("公钥未加载")
|
||||
}
|
||||
|
||||
// 使用 OAEP 填充进行加密
|
||||
ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, c.publicKey, plaintext)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("公钥加密失败: %w", err)
|
||||
}
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
// DecryptWithPrivateKey 使用私钥解密数据
|
||||
func (c *rsaClient) DecryptWithPrivateKey(ciphertext []byte) ([]byte, error) {
|
||||
if c.privateKey == nil {
|
||||
return nil, errors.New("私钥未加载")
|
||||
}
|
||||
|
||||
// 使用 OAEP 填充进行解密
|
||||
plaintext, err := rsa.DecryptPKCS1v15(rand.Reader, c.privateKey, ciphertext)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("私钥解密失败: %w", err)
|
||||
}
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user