This commit is contained in:
2026-03-13 15:51:59 +08:00
parent 4db2386bbf
commit 4e91f4cede
133 changed files with 19502 additions and 37 deletions

View File

@@ -0,0 +1,142 @@
package heepay
import (
"bytes"
"crypto/des"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"errors"
)
// EncryptRequest 使用 RSA+3DES 加密请求体
// 1. 生成随机 3DES 密钥24 字节)
// 2. 用 3DES-CBC 加密 JSON 请求体
// 3. 用汇元 RSA 公钥加密 3DES 密钥
func EncryptRequest(plaintext []byte, publicKeyPEM string) (encData string, encKey string, err error) {
pubKey, err := parseRSAPublicKey(publicKeyPEM)
if err != nil {
return "", "", err
}
// 生成 3DES 密钥
desKey := make([]byte, 24)
if _, err = rand.Read(desKey); err != nil {
return "", "", err
}
// 3DES 加密
ciphertext, err := tripleDesEncrypt(plaintext, desKey)
if err != nil {
return "", "", err
}
// RSA 加密 3DES 密钥
encKeyBytes, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, desKey)
if err != nil {
return "", "", err
}
encData = base64.StdEncoding.EncodeToString(ciphertext)
encKey = base64.StdEncoding.EncodeToString(encKeyBytes)
return
}
// DecryptResponse 使用 RSA 私钥 + 3DES 解密响应
func DecryptResponse(encData, encKey, privateKeyPEM string) ([]byte, error) {
privKey, err := parseRSAPrivateKey(privateKeyPEM)
if err != nil {
return nil, err
}
encKeyBytes, err := base64.StdEncoding.DecodeString(encKey)
if err != nil {
return nil, err
}
desKey, err := rsa.DecryptPKCS1v15(rand.Reader, privKey, encKeyBytes)
if err != nil {
return nil, err
}
ciphertext, err := base64.StdEncoding.DecodeString(encData)
if err != nil {
return nil, err
}
return tripleDesDecrypt(ciphertext, desKey)
}
// tripleDesEncrypt 3DES-CBC 加密PKCS5Padding
func tripleDesEncrypt(plaintext, key []byte) ([]byte, error) {
block, err := des.NewTripleDESCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
plaintext = pkcs5Padding(plaintext, blockSize)
iv := key[:blockSize] // 使用密钥前 8 字节作为 IV
mode := newCBCEncrypter(block, iv)
ciphertext := make([]byte, len(plaintext))
mode.CryptBlocks(ciphertext, plaintext)
return ciphertext, nil
}
// tripleDesDecrypt 3DES-CBC 解密
func tripleDesDecrypt(ciphertext, key []byte) ([]byte, error) {
block, err := des.NewTripleDESCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
iv := key[:blockSize]
mode := newCBCDecrypter(block, iv)
plaintext := make([]byte, len(ciphertext))
mode.CryptBlocks(plaintext, ciphertext)
return pkcs5Unpadding(plaintext)
}
func pkcs5Padding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(data, padText...)
}
func pkcs5Unpadding(data []byte) ([]byte, error) {
length := len(data)
if length == 0 {
return nil, errors.New("empty data")
}
padding := int(data[length-1])
if padding > length {
return nil, errors.New("invalid padding")
}
return data[:length-padding], nil
}
func parseRSAPublicKey(pemStr string) (*rsa.PublicKey, error) {
block, _ := pem.Decode([]byte(pemStr))
if block == nil {
return nil, errors.New("failed to decode PEM block")
}
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
rsaPub, ok := pub.(*rsa.PublicKey)
if !ok {
return nil, errors.New("not RSA public key")
}
return rsaPub, nil
}
func parseRSAPrivateKey(pemStr string) (*rsa.PrivateKey, error) {
block, _ := pem.Decode([]byte(pemStr))
if block == nil {
return nil, errors.New("failed to decode PEM block")
}
return x509.ParsePKCS1PrivateKey(block.Bytes)
}