API签名生成

# 签名统一生成规则

只有参数值参与签名, Key(参数名) 只进行排序,不参与签名计算

  1. 将所有非空参数的 Key(参数名) 按照 ASCII 排序
  2. 按 Key(参数名) 的顺序,逐个取参数值进并行拼接后,采用 RSA 算法对字符串计算,算出签名字符串

# 示例说明

  • 示例参数
参数 类型
merchantCode S82023000000000000001
orderType 0
method qrPay
orderNum T13748238583
payMoney 100
notifyUrl http://notifyUrl
dateTime 2099-99-99 01:01:01
  • 拼接字符串
  1. 首先把 Key(参数名) 按照ASCII排序
  2. 然后根据 Key(参数名) 排序后顺序取值并拼接成字符串

StrA = 2099-99-99 01:01:01S82023000000000000001qrPayhttp://notifyUrlT137482385830100

  • 计算签名
  1. 使用您在 TopPay商户后台 配置的密钥对
  2. 用您的 私钥(privateKey) 进行加密计算RSA(StrA)获取到最终的签名字符串

Sign = IMLn23c4orM+7pZhHoRmbjrol4X33jeAqFxbZuQ+pnznBIGhb6 ...

# 代码示例

import com.google.gson.JsonObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * TopPay RSA签名工具类
 * 
 * Author: TopPay
 */
public class TopPayRequestUtil {

    /**
     * 验证签名
     * 
     * @param params
     * @return
     */
    public static boolean verifySign(JsonObject params, String publickey) throws InvalidKeySpecException, NoSuchAlgorithmException {
        String platSign = params.remove("platSign").getAsString(); // 签名
        List<String> paramNameList = new ArrayList<>(params.keySet());
        Collections.sort(paramNameList);

        StringBuilder stringBuilder = new StringBuilder();
        for (String name : paramNameList) {
            stringBuilder.append(params.get(name).getAsString());
        }
        System.out.println("keys:" + stringBuilder);

        String decryptSign = publicDecrypt(platSign, getPublicKey(publickey));
        System.out.println("decryptSign:" + decryptSign);

        return stringBuilder.toString().equals(decryptSign);
    }

    /**
     * 私钥加密
     * 
     * @param data
     * @param privateKey
     * @return
     */
    public static String privateEncrypt(String data, RSAPrivateKey privateKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            return Base64.encodeBase64String(
                    rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes("UTF-8"), privateKey.getModulus().bitLength()));
        } catch (Exception e) {
            throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
        }
    }

    /**
     * 公钥解密
     * 
     * @param data
     * @param publicKey
     * @return
     */
    public static String publicDecrypt(String data, RSAPublicKey publicKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            return new String(
                    rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()),
                    "UTF-8");
        } catch (Exception e) {
            throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
        }
    }

    /**
     * 得到私钥
     * 
     * @param privateKey 密钥字符串(经过base64编码)
     */
    public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        // 通过PKCS#8编码的Key指令获得私钥对象
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
        RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
        return key;
    }

    /**
     * 得到公钥
     * 
     * @param publicKey 密钥字符串(经过base64编码)
     */
    public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        // 通过X509编码的Key指令获得公钥对象
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
        RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
        return key;
    }

    private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) {
        int maxBlock = 0;
        if (opmode == Cipher.DECRYPT_MODE) {
            maxBlock = keySize / 8;
        } else {
            maxBlock = keySize / 8 -11;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] buff;
        int i = 0;
        try {
            while (datas.length > offSet) {
                if (datas.length - offSet > maxBlock) {
                    buff = cipher.doFinal(datas, offSet, maxBlock);
                } else {
                    buff = cipher.doFinal(datas, offSet, datas.length - offSet);
                }
                out.write(buff, 0, buff.length);
                i++;
                offSet = i * maxBlock;
            }
        } catch (Exception e) {
            throw new RuntimeException("加解密阀值为[" + maxBlock + "]的数据时发生异常", e);
        }
        byte[] resultDatas = out.toByteArray();
        IOUtils.closeQuietly(out);
        return resultDatas;
    }

    public static String doPost(String url, String json) throws IOException {
        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(url);
        StringEntity s = new StringEntity(json);
        s.setContentEncoding("UTF-8");
        s.setContentType("application/json");//发送json数据需要设置contentType
        post.setEntity(s);
        HttpResponse res = client.execute(post);
        if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            return EntityUtils.toString(res.getEntity());// 返回json格式:

        }
        return null;
    }
}

<?php
header('Content-Type: text/html; charset=utf-8');
class Rsa{
    public function __construct($platPublicKey, $mchPrivateKey){
        // 从文件中读取公钥和私钥
       $this->publicKey = openssl_pkey_get_public($platPublicKey);
        if (!$this->publicKey) {
            die('Load public key error');
        }
        $this->privateKey = openssl_pkey_get_private($mchPrivateKey);
        if (!$this->privateKey) {
            die('Load private key error');
        }
    }

    //私钥加密数据
    public function pivate_key_encrypt($data){
        $crypto = '';
        foreach (str_split($data, 117) as $chunk) {
            openssl_private_encrypt($chunk, $encryptData, $this->privateKey);
            $crypto .= $encryptData;
        }
        return base64_encode($crypto); // 签名后的数据进行base64编码以便传输
    }

    //公钥解密签名数据
    public function public_key_decrypt($encryptedData){
        $encryptedData = base64_decode($encryptedData); // 解码收到的签名
        if ($encryptedData === false) {
            echo "Failed to base64 decode the data.\n";
            return false;
        }
        if (openssl_public_decrypt($encryptedData, $decrypted, $this->publicKey)) {
            return $decrypted; // 解密成功,返回解密后的数据
        } else {
            // 打印所有 OpenSSL 错误信息
            while ($msg = openssl_error_string()) {
                echo "OpenSSL Error: $msg\n";
            }
            return false; // 解密失败
        }
    }
}

//下述代码为调试代码
//请注意:请求数据加密使用商户私钥,解密通知使用平台公钥
//商户私钥
$mchPrivateKey = '-----BEGIN PRIVATE KEY-----'."\n".'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAK8ZBceS0SgKtD8Scxx5jhBVzXkofK9bV4/JiZKpkkL327iBx1vNhi66fDuSqx0gpZKM9Xqr/hxzzrrlk4W5QfxbyIUx06a4Y7RBFQi+J/T2GHJbJozsik8yVTb6jJ0BZaOBzwkWYNm3V1Zsy5o5L1HD3n3BQ6hCltArjIPfsGPTAgMBAAECgYBtrMS7/zBXXm0MXKgRm+nqPXRYgY2n4RT1kY1EekaM/+d2qIOQ8ykrN8/9GJ9pvTs4kmZokja256sD0i0XQ7UaLXYp31jTU4HlNpB8ixiCQG0gvldZRlLlGEeCeNrCQXT88dqC9mmvR7FIvS1sUnDonMZXEtJC8HOL4L80P52P0QJBAN3aovKYaCtmbtmYc76U+CqxyijRCxqV1Cb6u+YFY423FrFG2hXhdVu8UmgV+VvgT5lh0VQyKzVqRIdwk1hwzW8CQQDKDB8alSSBgcaEhlQkuTUjz4TwnYa5UhDuwzIs9FC2QLbBMa5alUiJDVlqVc33WzAHmGBJPRtMnnsGlgPeQiXdAkEAw9GVfjeTyqrxMNLlZtSqb1TaMUjCWkbhKT6q1w7unkl6mCMHn8SPB9ejjQfIP5Yv7Bxw3bYieVVBA6MUCz4VtQJAKju8aK8SMWvyFhOKFR8Np42iKTWUSrqHxZDRtSngkSgXy2xaGJ8pyVQcA6kp43GRKZVFUynNwgdCig7jghrrlQJBANfIE+D+PcFLSC8pRmX0sPhTLbuSFORgRzvpovW/FGXonNRp/yPWgIdXzpJKb40IFbbPEPjZtHKRJwSWWBDEfuk='."\n".'-----END PRIVATE KEY-----';
//平台公钥
$platPublicKey = '-----BEGIN PUBLIC KEY-----'."\n".'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvGQXHktEoCrQ/EnMceY4QVc15KHyvW1ePyYmSqZJC99u4gcdbzYYuunw7kqsdIKWSjPV6q/4cc8665ZOFuUH8W8iFMdOmuGO0QRUIvif09hhyWyaM7IpPMlU2+oydAWWjgc8JFmDZt1dWbMuaOS9Rw959wUOoQpbQK4yD37Bj0wIDAQAB'."\n".'-----END PUBLIC KEY-----';
//调用加解密工具类
$encryptionTool = new Rsa($platPublicKey, $mchPrivateKey);
$merchantCode = 'S820230414142102000012';
$orderType = '0';
$orderNum = 'TEST202404121503';
$money = '22.00';
$name = 'สวัสดี สวัสดี';
$name_ch = '测试';
$dateTime = date("YmdHis",time());
$params = array(
    'merchantCode' => $merchantCode,
    'orderType' => $orderType,
    'orderNum' => $orderNum,
    'money' => $money,
    'dateTime' => $dateTime,
    'name' => $name,
    'name_ch' => $name_ch,

);
//数据排序拼接
ksort($params);
$params_str = '';
foreach ($params as $key => $val) {
    $params_str = $params_str . $val;
}
$signature = $encryptionTool->pivate_key_encrypt($params_str);
$decryptedData = $encryptionTool->public_key_decrypt($signature);
echo "Data: " . $params_str . "<br>";
echo "Signature: " . $signature . "<br>";
echo "DecryptedData: " . $decryptedData . "<br>";
?>

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace demo.utils
{
    public class RSAForJava
    {

        public RSAForJava()
        {

        }
        /// <summary>
        /// KEY 结构体
        /// </summary>
        public struct RSAKEY
        {
            /// <summary>
            /// 公钥
            /// </summary>
            public string PublicKey
            {
                get;
                set;
            }
            /// <summary>
            /// 私钥
            /// </summary>
            public string PrivateKey
            {
                get;
                set;
            }
        }
        public RSAKEY GetKey()
        {
            //RSA密钥对的构造器
            RsaKeyPairGenerator keyGenerator = new RsaKeyPairGenerator();

            //RSA密钥构造器的参数
            RsaKeyGenerationParameters param = new RsaKeyGenerationParameters(
                Org.BouncyCastle.Math.BigInteger.ValueOf(3),
                new Org.BouncyCastle.Security.SecureRandom(),
                1024,   //密钥长度
                25);
            //用参数初始化密钥构造器
            keyGenerator.Init(param);
            //产生密钥对
            AsymmetricCipherKeyPair keyPair = keyGenerator.GenerateKeyPair();
            //获取公钥和密钥
            AsymmetricKeyParameter publicKey = keyPair.Public;
            AsymmetricKeyParameter privateKey = keyPair.Private;

            SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
            PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey);


            Asn1Object asn1ObjectPublic = subjectPublicKeyInfo.ToAsn1Object();

            byte[] publicInfoByte = asn1ObjectPublic.GetEncoded("UTF-8");
            Asn1Object asn1ObjectPrivate = privateKeyInfo.ToAsn1Object();
            byte[] privateInfoByte = asn1ObjectPrivate.GetEncoded("UTF-8");

            RSAKEY item = new RSAKEY()
            {
                PublicKey = Convert.ToBase64String(publicInfoByte),
                PrivateKey = Convert.ToBase64String(privateInfoByte)
            };
            return item;
        }
        private AsymmetricKeyParameter GetPublicKeyParameter(string s)
        {
            s = s.Replace("\r", "").Replace("\n", "").Replace(" ", "");
            byte[] publicInfoByte = Convert.FromBase64String(s);
            Asn1Object pubKeyObj = Asn1Object.FromByteArray(publicInfoByte);//这里也可以从流中读取,从本地导入
            AsymmetricKeyParameter pubKey = PublicKeyFactory.CreateKey(publicInfoByte);
            return pubKey;
        }
        private AsymmetricKeyParameter GetPrivateKeyParameter(string s)
        {
            s = s.Replace("\r", "").Replace("\n", "").Replace(" ", "");

            byte[] privateInfoByte = Convert.FromBase64String(s);
            // Asn1Object priKeyObj = Asn1Object.FromByteArray(privateInfoByte);//这里也可以从流中读取,从本地导入
            // PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey);
            AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(privateInfoByte);
            return priKey;
        }

        private static StreamReader GetStreamReader(string content)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(content);
            var memory = new MemoryStream(bytes);
            var reader = new StreamReader(memory);

            return reader;
        }

        public string EncryptByPrivateKey(string s, string key)
        {
            //非对称加密算法,加解密用
            IAsymmetricBlockCipher engine = new Pkcs1Encoding(new RsaEngine());
            //加密
            try
            {
                engine.Init(true, GetPrivateKeyParameter(key));
                byte[] byteData = System.Text.Encoding.UTF8.GetBytes(s);

                byte[] result = new byte[] { };
                for (int i = 0, j = byteData.Length / 117 + (byteData.Length % 117 == 0 ? 0 : 1); i < j; i++)
                {
                    byte[] getData = byteData.Skip(i * 117).Take(117).ToArray();
                    byte[] ResultData = engine.ProcessBlock(getData, 0, getData.Length);
                    result = result.Concat(ResultData).ToArray();
                }

                //var ResultData = engine.ProcessBlock(byteData, 0, byteData.Length);
                return Convert.ToBase64String(result);

                //Console.WriteLine("密文(base64编码):" + Convert.ToBase64String(testData) + Environment.NewLine);
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }
        public string DecryptByPublicKey(string s, string key)
        {
            s = s.Replace("\r", "").Replace("\n", "").Replace(" ", "");
            //非对称加密算法,加解密用
            IAsymmetricBlockCipher engine = new Pkcs1Encoding(new RsaEngine());

            //解密

            try
            {
                engine.Init(false, GetPublicKeyParameter(key));
                byte[] byteData = Convert.FromBase64String(s);

                string all = "";

                for (int i = 0, j = byteData.Length / 128 + (byteData.Length % 128 == 0 ? 0 : 1); i < j; i++)
                {
                    byte[] getData = byteData.Skip(i * 128).Take(128).ToArray();
                    byte[] ResultData = engine.ProcessBlock(getData, 0, getData.Length);
                    all += Encoding.UTF8.GetString(ResultData);
                }
                return all;
                //var ResultData = engine.ProcessBlock(byteData, 0, byteData.Length);
                //return System.Text.Encoding.UTF8.GetString(ResultData);

            }
            catch (Exception ex)
            {
                return ex.Message;

            }
        }
        /// <summary>
        /// 验证签名
        /// </summary>
        /// <param name="?"></param>
        /// <returns></returns>
        public bool verifySign(Dictionary<string, object> dict, string publickey)
        {
            string platSign = dict["platSign"].ToString().Trim(); // 签名
            List<string> paramNameList = new List<string>();
            foreach (string key in dict.Keys)
            {
                if (!"platSign".Equals(key))
                {
                    paramNameList.Add(key);
                }
            }
            paramNameList.Sort();
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < paramNameList.Count; i++)
            {
                string name = paramNameList[i];
                stringBuilder.Append(dict[name]);
            }

            String decryptSign = "";
            try
            {
                decryptSign = DecryptByPublicKey(platSign, publickey);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            if (!stringBuilder.ToString().Equals(decryptSign, StringComparison.OrdinalIgnoreCase))
            {
                return false;
            }
            return true;
        }
    }
}

package rsa_ext

import (
	"bytes"
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha512"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"errors"
	"hash"
	"io"
	"io/ioutil"
	"math/big"
	"os"
)

var (
	ErrNoPubKey        = errors.New("no pub key input")
	ErrDuplicatePubKey = errors.New("duplicate pub key specify")
	ErrNoPriKey        = errors.New("no pri key input")
	ErrDuplicatePriKey = errors.New("duplicate pri key specify")
	ErrNoPem           = errors.New("no pem")
	ErrDataToLarge     = errors.New("message too long for RSA public key size")
	ErrDataLen         = errors.New("data length error")
	ErrDataBroken      = errors.New("data broken, first byte is not zero")
	ErrKeyPairDismatch = errors.New("data is not encrypted by the private key")
	ErrDecryption      = errors.New("decryption error")
)

type Cryptor struct {
	pub     *rsa.PublicKey
	pri     *rsa.PrivateKey
	PubPath string //公钥地址
	PriPath string //私钥地址
	Pub64   string //公钥主题不含头尾
	Pri64   string //私钥主体不含头尾
}

func NewCryptor() *Cryptor {
    return &Cryptor{}
}

func (r *Cryptor) loadPubKey() {
	if r.pub != nil {
		return
	}
	if r.PubPath == "" && r.Pub64 == "" {
		panic(ErrNoPubKey)
	}
	if r.PubPath != "" && r.Pub64 != "" {
		panic(ErrDuplicatePubKey)
	}
	var keyByte []byte
	if r.PubPath != "" {
		keyByte = ReadFile(r.PubPath)
		block, _ := pem.Decode([]byte(keyByte))
		if block == nil {
			panic(ErrNoPem)
		}
		keyByte = block.Bytes
	}
	if r.Pub64 != "" {
		var err error
		keyByte, err = base64.StdEncoding.DecodeString(r.Pub64)
		CheckErr(err)
	}
	publicKeyInterface, err := x509.ParsePKIXPublicKey(keyByte)
	if err != nil {
		publicKeyInterface, err = x509.ParsePKCS1PublicKey(keyByte)
		CheckErr(err)
	}
	r.pub = publicKeyInterface.(*rsa.PublicKey)
}

func (r *Cryptor) loadPriKey() {
	if r.pri != nil {
		return
	}
	if r.PriPath == "" && r.Pri64 == "" {
		panic(ErrNoPriKey)
	}
	if r.PriPath != "" && r.Pri64 != "" {
		panic(ErrDuplicatePriKey)
	}
	var keyByte []byte
	if r.PriPath != "" {
		keyByte = ReadFile(r.PriPath)
		block, _ := pem.Decode([]byte(keyByte))
		if block == nil {
			panic(ErrNoPem)
		}
		keyByte = block.Bytes
	}
	if r.Pri64 != "" {
		var err error
		keyByte, err = base64.StdEncoding.DecodeString(r.Pri64)
		CheckErr(err)
	}
	privateKey, err := x509.ParsePKCS8PrivateKey(keyByte)
	if err != nil {
		privateKey, err = x509.ParsePKCS1PrivateKey(keyByte)
		CheckErr(err)
	}
	r.pri = privateKey.(*rsa.PrivateKey)
}

// 公钥加密
func (r *Cryptor) Encrypt(plainText []byte) []byte {
	r.loadPubKey()
	cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, r.pub, plainText)
	CheckErr(err)
	return cipherText
}

// 私钥解密
func (r *Cryptor) Decrypt(cipherText []byte) []byte {
	r.loadPriKey()
	plainText, _ := rsa.DecryptPKCS1v15(rand.Reader, r.pri, cipherText)
	return plainText
}

// 签名 默认SHA512
func (r *Cryptor) Sign(data []byte) []byte {
	return r.SignWithHash(data, sha512.New(), crypto.SHA512)
}

// 签名 指定Hash算法 hash和hashType要保持一直
func (r *Cryptor) SignWithHash(data []byte, h hash.Hash, hashType crypto.Hash) []byte {
	r.loadPriKey()
	h.Write([]byte(data))
	signature, err := rsa.SignPKCS1v15(rand.Reader, r.pri, hashType, h.Sum(nil))
	CheckErr(err)
	return signature
}

// 验签 默认sha512
func (r *Cryptor) Verify(data []byte, sign []byte) error {
	return r.VerifyWithHash(data, sign, sha512.New(), crypto.SHA512)
}

// 验签 指定Hash算法 hash和hashType要保持一直
func (r *Cryptor) VerifyWithHash(data []byte, sign []byte, h hash.Hash, hashType crypto.Hash) error {
	r.loadPubKey()
	h.Write(data)
	return rsa.VerifyPKCS1v15(r.pub, hashType, h.Sum(nil), sign)
}

func ReadFile(path string) []byte {
	file, err := os.Open(path)
	CheckErr(err)
	defer file.Close()
	info, err := file.Stat()
	CheckErr(err)
	buf := make([]byte, info.Size())
	_, err = file.Read(buf)
	CheckErr(err)
	return buf
}

// 私钥加密
func (r *Cryptor) PriEncrypt(input []byte) []byte {
	r.loadPriKey()
	output := bytes.NewBuffer(nil)
	err := priKeyIO(r.pri, bytes.NewReader(input), output, true)
	CheckErr(err)
	out, err := ioutil.ReadAll(output)
	CheckErr(err)
	return out
}

// 公钥解密
func (r *Cryptor) PubDecrypt(input []byte) []byte {
	r.loadPubKey()
	output := bytes.NewBuffer(nil)
	err := pubKeyIO(r.pub, bytes.NewReader(input), output, false)
	CheckErr(err)
	out, err := ioutil.ReadAll(output)
	CheckErr(err)
	return out
}

// 私钥加密或解密Reader
func priKeyIO(pri *rsa.PrivateKey, r io.Reader, w io.Writer, isEncrypt bool) (err error) {
	k := (pri.N.BitLen() + 7) / 8
	if isEncrypt {
		k = k - 11
	}
	buf := make([]byte, k)
	var b []byte
	size := 0
	for {
		size, err = r.Read(buf)
		if err != nil {
			if err == io.EOF {
				return nil
			}
			return err
		}
		if size < k {
			b = buf[:size]
		} else {
			b = buf
		}
		if isEncrypt {
			b, err = priKeyEncrypt(rand.Reader, pri, b)
		} else {
			b, err = rsa.DecryptPKCS1v15(rand.Reader, pri, b)
		}
		if err != nil {
			return err
		}
		if _, err = w.Write(b); err != nil {
			return err
		}
	}
}

// 公钥加密或解密Reader
func pubKeyIO(pub *rsa.PublicKey, in io.Reader, out io.Writer, isEncrytp bool) (err error) {
	k := (pub.N.BitLen() + 7) / 8
	if isEncrytp {
		k = k - 11
	}
	buf := make([]byte, k)
	var b []byte
	size := 0
	for {
		size, err = in.Read(buf)
		if err != nil {
			if err == io.EOF {
				return nil
			}
			return err
		}
		if size < k {
			b = buf[:size]
		} else {
			b = buf
		}
		if isEncrytp {
			b, err = rsa.EncryptPKCS1v15(rand.Reader, pub, b)
		} else {
			b, err = pubKeyDecrypt(pub, b)
		}
		if err != nil {
			return err
		}
		if _, err = out.Write(b); err != nil {
			return err
		}
	}
}

// 公钥解密
func pubKeyDecrypt(pub *rsa.PublicKey, data []byte) ([]byte, error) {
	k := (pub.N.BitLen() + 7) / 8
	if k != len(data) {
		return nil, ErrDataLen
	}
	m := new(big.Int).SetBytes(data)
	if m.Cmp(pub.N) > 0 {
		return nil, ErrDataToLarge
	}
	m.Exp(m, big.NewInt(int64(pub.E)), pub.N)
	d := leftPad(m.Bytes(), k)
	if d[0] != 0 {
		return nil, ErrDataBroken
	}
	if d[1] != 0 && d[1] != 1 {
		return nil, ErrKeyPairDismatch
	}
	var i = 2
	for ; i < len(d); i++ {
		if d[i] == 0 {
			break
		}
	}
	i++
	if i == len(d) {
		return nil, nil
	}
	return d[i:], nil
}

// 从crypto/rsa复制
func leftPad(input []byte, size int) (out []byte) {
	n := len(input)
	if n > size {
		n = size
	}
	out = make([]byte, size)
	copy(out[len(out)-n:], input)
	return
}

// 私钥加密
func priKeyEncrypt(rand io.Reader, priv *rsa.PrivateKey, hashed []byte) ([]byte, error) {
	tLen := len(hashed)
	k := (priv.N.BitLen() + 7) / 8
	if k < tLen+11 {
		return nil, ErrDataLen
	}
	em := make([]byte, k)
	em[1] = 1
	for i := 2; i < k-tLen-1; i++ {
		em[i] = 0xff
	}
	copy(em[k-tLen:k], hashed)
	m := new(big.Int).SetBytes(em)
	c, err := decrypt(rand, priv, m)
	if err != nil {
		return nil, err
	}
	copyWithLeftPad(em, c.Bytes())
	return em, nil
}

// 从crypto/rsa复制
var bigZero = big.NewInt(0)
var bigOne = big.NewInt(1)

func decrypt(random io.Reader, priv *rsa.PrivateKey, c *big.Int) (m *big.Int, err error) {
	if c.Cmp(priv.N) > 0 {
		err = ErrDecryption
		return
	}
	var ir *big.Int
	if random != nil {
		var r *big.Int

		for {
			r, err = rand.Int(random, priv.N)
			if err != nil {
				return
			}
			if r.Cmp(bigZero) == 0 {
				r = bigOne
			}
			var ok bool
			ir, ok = modInverse(r, priv.N)
			if ok {
				break
			}
		}
		bigE := big.NewInt(int64(priv.E))
		rpowe := new(big.Int).Exp(r, bigE, priv.N)
		cCopy := new(big.Int).Set(c)
		cCopy.Mul(cCopy, rpowe)
		cCopy.Mod(cCopy, priv.N)
		c = cCopy
	}
	if priv.Precomputed.Dp == nil {
		m = new(big.Int).Exp(c, priv.D, priv.N)
	} else {
		m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0])
		m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1])
		m.Sub(m, m2)
		if m.Sign() < 0 {
			m.Add(m, priv.Primes[0])
		}
		m.Mul(m, priv.Precomputed.Qinv)
		m.Mod(m, priv.Primes[0])
		m.Mul(m, priv.Primes[1])
		m.Add(m, m2)

		for i, values := range priv.Precomputed.CRTValues {
			prime := priv.Primes[2+i]
			m2.Exp(c, values.Exp, prime)
			m2.Sub(m2, m)
			m2.Mul(m2, values.Coeff)
			m2.Mod(m2, prime)
			if m2.Sign() < 0 {
				m2.Add(m2, prime)
			}
			m2.Mul(m2, values.R)
			m.Add(m, m2)
		}
	}
	if ir != nil {
		m.Mul(m, ir)
		m.Mod(m, priv.N)
	}

	return
}

// 从crypto/rsa复制
func modInverse(a, n *big.Int) (ia *big.Int, ok bool) {
	g := new(big.Int)
	x := new(big.Int)
	y := new(big.Int)
	g.GCD(x, y, a, n)
	if g.Cmp(bigOne) != 0 {
		return
	}
	if x.Cmp(bigOne) < 0 {
		x.Add(x, n)
	}
	return x, true
}

// 从crypto/rsa复制
func copyWithLeftPad(dest, src []byte) {
	numPaddingBytes := len(dest) - len(src)
	for i := 0; i < numPaddingBytes; i++ {
		dest[i] = 0
	}
	copy(dest[numPaddingBytes:], src)
}

func CheckErr(err error) {
	if err != nil {
		panic(err)
	}
}

from M2Crypto import RSA

# 生成RSA密钥对
rsa_key = RSA.gen_key(2048, 65537)

# 待加密的数据
data_to_encrypt = b'Hello, RSA!'

# 使用私钥加密数据
encrypted_data = rsa_key.private_encrypt(data_to_encrypt, RSA.pkcs1_padding)

# 使用公钥解密数据
try:
    decrypted_data = rsa_key.public_decrypt(encrypted_data, RSA.pkcs1_padding)
    print("Decrypted data:", decrypted_data)
except RSA.RSAError as e:
    print("RSAError:", e)

const crypto = require('crypto');

const nodeRSA = require('node-rsa');

// 该公私钥仅供示例,业务对接时,请使用真实密钥对
const privateKey = `-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKGFQO+Gu+a1Vc08jsYL7v2dKIitgAeFPSNDOyNBUnbH3IFFfk0lNGHZQ45pvicFMARshBDzR7jJynl/F+JYkQBoqFQIRVsEHMWkq3+3QapCjknNq+H2Vnd41swxaWy3lNTgN532ia04LBghWxCJo4/ZMBsUX8qCSTer1lvSsFkXAgMBAAECgYA7hPUWztly/KNvi78477DTuBP1uamSG+EZm26xYSLYLnHtGQSfvPP+kqc4VXMCwgCdwLcx39QwHfwEpXbRq71SiUHiiwaZncNIWLFiUzy23DDc6GlP5VPp/bCMWrIukE0zp4a4Il7Uq7smDAM1oZFv44PMJfX52iFdmO1DSKX0YQJBANOwqgt6AjVuBZErpe5bZdZAxXFR3utc2hcQza4XmK1bxrKK3IfK7qslyGc+OrW5HzCzBQM3M5tGAPmFDmalMg8CQQDDVEV29muQ9R1cLcAVMLPNeBkMwukLO0J/iJ4JN+hS8bcOdpdQ8pyaNqbUMpHkYKP0PhS2dcieAVRlVAj8mVB5AkBNH+9EESae2r/SfSmOJuR6Y8zLlX13GLQodSnKhLRObMJ+qBLism+0ESbrXoO7U3/mmUJ5QnJd3upZ/j0Z7pPHAkBQOXtyWdFiLxpI8s1yppciq9H2CNO4djVgthbaiGjWMErUGOcbKxogyJOKkd6T4xFTzm+pZQTpyHgGShaK0NlZAkBMst7KZNxDMwRTImCCi03GU42uKfpzK9pK3cjyU2eYftNXAfEmfB49uxXW839m9vYQvJBltYUbbsLsMdJBkrNT
-----END PRIVATE KEY-----`;

const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChhUDvhrvmtVXNPI7GC+79nSiIrYAHhT0jQzsjQVJ2x9yBRX5NJTRh2UOOab4nBTAEbIQQ80e4ycp5fxfiWJEAaKhUCEVbBBzFpKt/t0GqQo5Jzavh9lZ3eNbMMWlst5TU4Ded9omtOCwYIVsQiaOP2TAbFF/Kgkk3q9Zb0rBZFwIDAQAB
-----END PUBLIC KEY-----`;


// 使用私钥对消息进行加密(通常这是用于创建签名)
function encryptWithPrivateKey(data) {
    //将数据转换为Buffer
    const buffer = Buffer.from(data);
    //加密块的最大大小
    const maxBlockSize = 117; 
    let offset = 0;
    let encryptedBuffer = Buffer.alloc(0);
    //分块加密
    while (offset < buffer.length) {
        //获取当前块
        const block = buffer.slice(offset, Math.min(offset + maxBlockSize, buffer.length));
        //使用私钥进行加密
        const encryptedBlock = crypto.privateEncrypt(
            {
            key: privateKey,
            padding: crypto.constants.RSA_PKCS1_PADDING,
            },
            block
        );
        //将加密后的块加到结果Buffer上
        encryptedBuffer = Buffer.concat([encryptedBuffer, encryptedBlock]);
        //增加偏移量
        offset += block.length;
    }
    //转换为Base64编码
    return encryptedBuffer.toString('base64');
}



//使用公钥解密数据
function decryptWithPublicKey(signature) {
   const decryptedData = crypto.publicDecrypt(
    {
      key: publicKey,
      padding: crypto.constants.RSA_PKCS1_PADDING,
    },
    Buffer.from(signature, 'base64') // 解码Base64编码的加密数据
  );
  return decryptedData.toString();
}

// 导出加密函数供其他文件使用
module.exports = {
    encryptWithPrivateKey,
    decryptWithPublicKey,
}