This commit is contained in:
邹宗楠
2025-07-11 16:41:48 +08:00
parent 6d9c6a88fc
commit d50435775c
8 changed files with 253 additions and 110 deletions

View File

@@ -10,6 +10,7 @@ import (
"encoding/base64"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
"git.rosy.net.cn/baseapi/utils"
"github.com/tjfoc/gmsm/sm4"
@@ -164,6 +165,37 @@ func (a *API) signParamRSA(params map[string]interface{}, RSAPrivate string) (si
return authorization, nil
}
// signParamRSA 支付签名
func (a *API) signParamPrivateKey(params map[string]interface{}, RSAPrivate string) (sig string, err error) {
block, _ := pem.Decode([]byte(RSAPrivate))
private, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return "", err
}
// 签名参数
body, err := json.Marshal(params)
if err != nil {
return "", err
}
//bodyData := base64.StdEncoding.EncodeToString(body)
nonceStr := GenerateSecureRandomString(12)
timeStamp := utils.Int64ToStr(time.Now().Unix())
context := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n", a.appID, a.serialNo, timeStamp, nonceStr, string(body))
// 进行rsa加密签名
hashed := sha256.Sum256([]byte(context))
signedData, err := rsa.SignPKCS1v15(rand.Reader, private.(*rsa.PrivateKey), crypto.SHA256, hashed[:])
if err != nil {
return "", err
}
signData := base64.StdEncoding.EncodeToString(signedData)
authorization := fmt.Sprintf(`LKLAPI-SHA256withRSA appid="%s",serial_no="%s",timestamp="%s",nonce_str="%s",signature="%s"`, a.appID, a.serialNo, timeStamp, nonceStr, signData)
return authorization, nil
}
// GenerateSecureRandomString 获取随机字符串
func GenerateSecureRandomString(length int) string {
charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
@@ -234,3 +266,105 @@ func CallBackResultInfo(err error) *CallBackResult {
Message: err.Error(),
}
}
/****************************/
const (
MAX_ENCRYPT_BLOCK = 117
MAX_DECRYPT_BLOCK = 128
)
func EncryptByPrivateKey(data []byte, privateKeyStr string) (string, error) {
// 解析私钥
block, _ := pem.Decode([]byte(privateKeyStr))
if block == nil {
return "", errors.New("failed to parse PEM block")
}
privKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return "", err
}
rsaPrivateKey := privKey.(*rsa.PrivateKey)
// 分段加密
var encrypted []byte
for offset := 0; offset < len(data); offset += MAX_ENCRYPT_BLOCK {
end := offset + MAX_ENCRYPT_BLOCK
if end > len(data) {
end = len(data)
}
chunk, err := rsa.SignPKCS1v15(nil, rsaPrivateKey, 0, data[offset:end])
if err != nil {
return "", err
}
encrypted = append(encrypted, chunk...)
}
return base64.StdEncoding.EncodeToString(encrypted), nil
}
// DecryptByPublicKey 解密函数:分段解密(公钥解密,需手动实现模幂运算)
func DecryptByPublicKey(ciphertext []byte, publicKeyStr string) ([]byte, error) {
// 解析公钥
block, _ := pem.Decode([]byte(publicKeyStr))
if block == nil {
return nil, errors.New("failed to parse PEM block")
}
pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
rsaPublicKey := pubKey.(*rsa.PublicKey)
n := rsaPublicKey.N // 公钥模数
e := rsaPublicKey.E // 公钥指数
blockSize := rsaPublicKey.Size() // 密钥的字节长度128字节
var result bytes.Buffer
for len(ciphertext) > 0 {
blockLen := blockSize
if len(ciphertext) < blockLen {
blockLen = len(ciphertext)
}
block := ciphertext[:blockLen]
ciphertext = ciphertext[blockLen:]
// 将密文块转换为大整数
c := new(big.Int).SetBytes(block)
// 计算 m = c^e mod n (由于私钥加密公钥解密时需要e和n)
m := new(big.Int).Exp(c, big.NewInt(int64(e)), n)
// 将结果转换为字节数组,并补零到固定长度
mBytes := m.Bytes()
if len(mBytes) < blockSize {
padding := make([]byte, blockSize-len(mBytes))
mBytes = append(padding, mBytes...)
}
// 写入最终结果
result.Write(mBytes)
}
// 移除PKCS1v15填充需要实现填充剥离
// 注意此处简化实际需解析填充结构比如去除00 02和填充字节
return stripPKCS1v15Padding(result.Bytes()), nil
}
// 移除PKCS1v15填充示例逻辑需根据实际填充调整
func stripPKCS1v15Padding(data []byte) []byte {
var newData = make([]byte, 0, len(data))
for i := 0; i < len(data); i++ {
if data[i] == 0x01 || data[i] == 0xFF || data[i] == 0x00 {
continue
}
newData = append(newData, data[i])
}
return newData
}