生产证书操作说明
- 商户下载
证书生成工具
,使用工具生成商户的私钥(xxx.pfx)和公钥(xxx.cer) - 商户公钥(xxx.cer)提供给GEP技术支持,技术支持配置后会提供GEP公钥和证书编号
加密过程
按照接口文档中的
加密数据dataContent
列表参数组装JSON串明文然后对明文进行 BASE64编码
再使用 商户私钥(xxx.pfx) 进行 RSA加密 得到密文
解密过程
需对接口返回的结果信息
result
字段使用GEP公钥 进行 RSA解密然后进行BASE64解码后得到明文,
注:部分接口返回
result
不需解密,具体参考对应接口说明
加解密过程图解
加解密示例
若需使用PEM格式证书可使用在线转换工具 RSA证书转PEM
JAVA示例
示例说明:
RsaReadUtil.java
- 读取证书类,RsaCodingUtil.java
- RSA加解密类
- 私钥加密:
RsaCodingUtil.encryptByPriPfxFile
- 公钥解密:
RsaCodingUtil.decryptByPublicKey
RsaReadUtil.java
package com.baofoo.rsa;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Enumeration;
import sun.misc.BASE64Decoder;
/**
* <b>公私钥读取工具</b><br>
*
*/
public final class RsaReadUtil {
/**
* 根据Cer文件读取公钥
*
* @param pubCerPath
* @return
*/
public static PublicKey getPublicKeyFromFile(String pubCerPath) {
FileInputStream pubKeyStream = null;
try {
pubKeyStream = new FileInputStream(pubCerPath);
byte[] reads = new byte[pubKeyStream.available()];
pubKeyStream.read(reads);
return getPublicKeyByText(new String(reads));
} catch (FileNotFoundException e) {
// //log.error("公钥文件不存在:", e);
} catch (IOException e) {
// log.error("公钥文件读取失败:", e);
} finally {
if (pubKeyStream != null) {
try {
pubKeyStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
/**
* 根据公钥Cer文本串读取公钥
*
* @param pubKeyText
* @return
*/
public static PublicKey getPublicKeyByText(String pubKeyText) {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
BufferedReader br = new BufferedReader(new StringReader(pubKeyText));
String line = null;
StringBuilder keyBuffer = new StringBuilder();
while ((line = br.readLine()) != null) {
if (!line.startsWith("-")) {
keyBuffer.append(line);
}
}
Certificate certificate = certificateFactory.generateCertificate(new ByteArrayInputStream(new BASE64Decoder().decodeBuffer(keyBuffer.toString())));
return certificate.getPublicKey();
} catch (Exception e) {
// log.error("解析公钥内容失败:", e);
}
return null;
}
/**
* 根据私钥路径读取私钥
*
* @param pfxPath
* @param priKeyPass
* @return
*/
public static PrivateKey getPrivateKeyFromFile(String pfxPath, String priKeyPass) {
InputStream priKeyStream = null;
try {
priKeyStream = new FileInputStream(pfxPath);
byte[] reads = new byte[priKeyStream.available()];
priKeyStream.read(reads);
return getPrivateKeyByStream(reads, priKeyPass);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (priKeyStream != null) {
try {
priKeyStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
/**
* 根据PFX私钥字节流读取私钥
*
* @param pfxBytes
* @param priKeyPass
* @return
*/
public static PrivateKey getPrivateKeyByStream(byte[] pfxBytes, String priKeyPass) {
try {
KeyStore ks = KeyStore.getInstance("PKCS12");
char[] charPriKeyPass = priKeyPass.toCharArray();
ks.load(new ByteArrayInputStream(pfxBytes), charPriKeyPass);
Enumeration<String> aliasEnum = ks.aliases();
String keyAlias = null;
if (aliasEnum.hasMoreElements()) {
keyAlias = (String) aliasEnum.nextElement();
}
return (PrivateKey) ks.getKey(keyAlias, charPriKeyPass);
} catch (IOException e) {
// 加密失败
// log.error("解析文件,读取私钥失败:", e);
} catch (KeyStoreException e) {
// log.error("私钥存储异常:", e);
} catch (NoSuchAlgorithmException e) {
// log.error("不存在的解密算法:", e);
} catch (CertificateException e) {
// log.error("证书异常:", e);
} catch (UnrecoverableKeyException e) {
// log.error("不可恢复的秘钥异常", e);
}
return null;
}
}
RsaCodingUtil.java
package com.baofoo.rsa;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import com.baofoo.util.FormatUtil;
/**
* <b>Rsa加解密工具</b><br>
* <br>
* 公钥采用X509,Cer格式的<br>
* 私钥采用PKCS12加密方式的PFX私钥文件<br>
*/
public final class RsaCodingUtil {
// ======================================================================================
// 公钥加密私钥解密段
// ======================================================================================
/**
* 指定Cer公钥路径加密
*
* @param src
* @param pubCerPath
* @return hex串
*/
public static String encryptByPubCerFile(String src, String pubCerPath) {
PublicKey publicKey = RsaReadUtil.getPublicKeyFromFile(pubCerPath);
if (publicKey == null) {
return null;
}
return encryptByPublicKey(src, publicKey);
}
/**
* 用公钥内容加密
*
* @param src
* @param pubKeyText
* @return hex串
*/
public static String encryptByPubCerText(String src, String pubKeyText) {
PublicKey publicKey = RsaReadUtil.getPublicKeyByText(pubKeyText);
if (publicKey == null) {
return null;
}
return encryptByPublicKey(src, publicKey);
}
/**
* 公钥加密返回
*
* @param src
* @param publicKey
* @param encryptMode
* @return hex串
*/
public static String encryptByPublicKey(String src, PublicKey publicKey) {
byte[] destBytes = rsaByPublicKey(src.getBytes(), publicKey, Cipher.ENCRYPT_MODE);
if (destBytes == null) {
return null;
}
return FormatUtil.byte2Hex(destBytes);
}
/**
* 根据私钥文件解密
*
* @param src
* @param pfxPath
* @param priKeyPass
* @return
*/
public static String decryptByPriPfxFile(String src, String pfxPath, String priKeyPass) {
if (FormatUtil.isEmpty(src) || FormatUtil.isEmpty(pfxPath)) {
return null;
}
PrivateKey privateKey = RsaReadUtil.getPrivateKeyFromFile(pfxPath, priKeyPass);
if (privateKey == null) {
return null;
}
return decryptByPrivateKey(src, privateKey);
}
/**
* 根据私钥文件流解密
*
* @param src
* @param pfxPath
* @param priKeyPass
* @return
*/
public static String decryptByPriPfxStream(String src, byte[] pfxBytes, String priKeyPass) {
if (FormatUtil.isEmpty(src)) {
return null;
}
PrivateKey privateKey = RsaReadUtil.getPrivateKeyByStream(pfxBytes, priKeyPass);
if (privateKey == null) {
return null;
}
return decryptByPrivateKey(src, privateKey);
}
/**
* 私钥解密
*
* @param src
* @param privateKey
* @return
*/
public static String decryptByPrivateKey(String src, PrivateKey privateKey) {
if (FormatUtil.isEmpty(src)) {
return null;
}
try {
byte[] destBytes = rsaByPrivateKey(FormatUtil.hex2Bytes(src), privateKey, Cipher.DECRYPT_MODE);
if (destBytes == null) {
return null;
}
return new String(destBytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
// //log.error("解密内容不是正确的UTF8格式:", e);
} catch (Exception e) {
// //log.error("解密内容异常", e);
}
return null;
}
// ======================================================================================
// 私钥加密公钥解密
// ======================================================================================
/**
* 根据私钥文件加密
*
* @param src
* @param pfxPath
* @param priKeyPass
* @return
*/
public static String encryptByPriPfxFile(String src, String pfxPath, String priKeyPass) {
PrivateKey privateKey = RsaReadUtil.getPrivateKeyFromFile(pfxPath, priKeyPass);
if (privateKey == null) {
return null;
}
return encryptByPrivateKey(src, privateKey);
}
/**
* 根据私钥文件流加密
*
* @param src
* @param pfxPath
* @param priKeyPass
* @return
*/
public static String encryptByPriPfxStream(String src, byte[] pfxBytes, String priKeyPass) {
PrivateKey privateKey = RsaReadUtil.getPrivateKeyByStream(pfxBytes, priKeyPass);
if (privateKey == null) {
return null;
}
return encryptByPrivateKey(src, privateKey);
}
/**
* 根据私钥加密
*
* @param src
* @param privateKey
*/
public static String encryptByPrivateKey(String src, PrivateKey privateKey) {
byte[] destBytes = rsaByPrivateKey(src.getBytes(), privateKey, Cipher.ENCRYPT_MODE);
if (destBytes == null) {
return null;
}
return FormatUtil.byte2Hex(destBytes);
}
/**
* 指定Cer公钥路径解密
*
* @param src
* @param pubCerPath
* @return
*/
public static String decryptByPubCerFile(String src, String pubCerPath) {
PublicKey publicKey = RsaReadUtil.getPublicKeyFromFile(pubCerPath);
if (publicKey == null) {
System.out.println("证书读取失败");
return null;
}
return decryptByPublicKey(src, publicKey);
}
/**
* 根据公钥文本解密
*
* @param src
* @param pubKeyText
* @return
*/
public static String decryptByPubCerText(String src, String pubKeyText) {
PublicKey publicKey = RsaReadUtil.getPublicKeyByText(pubKeyText);
if (publicKey == null) {
return null;
}
return decryptByPublicKey(src, publicKey);
}
/**
* 根据公钥解密
*
* @param src
* @param publicKey
* @return
*/
public static String decryptByPublicKey(String src, PublicKey publicKey) {
try {
byte[] destBytes = rsaByPublicKey(FormatUtil.hex2Bytes(src), publicKey, Cipher.DECRYPT_MODE);
if (destBytes == null) {
return null;
}
return new String(destBytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
// //log.error("解密内容不是正确的UTF8格式:", e);
e.printStackTrace();
}
return null;
}
// ======================================================================================
// 公私钥算法
// ======================================================================================
/**
* 公钥算法
*
* @param srcData 源字节
* @param publicKey 公钥
* @param mode 加密 OR 解密
* @return
*/
public static byte[] rsaByPublicKey(byte[] srcData, PublicKey publicKey, int mode) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(mode, publicKey);
// 分段加密
int blockSize = (mode == Cipher.ENCRYPT_MODE) ? cipher.getOutputSize(srcData.length) - 11
: cipher.getOutputSize(srcData.length);
byte[] encryptedData = null;
for (int i = 0; i < srcData.length; i += blockSize) {
// 注意要使用2的倍数,否则会出现加密后的内容再解密时为乱码
byte[] doFinal = cipher.doFinal(subarray(srcData, i, i + blockSize));
encryptedData = addAll(encryptedData, doFinal);
}
System.out.println("-------解密成功--------");
return encryptedData;
} catch (NoSuchAlgorithmException e) {
System.out.println("公钥算法-不存在的解密算法:" + e);
// //log.error("公钥算法-不存在的解密算法:", e);
} catch (NoSuchPaddingException e) {
System.out.println("公钥算法-无效的补位算法:" + e);
// //log.error("公钥算法-无效的补位算法:", e);
} catch (IllegalBlockSizeException e) {
System.out.println("公钥算法-无效的块大小:" + e);
// //log.error("公钥算法-无效的块大小:", e);
} catch (BadPaddingException e) {
System.out.println("公钥算法-补位算法异常:" + e);
// //log.error("公钥算法-补位算法异常:", e);
} catch (InvalidKeyException e) {
System.out.println("公钥算法-无效的私钥:" + e);
// //log.error("公钥算法-无效的私钥:", e);
}
return null;
}
/**
* 私钥算法
*
* @param srcData 源字节
* @param privateKey 私钥
* @param mode 加密 OR 解密
* @return
*/
public static byte[] rsaByPrivateKey(byte[] srcData, PrivateKey privateKey, int mode) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(mode, privateKey);
// 分段加密
int blockSize = (mode == Cipher.ENCRYPT_MODE) ? cipher.getOutputSize(srcData.length) - 11
: cipher.getOutputSize(srcData.length);
byte[] decryptData = null;
for (int i = 0; i < srcData.length; i += blockSize) {
byte[] doFinal = cipher.doFinal(subarray(srcData, i, i + blockSize));
decryptData = addAll(decryptData, doFinal);
}
return decryptData;
} catch (NoSuchAlgorithmException e) {
// //log.error("私钥算法-不存在的解密算法:", e);
} catch (NoSuchPaddingException e) {
// log.error("私钥算法-无效的补位算法:", e);
} catch (IllegalBlockSizeException e) {
// log.error("私钥算法-无效的块大小:", e);
} catch (BadPaddingException e) {
// log.error("私钥算法-补位算法异常:", e);
} catch (InvalidKeyException e) {
// log.error("私钥算法-无效的私钥:", e);
}
return null;
}
// /////////////==========================
public static byte[] subarray(byte[] array, int startIndexInclusive, int endIndexExclusive) {
if (array == null) {
return null;
}
if (startIndexInclusive < 0) {
startIndexInclusive = 0;
}
if (endIndexExclusive > array.length) {
endIndexExclusive = array.length;
}
int newSize = endIndexExclusive - startIndexInclusive;
if (newSize <= 0) {
return new byte[0];
}
byte[] subarray = new byte[newSize];
System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
return subarray;
}
public static byte[] addAll(byte[] array1, byte[] array2) {
if (array1 == null) {
return clone(array2);
} else if (array2 == null) {
return clone(array1);
}
byte[] joinedArray = new byte[array1.length + array2.length];
System.arraycopy(array1, 0, joinedArray, 0, array1.length);
System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
return joinedArray;
}
public static byte[] clone(byte[] array) {
if (array == null) {
return null;
}
return (byte[]) array.clone();
}
}
PHP示例
- 私钥加密:
encryptByPFXFile
- 公钥解密:
decryptByCERFile
RSAUtil.php
<?php
/**
* Company: www.baofu.com
* @date 2023年2月20日
* 新增1024与2048兼容加解密
*/
class RSAUtil{
/**
* 读取私钥
* @param type $PfxPath
* @param type $PrivateKPASS
* @return array
* @throws Exception
*/
private static function getPriveKey($PfxPath,$PrivateKPASS){
try {
if(!file_exists($PfxPath)) {
throw new Exception("私钥文件不存在!路径:".$PfxPath);
}
$PKCS12 = file_get_contents($PfxPath);
$PrivateKey = array();
if(openssl_pkcs12_read($PKCS12, $PrivateKey, $PrivateKPASS)){
return $PrivateKey["pkey"];
}else{
throw new Exception("私钥证书读取出错!原因[证书或密码不匹配],请检查本地证书相关信息。");
}
} catch (Exception $ex) {
$ex->getTrace();
}
}
/**
* 读取公钥
* @param type $PublicPath
* @return type
* @throws Exception
*/
private static function getPublicKey($PublicPath){
try {
if(!file_exists($PublicPath)) {
throw new Exception("公钥文件不存在!路径:".$PublicPath);
}
$KeyFile = file_get_contents($PublicPath);
$PublicKey = openssl_get_publickey($KeyFile);
if(empty($PublicKey)){
throw new Exception("公钥不可用!路径:".$PublicPath);
}
return $PublicKey;
} catch (Exception $ex) {
$ex->getTraceAsString();
}
}
/**
* 公钥加密
* @param type $Data 加密数据
* @param type $PfxPath 私钥路径
* @param type $PrivateKPASS 私钥密码
* @return type
* @throws Exception
*/
public static function encryptByCERFile($Data,$PublicPath){
try {
if (!function_exists( 'bin2hex')) {
throw new Exception("bin2hex PHP5.4及以上版本支持此函数,也可自行实现!");
}
$KeyObj = self::getPublicKey($PublicPath);
$BASE64EN_DATA = base64_encode($Data);
$EncryptStr = "";
$blockSize = self::get_Key_Size($KeyObj,false);
if($blockSize<=0){
throw new Exception("BlockSize is 0");
}else{
$blockSize = $blockSize/8-11;
}
$totalLen = strlen($BASE64EN_DATA);
$EncryptSubStarLen = 0;
$EncryptTempData="";
while ($EncryptSubStarLen < $totalLen){
openssl_public_encrypt(substr($BASE64EN_DATA, $EncryptSubStarLen, $blockSize), $EncryptTempData, $KeyObj);
$EncryptStr .= bin2hex($EncryptTempData);
$EncryptSubStarLen += $blockSize;
}
return $EncryptStr;
} catch (Exception $exc) {
echo $exc->getTraceAsString();
}
}
/**
* 私钥加密
* @param type $Data
* @param type $PfxPath
* @param type $PrivateKPASS
* @return type
* @throws Exception
*/
public static function encryptByPFXFile($Data,$PfxPath,$PrivateKPASS){
try {
if (!function_exists( 'bin2hex')) {
throw new Exception("bin2hex PHP5.4及以上版本支持此函数,也可自行实现!");
}
$KeyObj = self::getPriveKey($PfxPath,$PrivateKPASS);
$BASE64EN_DATA = base64_encode($Data);
$EncryptStr = "";
$blockSize = self::get_Key_Size($KeyObj);
if($blockSize<=0){
throw new Exception("BlockSize is 0");
}else{
$blockSize = $blockSize/8-11;//分段
}
$totalLen = strlen($BASE64EN_DATA);
$EncryptSubStarLen = 0;
$EncryptTempData="";
while ($EncryptSubStarLen < $totalLen){
openssl_private_encrypt(substr($BASE64EN_DATA, $EncryptSubStarLen, $blockSize), $EncryptTempData, $KeyObj);
$EncryptStr .= bin2hex($EncryptTempData);
$EncryptSubStarLen += $blockSize;
}
return $EncryptStr;
} catch (Exception $exc) {
echo $exc->getTraceAsString();
}
}
/**
* 私钥解密
* @param type $Data 解密数据
* @param type $PublicPath 解密公钥路径
* @return type
* @throws Exception
*/
public static function decryptByPFXFile($Data,$PfxPath,$PrivateKPASS){
try {
if (!function_exists( 'hex2bin')) {
throw new Exception("hex2bin PHP5.4及以上版本支持此函数,也可自行实现!");
}
$KeyObj = self::getPriveKey($PfxPath,$PrivateKPASS);
$blockSize = self::get_Key_Size($KeyObj);
if($blockSize<=0){
throw new Exception("BlockSize is 0");
}else{
$blockSize = $blockSize/4;
}
$DecryptRsult="";
$totalLen = strlen($Data);
$EncryptSubStarLen = 0;
$DecryptTempData="";
while ($EncryptSubStarLen < $totalLen) {
openssl_private_decrypt(hex2bin(substr($Data, $EncryptSubStarLen, $blockSize)), $DecryptTempData, $KeyObj);
$DecryptRsult .= $DecryptTempData;
$EncryptSubStarLen += $blockSize;
}
return base64_decode($DecryptRsult);
} catch (Exception $exc) {
echo $exc->getTraceAsString();
}
}
/**
* 公钥解密
* @param type $Data
* @param type $PublicPath
* @return type
* @throws Exception
*/
public static function decryptByCERFile($Data,$PublicPath) {
try {
if (!function_exists( 'hex2bin')) {
throw new Exception("hex2bin PHP5.4及以上版本支持此函数,也可自行实现!");
}
$KeyObj = self::getPublicKey($PublicPath);
$DecryptRsult="";
$blockSize = self::get_Key_Size($KeyObj,false);
if($blockSize<=0){
throw new Exception("BlockSize is 0");
}else{
$blockSize = $blockSize/4;
}
$totalLen = strlen($Data);
$EncryptSubStarLen = 0;
$DecryptTempData="";
while ($EncryptSubStarLen < $totalLen) {
openssl_public_decrypt(hex2bin(substr($Data, $EncryptSubStarLen, $blockSize)), $DecryptTempData, $KeyObj);
$DecryptRsult .= $DecryptTempData;
$EncryptSubStarLen += $blockSize;
}
return base64_decode($DecryptRsult);
} catch (Exception $exc) {
echo $exc->getTraceAsString();
}
}
/**
* 获取证书长度
* @param type $Key_String
* @param type $Key_Type
* @return int
* @throws Exception
*/
private static function get_Key_Size($Key_String,$Key_Type=true){
$Key_Temp=array();
try{
if($Key_Type){//私钥
$Key_Temp = openssl_pkey_get_details(openssl_pkey_get_private($Key_String));
}else if(openssl_pkey_get_public($Key_String)){//公钥
$Key_Temp = openssl_pkey_get_details(openssl_pkey_get_public($Key_String));
}else{
throw new Exception("Is not a key");
}
IF(array_key_exists("bits",$Key_Temp)){
return $Key_Temp["bits"];
}else{
return 0;
}
} catch (Exception $ex){
$ex->getTrace();
return 0;
}
}
}
.NET示例
示例需用到
BouncyCastle
包,可以使用NuGet引用;RsaReadUtil.cs
-证书读取类,RSAUtil.cs
-RSA加解密类
- 私钥加密:
EncryptRSAByPfx
- 公钥解密:
DecryptRSAByCer
RsaReadUtil.cs
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Pkix;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.Utilities.Encoders;
namespace SecurityUtil
{
/**
* <b>Rsa加解密工具</b><br>
* <br>
* 公钥采用X509,Cer格式<br>
* 私钥采用PKCS12加密方式的PFX私钥文件<br>
* 加密算法为1024位的RSA\工作模式ECB\填充算法为PKCS1Padding<br>
*
* @author 宝付_大圣
* @version 1.0
* 宝付网络科技(上海)有限公司
* 引用加密动态库 BouncyCastle.Crypto.dll(必要)
*/
class RsaReadUtil
{
/*
*
==================读取私钥==========================
* path 证书路径
*
* pwd 证书密码
*
*/
public static AsymmetricKeyParameter getPrivateKeyFromFile( string path,string pwd)
{
FileStream fs = File.OpenRead(path); //path路径下证书
char[] passwd = pwd.ToCharArray();
Pkcs12Store store = new Pkcs12StoreBuilder().Build();
store.Load(fs, passwd); //加载证书
string alias = null;
foreach (string str in store.Aliases)
{
if (store.IsKeyEntry(str))
alias = str;
}
AsymmetricKeyEntry keyEntry = store.GetKey(alias);
return keyEntry.Key;
}
/*
==================读取公钥==========================
*
* path 证书路径
*
*/
public static AsymmetricKeyParameter getPublicKeyFromFile(string path)
{
StreamReader sr = new StreamReader(path);
String line = null;
StringBuilder keyBuffer = new StringBuilder();
while ((line = sr.ReadLine()) != null)
{
if (!line.StartsWith("-"))
{
keyBuffer.Append(line);
}
}
if (String.IsNullOrEmpty(keyBuffer.ToString().Trim()))
{
throw new Exception("公钥读取异常[keyBuffer=null or Empty]");
}
X509Certificate CerObj = new X509CertificateParser().ReadCertificate(Base64.Decode(keyBuffer.ToString()));
return CerObj.GetPublicKey();
}
}
}
RSAUtil.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto;
using SecurityUtil;
namespace SecurityUtil
{
/**
* <b>Rsa加解密工具</b><br>
* <br>
* 公钥采用X509,Cer格式<br>
* 私钥采用PKCS12加密方式的PFX私钥文件<br>
* 加密算法为1024位的RSA\工作模式ECB\填充算法为PKCS1Padding<br>
*
* @author 宝付_大圣
* @version 1.0
* 宝付网络科技(上海)有限公司
* 开源加密方法BouncYCastle
*/
public class RSAUtil
{
public static String EncryptRSAByCer(string src, string path)
{
try
{
AsymmetricKeyParameter PrivteKey = RsaReadUtil.getPublicKeyFromFile(path);//读取公钥
byte[] string64 = Base64.Encode(System.Text.Encoding.UTF8.GetBytes(src));//Base64编码 字符编码UF8
String HEX = Hex.ToHexString(RSAEDCore(string64, PrivteKey, true));//加密并转成十六进制
return HEX;
}
catch (Exception ex)
{
return "{[本地加密异常][EncryptRSAByPfx][" + ex.Message + "]}";
}
}
public static string EncryptRSAByPfx(string src, string path, string passwd)
{
try
{
AsymmetricKeyParameter PrivteKey = RsaReadUtil.getPrivateKeyFromFile(path, passwd);//读取私钥
byte[] string64 = Base64.Encode(System.Text.Encoding.UTF8.GetBytes(src));//Base64编码 字符编码UF8
// Log.LogWrite("【Base64编码】" + System.Text.Encoding.UTF8.GetString(string64));
string HEX = Hex.ToHexString(RSAEDCore(string64, PrivteKey, true));//加密并转成十六进制
return HEX;
}
catch (Exception ex)
{
return "{[本地加密异常][EncryptRSAByPfx][" + ex.Message + "]}";
}
}
public static String DecryptRSAByPfx(string src, string path, string passwd)
{
try
{
AsymmetricKeyParameter PublicKey = RsaReadUtil.getPrivateKeyFromFile(path, passwd);//读取私钥
byte[] HEXbyte = Hex.Decode(src);
byte[] DecryString = RSAEDCore(HEXbyte, PublicKey, false);
return System.Text.Encoding.UTF8.GetString(Base64.Decode(DecryString));
}catch(Exception ex)
{
return "{[本地解密异常][DecryptRSAByCer][" + ex.Message + "]}";
}
}
public static string DecryptRSAByCer(string src, string path)
{
try
{
AsymmetricKeyParameter PublicKey = RsaReadUtil.getPublicKeyFromFile(path);//读取公钥
byte[] HEXbyte = Hex.Decode(src);
byte[] DecryString = RSAEDCore(HEXbyte, PublicKey, false);
return System.Text.Encoding.UTF8.GetString(Base64.Decode(DecryString));
}
catch (Exception ex)
{
return "{[本地解密异常][DecryptRSAByCer][" + ex.Message + "]}";
}
}
/*加密核心
* Src加密内容
*
* PFXorCER 证书
*
* Mode 加密或解密 true OR false
*/
private static byte[] RSAEDCore(byte[] Src,AsymmetricKeyParameter PFXorCER,bool Mode)
{
IAsymmetricBlockCipher engine = new RsaEngine();
IBufferedCipher Cipher = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");//加密标准
Cipher.Init(Mode, PFXorCER);//初始加密程序
byte[] EDString = null;
int blockSize = Cipher.GetBlockSize();//获取分段长度
for (int i = 0; i < Src.Length; i += blockSize)
{
byte[] outBytes = Cipher.DoFinal(Subarray(Src, i, i + blockSize));//数据加密
EDString = AddAll(EDString, outBytes);
}
return EDString;
}
/*
* 数据分块算法
*
* array:源长度
*
* startIndexInclusive:开始长度
*
* endIndexExclusive:结束长度
*
*/
private static byte[] Subarray(byte[] array, int startIndexInclusive, int endIndexExclusive)
{
if (array == null)
{
throw new IOException("byte[] array内容为空!异常:subarray(byte[],int,int)");
}
if (endIndexExclusive > array.Length)
{
endIndexExclusive = array.Length;
}
int newSize = endIndexExclusive - startIndexInclusive;
if (newSize <= 0)
{
return new byte[0];
}
byte[] subarray = new byte[newSize];
Array.Copy(array, startIndexInclusive, subarray, 0, newSize);
return subarray;
}
/*
* 数据拼接
*
* array1
*
* array2
*
* AddAll=array1+array2
*/
public static byte[] AddAll(byte[] array1, byte[] array2)
{
if (array1 == null)
{
return Clone(array2);
}
else if (array2 == null)
{
return Clone(array1);
}
byte[] joinedArray = new byte[array1.Length + array2.Length];
Array.Copy(array1, 0, joinedArray, 0, array1.Length);
Array.Copy(array2, 0, joinedArray, array1.Length, array2.Length);
return joinedArray;
}
/*
*=======================================
*/
public static byte[] Clone(byte[] array)
{
if (array == null)
{
return null;
}
return (byte[])array.Clone() ;
}
}
}
PYTHON示例
RSAUtil.py
"""
-------------------------------------------------
File Name: RSAUtil
Description: PYTHON-RSA 加密/解密、加签/验签
Author: CANGMU
date: 2024/5/27
-------------------------------------------------
"""
import base64
import binascii
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.serialization import pkcs12
from rsa import pkcs1, core, transform, PrivateKey, PublicKey, sign, verify, VerificationError
class RSAUtil:
@staticmethod
def load_key(cert_file_path, password=None):
"""Load a private or public key from a certificate file."""
try:
with open(cert_file_path, 'rb') as f:
cert_data = f.read()
if cert_file_path.endswith(('.pfx', '.p12')):
private_key, _, _ = pkcs12.load_key_and_certificates(
cert_data,
password.encode() if password else None,
backend=default_backend()
)
return PrivateKey.load_pkcs1(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
))
else:
certificate = x509.load_pem_x509_certificate(cert_data, backend=default_backend())
return PublicKey.load_pkcs1_openssl_pem(certificate.public_key().public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
))
except Exception as e:
print(f"Error loading key: {e}")
return None
@staticmethod
def _chunk_data(data, chunk_size):
"""Yield successive chunks from the input data."""
for i in range(0, len(data), chunk_size):
yield data[i:i + chunk_size]
@staticmethod
def pri_encrypt(encrypt_text, pfx_path, pfxpass):
"""Encrypt data using a private key."""
key = RSAUtil.load_key(pfx_path, pfxpass)
key_length = key.n.bit_length() // 8
block_size = key_length - 11
encrypt_text_base64 = base64.b64encode(encrypt_text.encode('utf-8'))
encrypted_data = b''
for chunk in RSAUtil._chunk_data(encrypt_text_base64, block_size):
chunk = pkcs1._pad_for_signing(chunk, key_length)
num = transform.bytes2int(chunk)
encrypted = core.encrypt_int(num, key.d, key.n)
encrypted_bytes = transform.int2bytes(encrypted)
# 确保加密数据填充前导零以匹配密钥长度
pad_length = key_length - len(encrypted_bytes)
padded_data = b'\x00' * pad_length + encrypted_bytes
encrypted_data += padded_data
return encrypted_data.hex()
@staticmethod
def pub_decrypt(decrypt_text, cer_path):
"""Decrypt data using a public key."""
key = RSAUtil.load_key(cer_path)
block_size = key.n.bit_length() // 8
decrypt_text_unhex = binascii.unhexlify(decrypt_text)
decrypted_data = b''
for chunk in RSAUtil._chunk_data(decrypt_text_unhex, block_size):
num = transform.bytes2int(chunk)
decrypted_int = core.decrypt_int(num, key.e, key.n)
decrypted_data += transform.int2bytes(decrypted_int)
return base64.b64decode(decrypted_data).decode('utf-8')
@staticmethod
def pub_encrypt(encrypt_text, cer_path):
"""Encrypt data using a public key."""
key = RSAUtil.load_key(cer_path)
block_size = key.n.bit_length() // 8 - 11
encrypted_data = b''
for chunk in RSAUtil._chunk_data(base64.b64encode(encrypt_text.encode('utf-8')), block_size):
encrypted_data += pkcs1.encrypt(chunk, key)
return encrypted_data.hex()
@staticmethod
def pri_decrypt(decrypt_text, pfx_path, pfxpass):
"""Decrypt data using a private key."""
key = RSAUtil.load_key(pfx_path, pfxpass)
block_size = key.n.bit_length() // 8
decrypted_data = b''
for chunk in RSAUtil._chunk_data(binascii.unhexlify(decrypt_text), block_size):
decrypted_data += pkcs1.decrypt(chunk, key)
return base64.b64decode(decrypted_data).decode('utf-8')
@staticmethod
def pri_sign(sign_text, algorithm_name, pfx_path, pfxpass):
"""Sign data using a private key and the specified hash algorithm."""
key = RSAUtil.load_key(pfx_path, pfxpass)
return sign(sign_text.encode('utf-8'), key, algorithm_name).hex()
@staticmethod
def pub_verify(data, sign_text, cer_path):
"""Verify a signature using a public key and the specified hash algorithm."""
key = RSAUtil.load_key(cer_path)
try:
verify(data.encode('utf-8'), binascii.unhexlify(sign_text), key)
return True
except VerificationError:
return False
@staticmethod
def pri_sha1_sign(sign_text, pfx_path, pfxpass):
return RSAUtil.pri_sign(sign_text, 'SHA-1', pfx_path, pfxpass)
@staticmethod
def pub_sha1_verify(data, sign_text, cer_path):
return RSAUtil.pub_verify(data, sign_text, cer_path)
@staticmethod
def pri_sha256_sign(sign_text, pfx_path, pfxpass):
return RSAUtil.pri_sign(sign_text, 'SHA-256', pfx_path, pfxpass)
@staticmethod
def pub_sha256_verify(data, sign_text, cer_path):
return RSAUtil.pub_verify(data, sign_text, cer_path)
# Example usage
if __name__ == '__main__':
test_data = 'send_time=2018-01-24 13:25:33&msg_id=456795112&version=4.0.0.0&123=100000949&txn_type=03&member_id=100000749&dgtl_envlp=5a9c3ac419735d249e319727c89cfc0ce4a80d6a954980eaf3ea934316a56a121c758b0d13bf3302b877a8dd68619db&user_id=123'
pfx_path1 = 'D:\\cert\\BAOFU20240612_pri.pfx'
pfx_psw1 = '123456'
cer_path1 = 'D:\\cert\\BAOFU20240612_pub1.cer'
pfx_path = 'D:\\cert\\key_5181200731000138828@@2103031802000005106.pfx'
pfx_psw = '5181200731000138828_190684'
cer_path = 'D:\\cert\\key_5181200731000138828@@2103031802000005106.cer'
pri_encrypted = RSAUtil.pri_encrypt(test_data, pfx_path, pfx_psw)
print("Private key encryption:", pri_encrypted)
decrypted = RSAUtil.pub_decrypt(pri_encrypted, cer_path)
print("Public key decryption:", decrypted)
pub_encrypted = RSAUtil.pub_encrypt(test_data, cer_path)
print("Public key encryption:", pub_encrypted)
decrypted_pri = RSAUtil.pri_decrypt(pub_encrypted, pfx_path, pfx_psw)
print("Private key decryption:", decrypted_pri)
sha256_sign_str = RSAUtil.pri_sha256_sign(test_data, pfx_path, pfx_psw)
print("Private key sign-sha256:", sha256_sign_str)
sha256_verify = RSAUtil.pub_sha256_verify(test_data, sha256_sign_str, cer_path)
print("Public key verify-sha256:", sha256_verify)
sha1_sign_str = RSAUtil.pri_sha1_sign(test_data, pfx_path, pfx_psw)
print("Private key sign-sha1:", sha1_sign_str)
sha1_verify = RSAUtil.pub_sha1_verify(test_data, sha1_sign_str, cer_path)
print("Public key verify-sha1:", sha1_verify)
NODEJS示例
更新说明:
- 2024-5-27 创建nodejs 加解密示例
- 2024-12-23 优化读取证书方法loadCert,兼容1024和2048证书的读取
- 私钥加密:
privateEncrypt
- 公钥解密:
publicDecrypt
RSAUtil.js
const fs = require('fs');
const forge = require('node-forge');
const crypto = require('crypto');
// 读取和解析证书(PFX 和 CER)
function loadCert(filePath, password = null, isPfx = false) {
const certBuffer = fs.readFileSync(filePath, 'binary');
let cert, key, blocks;
try{
if (isPfx) {
// 解析 PFX 文件
const pfxAsn1 = forge.asn1.fromDer(certBuffer);
const pfx = forge.pkcs12.pkcs12FromAsn1(pfxAsn1, password);
pfx.safeContents.forEach((safeContent) => {
safeContent.safeBags.forEach((safeBag) => {
if (safeBag.type === forge.pki.oids.pkcs8ShroudedKeyBag) {
key = safeBag.key;
} else if (safeBag.type === forge.pki.oids.certBag) {
cert = safeBag.cert;
}
});
});
if (!key) {
throw new Error('Private key not found in PFX file.');
}
blocks = key.n.toString(16).length / 2;
return { pem: forge.pki.privateKeyToPem(key), blocks };
} else {
// 解析 CER 文件
cert = forge.pki.certificateFromPem(certBuffer);
const publicKey = cert.publicKey;
blocks = publicKey.n.toString(16).length / 2;
return { pem: forge.pki.publicKeyToPem(publicKey), blocks };
}
} catch (error) {
throw new Error(`Failed to parse file ${filePath}: ${error.message}`);
}
}
// 使用 RSA 公钥加密
function publicEncrypt(data, cerPath) {
const { pem, blocks } = loadCert(cerPath, null, false);
const input = Buffer.from(data, 'utf8');
return encrypt(input, pem, blocks, crypto.publicEncrypt);
}
// 使用 RSA 私钥解密
function privateDecrypt(data, pfxPath, pfxPass) {
const { pem, blocks } = loadCert(pfxPath, pfxPass, true);
const input = Buffer.from(data, 'hex');
return decrypt(input, pem, blocks, crypto.privateDecrypt);
}
// 使用 RSA 私钥加密
function privateEncrypt(data, pfxPath, pfxPass) {
const { pem, blocks } = loadCert(pfxPath, pfxPass, true);
const input = Buffer.from(data, 'utf8');
return encrypt(input, pem, blocks, crypto.privateEncrypt);
}
// 使用 RSA 公钥解密
function publicDecrypt(data, cerPath) {
const { pem, blocks } = loadCert(cerPath, null, false);
const input = Buffer.from(data, 'hex');
return decrypt(input, pem, blocks, crypto.publicDecrypt);
}
// 通用加密函数
function encrypt(input, pem, blocks, encryptFunc) {
const encrypted = [];
for (let i = 0; i < input.length; i += (blocks - 11)) {
encrypted.push(encryptFunc(
{ key: pem, padding: crypto.constants.RSA_PKCS1_PADDING },
input.subarray(i, i + (blocks - 11))
));
}
return Buffer.concat(encrypted).toString('hex');
}
// 通用解密函数
function decrypt(input, pem, blocks, decryptFunc) {
const decrypted = [];
for (let i = 0; i < input.length; i += blocks) {
decrypted.push(decryptFunc(
{ key: pem, padding: crypto.constants.RSA_PKCS1_PADDING },
input.subarray(i, i + blocks)
));
}
return Buffer.concat(decrypted).toString('utf8');
}
// 创建签名
function createSign(data, pfxPath, pfxPass, algorithm) {
const sign = crypto.createSign(algorithm);
sign.update(data);
sign.end();
const { pem } = loadCert(pfxPath, pfxPass, true);
return sign.sign(pem).toString('hex');
}
// 验证签名
function verifySign(data, sign, cerPath, algorithm) {
const { pem } = loadCert(cerPath, null, false);
const verify = crypto.createVerify(algorithm);
verify.update(data);
verify.end();
return verify.verify(pem, Buffer.from(sign, 'hex'));
}
// 使用 RSA-SHA1 创建签名
function createSignSHA1(data, pfxPath, pfxPass) {
return createSign(data, pfxPath, pfxPass, 'RSA-SHA1');
}
// 使用 RSA-SHA1 验证签名
function verifySignSHA1(data, sign, cerPath) {
return verifySign(data, sign, cerPath, 'RSA-SHA1');
}
// 使用 RSA-SHA256 创建签名
function createSignSHA256(data, pfxPath, pfxPass) {
return createSign(data, pfxPath, pfxPass, 'RSA-SHA256');
}
// 使用 RSA-SHA256 验证签名
function verifySignSHA256(data, sign, cerPath) {
return verifySign(data, sign, cerPath, 'RSA-SHA256');
}
module.exports = {
publicEncrypt,
privateDecrypt,
privateEncrypt,
publicDecrypt,
createSignSHA1,
verifySignSHA1,
createSignSHA256,
verifySignSHA256
};
//----------------------------------------------------------------------------------------------------
const pfxpath = "D:\\cert\\BAOFU20240612_pri.pfx";
const cerpath = "D:\\cert\\BAOFU20240612_pub1.cer";
const pfxPass = "123456";
const pfxpath1 = "D:\\cert\\key_5181200731000138828@@2103031802000005106.pfx";
const cerpath1 = "D:\\cert\\key_5181200731000138828@@2103031802000005106.cer";
const pfxPass1 = "5181200731000138828_190684";
// 测试数据
const testData = 'send_time=2018-01-24 13:25:33&msg_id=456795112&version=4.0.0.0&123=100000949&txn_type=03&member_id=100000749&dgtl_envlp=5a9c3ac419735d249e319727c89cfc0ce4a80d6a954980eaf3ea934316a56a121c758b0d13bf3302b877a8dd68619db&user_id=123';
console.log("-------------String-------------:", testData);
// 测试加密和解密
const encryptedStr = publicEncrypt(testData, cerpath);
console.log("-------------Encrypted String-------------:", encryptedStr);
const decryptedStr = privateDecrypt(encryptedStr, pfxpath, pfxPass);
console.log("-------------Decrypted String-------------:", decryptedStr);
// 测试私钥加密和公钥解密
const priEncryptedStr = privateEncrypt(testData, pfxpath, pfxPass);
console.log("-------------Private Encrypted String-------------:", priEncryptedStr);
const pubDecryptedStr = publicDecrypt(priEncryptedStr, cerpath);
console.log("-------------Public Decrypted String-------------:", pubDecryptedStr);
// 测试签名和验签
const signatureStr = createSignSHA1(testData, pfxpath, pfxPass);
console.log("-------------Signature SHA1-------------:", signatureStr);
const isVerified = verifySignSHA1(testData, signatureStr, cerpath);
console.log("-------------Verification SHA1 Result-------------:", isVerified);
const signatureStr1 = createSignSHA256(testData, pfxpath, pfxPass);
console.log("-------------Signature SHA256-------------:", signatureStr1);
const isVerified1 = verifySignSHA256(testData, signatureStr1, cerpath);
console.log("-------------Verification SHA256 Result-------------:", isVerified1);
GOLANG示例
- 私钥加密
- 公钥解密
RSAUtil.go
package main
import (
"bytes"
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"encoding/pem"
"errors"
"fmt"
"io"
"math/big"
"os"
"golang.org/x/crypto/pkcs12"
)
var (
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")
ErrPublicKey = errors.New("get public key error")
ErrPrivateKey = errors.New("get private key error")
)
func LoadPrivateKey(privateKeyName, privatePassword string) (*rsa.PrivateKey, error) {
bytes, err := readFile(privateKeyName)
if err != nil {
return nil, err
}
blocks, err := pkcs12.ToPEM(bytes, privatePassword)
if err != nil {
return nil, err
}
// 寻找私钥块
var privBlock *pem.Block
for _, block := range blocks {
if block.Type == "PRIVATE KEY" {
privBlock = block
break
}
}
if privBlock == nil {
return nil, errors.New("failed to find PRIVATE KEY block")
}
// 尝试解析私钥
privInterface, err := parsePrivateKey(privBlock.Bytes)
if err != nil {
return nil, err
}
// 转换为 RSA 私钥
priv, ok := privInterface.(*rsa.PrivateKey)
if !ok {
return nil, errors.New("failed to convert private key to RSA format")
}
return priv, nil
}
// parsePrivateKey 解析私钥
func parsePrivateKey(data []byte) (interface{}, error) {
// 尝试解析为 PKCS#8 私钥
priv, err := x509.ParsePKCS8PrivateKey(data)
if err == nil {
return priv, nil
}
// 尝试解析为 EC 私钥
privEC, err := x509.ParseECPrivateKey(data)
if err == nil {
return privEC, nil
}
// 尝试解析为 PKCS#1 私钥
privRSA, err := x509.ParsePKCS1PrivateKey(data)
if err == nil {
return privRSA, nil
}
return nil, errors.New("failed to parse private key")
}
func LoadPublicKey(publicName string) (*rsa.PublicKey, error) {
bytes, err := readFile(publicName)
if err != nil {
return nil, err
}
block, _ := pem.Decode(bytes)
if block == nil {
return nil, errors.New("failed to decode PEM block containing public key")
}
x509Cer, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, err
}
publicKey, ok := x509Cer.PublicKey.(*rsa.PublicKey)
if !ok {
return nil, errors.New("failed to assert type *rsa.PublicKey")
}
return publicKey, nil
}
func EncryptWithPrivateKey(data, pfxpath, pfxpass string) (string, error) {
privateKey, err := LoadPrivateKey(pfxpath, pfxpass)
if err != nil {
return "", err
}
baseData := base64.StdEncoding.EncodeToString([]byte(data))
return encryptDecryptWithPrivateKey(privateKey, baseData, true)
}
func DecryptWithPublicKey(data, pubpath string) (string, error) {
dataByte, err := hex.DecodeString(data)
if err != nil {
return "", err
}
publicKey, err := LoadPublicKey(pubpath)
if err != nil {
return "", err
}
return encryptDecryptWithPublicKey(publicKey, dataByte, false)
}
func EncryptWithPublicKey(data, cerpath string) (string, error) {
publicKey, err := LoadPublicKey(cerpath)
if err != nil {
return "", err
}
baseData := base64.StdEncoding.EncodeToString([]byte(data))
return encryptDecryptWithPublicKey(publicKey, []byte(baseData), true)
}
func DecryptWithPrivateKey(data, pripath, pfxpass string) (string, error) {
dataByte, err := hex.DecodeString(data)
if err != nil {
return "", err
}
privateKey, err := LoadPrivateKey(pripath, pfxpass)
if err != nil {
return "", err
}
return encryptDecryptWithPrivateKey(privateKey, string(dataByte), false)
}
func SignSha1WithRsa(data, pripath, pfxpass string) (string, error) {
privateKey, err := LoadPrivateKey(pripath, pfxpass)
if err != nil {
return "", err
}
sha1Hash := sha1.New()
sha1Hash.Write([]byte(data))
hashed := sha1Hash.Sum(nil)
signByte, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA1, hashed)
return hex.EncodeToString(signByte), err
}
func VerifySignSha1WithRsa(data, signData, cerpath string) error {
publicKey, err := LoadPublicKey(cerpath)
if err != nil {
return err
}
sign, err := hex.DecodeString(signData)
if err != nil {
return err
}
hash := sha1.New()
hash.Write([]byte(data))
return rsa.VerifyPKCS1v15(publicKey, crypto.SHA1, hash.Sum(nil), sign)
}
func pubKeyIO(pub *rsa.PublicKey, in io.Reader, out io.Writer, isEncrypt bool) error {
k := (pub.N.BitLen() + 7) / 8
if isEncrypt {
k -= 11
}
buf := make([]byte, k)
var b []byte
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 isEncrypt {
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 priKeyIO(pri *rsa.PrivateKey, in io.Reader, out io.Writer, isEncrypt bool) error {
k := (pri.N.BitLen() + 7) / 8
if isEncrypt {
k -= 11
}
buf := make([]byte, k)
var b []byte
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 isEncrypt {
b, err = priKeyEncrypt(rand.Reader, pri, b)
} else {
b, err = rsa.DecryptPKCS1v15(rand.Reader, pri, 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
}
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
}
func encryptDecryptWithPrivateKey(privateKey *rsa.PrivateKey, data string, isEncrypt bool) (string, error) {
out := bytes.NewBuffer(nil)
in := bytes.NewReader([]byte(data))
if err := priKeyIO(privateKey, in, out, isEncrypt); err != nil {
return "", err
}
result, err := io.ReadAll(out)
if err != nil {
return "", err
}
if isEncrypt {
return hex.EncodeToString(result), nil
}
dataBs, err := base64.StdEncoding.DecodeString(string(result))
if err != nil {
return "", err
}
return string(dataBs), nil
}
func encryptDecryptWithPublicKey(publicKey *rsa.PublicKey, data []byte, isEncrypt bool) (string, error) {
out := bytes.NewBuffer(nil)
in := bytes.NewReader(data)
if err := pubKeyIO(publicKey, in, out, isEncrypt); err != nil {
return "", err
}
result, err := io.ReadAll(out)
if err != nil {
return "", err
}
if isEncrypt {
return hex.EncodeToString(result), nil
}
dataBs, err := base64.StdEncoding.DecodeString(string(result))
if err != nil {
return "", err
}
return string(dataBs), nil
}
func readFile(fileName string) ([]byte, error) {
return os.ReadFile(fileName)
}
func leftPad(input []byte, length int) []byte {
if len(input) >= length {
return input
}
padding := make([]byte, length-len(input))
return append(padding, input...)
}
func copyWithLeftPad(dst, src []byte) {
copy(dst[len(dst)-len(src):], src)
}
func decrypt(random io.Reader, priv *rsa.PrivateKey, c *big.Int) (*big.Int, error) {
if c.Cmp(priv.N) > 0 {
return nil, ErrDecryption
}
var ir *big.Int
if priv.Precomputed.Dp == nil {
ir = 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)
ir = m
}
return ir, nil
}
func main() {
fmt.Println("RSA Encryption Decryption Example")
plaintext := `{
"header": {
"memberId": "102004465",
"serviceTp": "T-1001-013-01",
"verifyType": "1",
"terminalId": "102004465"
},
"body": {
"version": "4.1.0",
"accType": 2,
"accInfo": {
"transSerialNo": "seq081600001",
"loginNo": "cnk033447rgc73f2u980",
},"noticeUrl":"","businessType":"BCT2.0"
}`
pfxpath := "D:\\GEP\\正式环境证书生成工具\\certool\\keyfile_pri.pfx"
pfxpsw := "123456"
cerpath := "D:\\GEP\\正式环境证书生成工具\\certool\\keyfile_pub.cer"
encryptstr, err := EncryptWithPrivateKey(plaintext, pfxpath, pfxpsw)
if err != nil {
fmt.Printf("私钥加密失败: %v\n", err)
return
}
fmt.Printf("私钥加密encryptstr: %v\n", encryptstr)
decryptstr, err := DecryptWithPublicKey(encryptstr, cerpath)
if err != nil {
fmt.Printf("公钥解密失败: %v\n", err)
return
}
fmt.Printf("公钥decryptstr: %v\n", decryptstr)
encryptstr1, err := EncryptWithPublicKey(plaintext, cerpath)
if err != nil {
fmt.Printf("公钥加密失败: %v\n", err)
return
}
fmt.Printf("公钥encryptstr: %v\n", encryptstr1)
decryptstr1, err := DecryptWithPrivateKey(encryptstr1, pfxpath, pfxpsw)
if err != nil {
fmt.Printf("私钥解密失败: %v\n", err)
return
}
fmt.Printf("私钥decryptstr: %v\n", decryptstr1)
}
作者:陈花枪 创建时间:2024-08-15 10:18
最后编辑:陈花枪 更新时间:2025-05-26 15:03
最后编辑:陈花枪 更新时间:2025-05-26 15:03