这个算是我真正意义上的第一篇技术博客吧,2022年了,需要对自己做一些改变了,从各个方面对自己要有更高的要求了,那就从自己专业技术上开始吧,把自己最近遇到的并成功解决的问题在复盘一下(大量查找资料并请教其他人,集思广议才得以解决,mrak一下)
最近在做的是与国科的接口对接,需要将我们的生产数据推送给国科,国科这边的加密方式为:双方均使用RSA加密AES的秘钥,使用RSA加签、验签,使用AES加密数据,,国科是用JAVA,我司是.NET 这就需要Java和.net对于加解密的代码要能互通才行
以前用的比较的多的加密方式大多都是对称加密:AES ,DES等,RSA 以前大多作为用于支付业务场景加密的安全策略,以前从来没有做过支付相关的业务,大概知道相关概念但具体是怎么运用的却不知道,通过这次的接口对接,只想通过一句话概括:
纸上得来终觉浅,绝知此事要躬行。
此次与国科对接的RSA+AES 具体实现步骤如下:
1.首先双方需要交换公钥
2 随机.产生16位的AES密钥,用RSA 并且用对方的公钥来加密AES的密钥
3.用自己的私钥根据双方的约定比如:报文的一部分数据生成签名,签名的算法要与对方的保持一致。比如都用:.net SHA-256withRSA 对应java的SHA256withRSA
4.用之前随机产生的AES 密钥加密业务数据
对方的实现步骤如下:
1.对方对接收到的加密的报文进行验签,根据你提供的RSA公钥 证明此消息是由你发送过来的,没有被别人修改过的
2.用你的RSA公钥解密AES随机密钥key
2.用解密出来的AES 随机key 解密业务数据
以下是我找到的参考博文,写的非常好的
//https://www.jianshu.com/p/1de40d21c413 为什么要才用RSA+AES的方式
//https://www.jianshu.com/p/8dc4a5f64e06 RSA加密/解密和签名/验签过程理解
//https://www.cnblogs.com/f1194361820/p/4260025.html 生动形象的描述了过
这个是我调用的代码
先附上JAVA代码吧
AESUtil 类
package com.gkht.m.encrypt.util;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.security.Security;
public class AESUtil {
/**
* 加密方式
*/
public static final String KEY_ALGORITHM = "AES";
/**
* 安全随机签名算法
*/
public static final String SECURE_ALGORITHM = "SHA1PRNG";
/**
* 加密算法
*/
public static final String SECRYPT_ALGORITHM = "AES/ECB/PKCS5Padding";
/**
* 报文加密
*
* @param randomKey 随机密钥
* @param plainData 上送报文
* @return 报文密文
* @throws Exception
*/
public static String encrypt(String plainData, String randomKey) throws Exception {
KeyGenerator aesGen = KeyGenerator.getInstance(KEY_ALGORITHM);
SecureRandom secureRandom = SecureRandom.getInstance(SECURE_ALGORITHM);
secureRandom.setSeed(randomKey.getBytes());
aesGen.init(128, secureRandom);
SecretKey secretKey = aesGen.generateKey();
SecretKeySpec keySpec = new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);
Security.addProvider(BouncyCastleProviderBuilder.build());
Cipher aesCipher = Cipher.getInstance(SECRYPT_ALGORITHM, "BC");
aesCipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] aesData = aesCipher.doFinal(plainData.getBytes("utf-8"));
return Base64.encodeBase64String(aesData);
}
public static String encryptWithBC(String data, String key) throws Exception {
ByteBuffer buffer = ByteBuffer.allocate(32);
buffer.put(key.getBytes());
KeyParameter kp = new KeyParameter(buffer.array());
byte[] bytes = data.getBytes("UTF8");
CBCBlockCipher aes = new CBCBlockCipher(new AESEngine());
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(aes, new PKCS7Padding());
cipher.init(true, kp);
byte[] output = new byte[cipher.getOutputSize(bytes.length)];
int len = cipher.processBytes(bytes, 0, bytes.length, output, 0);
cipher.doFinal(output, len);
return Base64.encodeBase64String(output);
}
public static String decryptWithBC(String data, String key) throws Exception {
ByteBuffer buffer = ByteBuffer.allocate(32);
buffer.put(key.getBytes());
KeyParameter kp = new KeyParameter(buffer.array());
byte[] bytes = Base64.decodeBase64(data);
CBCBlockCipher aes = new CBCBlockCipher(new AESEngine());
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(aes, new PKCS7Padding());
cipher.init(false, kp);
byte[] output = new byte[cipher.getOutputSize(bytes.length)];
int len = cipher.processBytes(bytes, 0, bytes.length, output, 0);
int len2 = cipher.doFinal(output, len);
byte rawData[] = new byte[len + len2];
System.arraycopy(output, 0, rawData, 0, rawData.length);
String plainData = new String(rawData, Charset.forName("utf-8"));
return plainData;
}
/**
* 报文解密
*
* @param aesBase64
* @param randomKey
* @return
* @throws Exception
*/
public static String decrypt(String aesBase64, String randomKey) throws Exception {
byte[] aesData = Base64.decodeBase64(aesBase64);
KeyGenerator aesGen = KeyGenerator.getInstance(KEY_ALGORITHM);
SecureRandom secureRandom = SecureRandom.getInstance(SECURE_ALGORITHM);
secureRandom.setSeed(randomKey.getBytes());
aesGen.init(128, secureRandom);
SecretKey secretKey = aesGen.generateKey();
SecretKeySpec keySpec = new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);
Security.addProvider(BouncyCastleProviderBuilder.build());
Cipher aesCipher = Cipher.getInstance(SECRYPT_ALGORITHM, "BC");
aesCipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] plain = aesCipher.doFinal(aesData);
String plainData = new String(plain, Charset.forName("utf-8"));
return plainData;
}
/**
* 生成随机密钥,一次一密
*
* @return
*/
public static String getRandomKey() {
SecureRandom random = new SecureRandom();
long randomKey = random.nextLong();
return String.valueOf(randomKey);
}
public static void main(String[] args) {
String content = "nQg5UGEWGRMU7EG1GbCD0Q==";
try {
decrypt(content, "5461205254612052");
} catch (Exception e) {
e.printStackTrace();
}
}
}
RSA Util 类
package com.gkht.m.encrypt.util;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class RSAUtil {
/**
* 加密方式
*/
public static final String KEY_ALGORITHM = "RSA";
/**
* 签名算法
*/
public static final String SIGNATURE_ALGORITHM = "SHA256withRSA";
/**
* 公钥算法
*/
public static final String PUBLIC_KEY = "RSAPublicKey";
/**
* 私钥算法
*/
public static final String PRIVATE_KEY = "RSAPrivateKey";
public static byte[] decryptBASE64(String key) {
return Base64.decodeBase64(key);
}
public static String encryptBASE64(byte[] bytes) {
return Base64.encodeBase64String(bytes);
}
/**
* 用私钥对信息生成数字签名
*
* @param data 待签名数据
* @param privateKey 私钥
* @throws Exception
*/
public static String sign(byte[] data, String privateKey) throws Exception {
// 解密由base64编码的私钥
byte[] keyBytes = decryptBASE64(privateKey);
// 构造PKCS8EncodedKeySpec对象
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取私钥匙对象
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 用私钥对信息生成数字签名
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(data);
return encryptBASE64(signature.sign());
}
/**
* 校验数字签名
*
* @param data 加密数据
* @param publicKey 公钥
* @param sign 数字签名
* @return 校验成功返回true,失败返回false
* @throws Exception
*/
public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
// 解密由base64编码的公钥
byte[] keyBytes = decryptBASE64(publicKey);
// 构造X509EncodedKeySpec对象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取公钥匙对象
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);
// 验证签名是否正常
return signature.verify(decryptBASE64(sign));
}
/**
* 解密<br>
* 私钥解密
*
* @param data 加密数据
* @param key 私钥
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception {
// 对密钥解密
byte[] keyBytes = decryptBASE64(key);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 解密 <br>
* 用私钥解密
*
* @param data 加密数据
* @param key 私钥
* @return 消息
* @throws Exception
*/
public static byte[] decryptByPrivateKey(String data, String key) throws Exception {
return decryptByPrivateKey(decryptBASE64(data), key);
}
/**
* 加密<br>
* 用公钥加密
*
* @param data 待加密消息
* @param key 公钥
* @return 密文
* @throws Exception
*/
public static String encryptByPublicKey(String data, String key) throws Exception {
// 对公钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return encryptBASE64(cipher.doFinal(data.getBytes()));
}
}
------------------------------------------------------------------------------以下是与之对应的.net代码--------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------.net 的 AES 类
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace RedCross.MDH.Implement.HospitalCustom.Encryption
{
public class AESUtily
{
//https://www.shangmayuan.com/a/67e15a2a3fa84d60b6e86db7.html 具体介绍文档参考
//算法/模式/填充 16字节加密后数据长度 不满16字节加密后长度
//AES/ECB/NoPadding 16 不支持
//AES/ECB/PKCS5Padding 32 16
//AES/ECB/ISO10126Padding 32 16
/// <summary>
/// AES 加密
/// </summary>
/// <param name="str"></param>
/// <param name="key"></param>
/// <returns></returns>
public static string AesEncrypt(string str, string key)//当模式为ECB模式,C#里key的长度一定要为16位
{
if (string.IsNullOrEmpty(str)) return null;
Byte[] toEncryptArray = Encoding.UTF8.GetBytes(str);
System.Security.Cryptography.RijndaelManaged rm = new System.Security.Cryptography.RijndaelManaged
{
Key = Encoding.UTF8.GetBytes(key),
Mode = System.Security.Cryptography.CipherMode.ECB,
Padding = System.Security.Cryptography.PaddingMode.PKCS7
};
System.Security.Cryptography.ICryptoTransform cTransform = rm.CreateEncryptor();
Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
/// <summary>
/// AES 解密
/// </summary>
/// <param name="str"></param>
/// <param name="key"></param>
/// <returns></returns>
public static string AesDecrypt(string str, string key)//当模式为ECB模式,C#里key的长度一定要为16位
{
if (string.IsNullOrEmpty(str)) return null;
Byte[] toEncryptArray = Convert.FromBase64String(str);
System.Security.Cryptography.RijndaelManaged rm = new System.Security.Cryptography.RijndaelManaged
{
Key = Encoding.UTF8.GetBytes(key),
Mode = System.Security.Cryptography.CipherMode.ECB,
Padding = System.Security.Cryptography.PaddingMode.PKCS7
};
System.Security.Cryptography.ICryptoTransform cTransform = rm.CreateDecryptor();
Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Encoding.UTF8.GetString(resultArray);
}
}
}
------------------------------。net RSAHelp 类
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
namespace RedCross.MDH.Implement.HospitalCustom.Encryption
{
//https://www.jianshu.com/p/1de40d21c413 为什么要才用RSA+AES的方式
//https://www.jianshu.com/p/8dc4a5f64e06 RSA加密/解密和签名/验签过程理解
//https://www.cnblogs.com/f1194361820/p/4260025.html 生动形象的描述了过程
//RSA是一种非对称加解密算法,用于实现签名/认证等。在.Net框架中提供了System.Security.Cryptography.RSACryptoServiceProvider类,用于封装实现RSA算法,但这个类使用的公钥/私钥格式为XML,这是.Net特有的格式,而其它语言如Java编程中一般使用PEM或DER等格式,OpenSSL规范中也特荐为PEM格式。项目中经常会遇到XML与PEM格式的密钥相互转换的需求
//RSA加密/解密和签名/验签过程理解 A->B:
//A:
// 1. A提取消息m的消息摘要h(m),并使用自己的私钥对摘要h(m)进行加密,生成签名s
// 2. A将签名s和消息m一起,使用B的公钥进行加密,生成密文c,发送给B
// B:
// 1. B接收到密文c,使用自己的私钥解密c得到明文m和数字签名s
// 2. B使用A的公钥解密数字签名s解密得到H(m)
// 3. B使用相同的方法提取消息m的消息摘要h(m)
// 4. B比较两个消息摘要。相同则验证成功;不同则验证失败
public partial class RSAHelper
{
#region 私钥加密,公钥解密
#region 私钥加密
/// <summary>
/// 基于BouncyCastle的RSA私钥加密
/// </summary>
/// <param name="privateKeyJava"></param>
/// <param name="data"></param>
/// <returns></returns>
public static string EncryptPrivateKeyJava(string privateKeyJava, string data, string encoding = "UTF-8")
{
RsaKeyParameters privateKeyParam = (RsaKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKeyJava));
byte[] cipherbytes = Encoding.GetEncoding(encoding).GetBytes(data);
RsaEngine rsa = new RsaEngine();
rsa.Init(true, privateKeyParam);//参数true表示加密/false表示解密。
cipherbytes = rsa.ProcessBlock(cipherbytes, 0, cipherbytes.Length);
return Convert.ToBase64String(cipherbytes);
}
#endregion
#region 公钥解密
/// <summary>
/// 基于BouncyCastle的RSA公钥解密
/// </summary>
/// <param name="publicKeyJava"></param>
/// <param name="data"></param>
/// <param name="encoding"></param>
/// <returns></returns>
public static string DecryptPublicKeyJava(string publicKeyJava, string data, string encoding = "UTF-8")
{
RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKeyJava));
byte[] cipherbytes = Convert.FromBase64String(data);
RsaEngine rsa = new RsaEngine();
rsa.Init(false, publicKeyParam);//参数true表示加密/false表示解密。
cipherbytes = rsa.ProcessBlock(cipherbytes, 0, cipherbytes.Length);
return Encoding.GetEncoding(encoding).GetString(cipherbytes);
}
#endregion
#region 加签
/// <summary>
/// 基于BouncyCastle的RSA签名
/// </summary>
/// <param name="data"></param>
/// <param name="privateKeyJava"></param>
/// <param name="hashAlgorithm">JAVA的和.NET的不一样,如:MD5(.NET)等同于MD5withRSA(JAVA)</param>
/// <param name="encoding"></param>
/// <returns></returns>
public static string RSASignJavaBouncyCastle(string data, string privateKeyJava, string hashAlgorithm = "SHA256withRSA", string encoding = "UTF-8")
{
RsaKeyParameters privateKeyParam = (RsaKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKeyJava));
ISigner signer = SignerUtilities.GetSigner(hashAlgorithm);
signer.Init(true, privateKeyParam);//参数为true验签,参数为false加签
var dataByte = Encoding.GetEncoding(encoding).GetBytes(data);
signer.BlockUpdate(dataByte, 0, dataByte.Length);
//return Encoding.GetEncoding(encoding).GetString(signer.GenerateSignature()); //签名结果 非Base64String
return Convert.ToBase64String(signer.GenerateSignature());
}
#endregion
#region 验签
/// <summary>
/// 基于BouncyCastle的RSA签名
/// </summary>
/// <param name="data">源数据</param>
/// <param name="publicKeyJava"></param>
/// <param name="signature">base64签名</param>
/// <param name="hashAlgorithm">JAVA的和.NET的不一样,如:MD5(.NET)等同于MD5withRSA(JAVA)</param>
/// <param name="encoding"></param>
/// <returns></returns>
public static bool VerifyJavaBouncyCastle(string data, string publicKeyJava, string signature, string hashAlgorithm = "SHA256withRSA", string encoding = "UTF-8")
{
RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKeyJava));
ISigner signer = SignerUtilities.GetSigner(hashAlgorithm);
signer.Init(false, publicKeyParam);
byte[] dataByte = Encoding.GetEncoding(encoding).GetBytes(data);
signer.BlockUpdate(dataByte, 0, dataByte.Length);
//byte[] signatureByte = Encoding.GetEncoding(encoding).GetBytes(signature);// 非Base64String
byte[] signatureByte = Convert.FromBase64String(signature);
return signer.VerifySignature(signatureByte);
}
#endregion
#endregion
#region 公钥加密,私钥解密
#region 加密
/// <summary>
/// RSA加密
/// </summary>
/// <param name="publicKeyJava"></param>
/// <param name="data"></param>
/// <returns></returns>
public static string EncryptJava(string publicKeyJava, string data, string encoding = "UTF-8")
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] cipherbytes;
rsa.FromPublicKeyJavaString(publicKeyJava);
//☆☆☆☆.NET 4.6以后特有☆☆☆☆
//HashAlgorithmName hashName = new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm);
//RSAEncryptionPadding padding = RSAEncryptionPadding.OaepSHA512;//RSAEncryptionPadding.CreateOaep(hashName);//.NET 4.6以后特有
//cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding);
//☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
//☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆
cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), false);
return Convert.ToBase64String(cipherbytes);
}
/// <summary>
/// RSA加密
/// </summary>
/// <param name="publicKeyCSharp"></param>
/// <param name="data"></param>
/// <returns></returns>
public static string EncryptCSharp(string publicKeyCSharp, string data, string encoding = "UTF-8")
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] cipherbytes;
rsa.FromXmlString(publicKeyCSharp);
//☆☆☆☆.NET 4.6以后特有☆☆☆☆
//HashAlgorithmName hashName = new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm);
//RSAEncryptionPadding padding = RSAEncryptionPadding.OaepSHA512;//RSAEncryptionPadding.CreateOaep(hashName);//.NET 4.6以后特有
//cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding);
//☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
//☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆
cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), false);
return Convert.ToBase64String(cipherbytes);
}
/// <summary>
/// RSA加密PEM秘钥
/// </summary>
/// <param name="publicKeyPEM"></param>
/// <param name="data"></param>
/// <returns></returns>
public static string EncryptPEM(string publicKeyPEM, string data, string encoding = "UTF-8")
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] cipherbytes;
rsa.LoadPublicKeyPEM(publicKeyPEM);
//☆☆☆☆.NET 4.6以后特有☆☆☆☆
//HashAlgorithmName hashName = new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm);
//RSAEncryptionPadding padding = RSAEncryptionPadding.OaepSHA512;//RSAEncryptionPadding.CreateOaep(hashName);//.NET 4.6以后特有
//cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding);
//☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
//☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆
cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), false);
return Convert.ToBase64String(cipherbytes);
}
#endregion
#region 解密
/// <summary>
/// RSA解密
/// </summary>
/// <param name="privateKeyJava"></param>
/// <param name="content"></param>
/// <returns></returns>
public static string DecryptJava(string privateKeyJava, string data, string encoding = "UTF-8")
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] cipherbytes;
rsa.FromPrivateKeyJavaString(privateKeyJava);
//☆☆☆☆.NET 4.6以后特有☆☆☆☆
//RSAEncryptionPadding padding = RSAEncryptionPadding.CreateOaep(new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm));//.NET 4.6以后特有
//cipherbytes = rsa.Decrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding);
//☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
//☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆
cipherbytes = rsa.Decrypt(Convert.FromBase64String(data), false);
return Encoding.GetEncoding(encoding).GetString(cipherbytes);
}
/// <summary>
/// RSA解密
/// </summary>
/// <param name="privateKeyCSharp"></param>
/// <param name="content"></param>
/// <returns></returns>
public static string DecryptCSharp(string privateKeyCSharp, string data, string encoding = "UTF-8")
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] cipherbytes;
rsa.FromXmlString(privateKeyCSharp);
//☆☆☆☆.NET 4.6以后特有☆☆☆☆
//RSAEncryptionPadding padding = RSAEncryptionPadding.CreateOaep(new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm));//.NET 4.6以后特有
//cipherbytes = rsa.Decrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding);
//☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
//☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆
cipherbytes = rsa.Decrypt(Convert.FromBase64String(data), false);
return Encoding.GetEncoding(encoding).GetString(cipherbytes);
}
/// <summary>
/// RSA解密
/// </summary>
/// <param name="privateKeyPEM"></param>
/// <param name="content"></param>
/// <returns></returns>
public static string DecryptPEM(string privateKeyPEM, string data, string encoding = "UTF-8")
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
byte[] cipherbytes;
rsa.LoadPrivateKeyPEM(privateKeyPEM);
//☆☆☆☆.NET 4.6以后特有☆☆☆☆
//RSAEncryptionPadding padding = RSAEncryptionPadding.CreateOaep(new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm));//.NET 4.6以后特有
//cipherbytes = rsa.Decrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding);
//☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
//☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆
cipherbytes = rsa.Decrypt(Convert.FromBase64String(data), false);
return Encoding.GetEncoding(encoding).GetString(cipherbytes);
}
#endregion
#region 加签
/// <summary>
/// RSA签名
/// </summary>
/// <param name="privateKeyJava">私钥</param>
/// <param name="data">待签名的内容</param>
/// <returns></returns>
public static string RSASignJava(string data, string privateKeyJava, string hashAlgorithm = "MD5", string encoding = "UTF-8")
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromPrivateKeyJavaString(privateKeyJava);//加载私钥
//RSAPKCS1SignatureFormatter RSAFormatter = new RSAPKCS1SignatureFormatter(rsa);
////设置签名的算法为MD5 MD5withRSA 签名
//RSAFormatter.SetHashAlgorithm(hashAlgorithm);
var dataBytes = Encoding.GetEncoding(encoding).GetBytes(data);
var HashbyteSignature = rsa.SignData(dataBytes, hashAlgorithm);
return Convert.ToBase64String(HashbyteSignature);
//byte[] HashbyteSignature = ConvertToRgbHash(data, encoding);
//byte[] dataBytes =Encoding.GetEncoding(encoding).GetBytes(data);
//HashbyteSignature = rsa.SignData(dataBytes, hashAlgorithm);
//return Convert.ToBase64String(HashbyteSignature);
//执行签名
//EncryptedSignatureData = RSAFormatter.CreateSignature(HashbyteSignature);
//return Convert.ToBase64String(RSAFormatter.CreateSignature(HashbyteSignature));
//return result.Replace("=", String.Empty).Replace('+', '-').Replace('/', '_');
}
/// <summary>
/// RSA签名
/// </summary>
/// <param name="privateKeyPEM">私钥</param>
/// <param name="data">待签名的内容</param>
/// <returns></returns>
public static string RSASignPEM(string data, string privateKeyPEM, string hashAlgorithm = "MD5", string encoding = "UTF-8")
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.LoadPrivateKeyPEM(privateKeyPEM);//加载私钥
var dataBytes = Encoding.GetEncoding(encoding).GetBytes(data);
var HashbyteSignature = rsa.SignData(dataBytes, hashAlgorithm);
return Convert.ToBase64String(HashbyteSignature);
}
/// <summary>
/// RSA签名CSharp
/// </summary>
/// <param name="privateKeyCSharp">私钥</param>
/// <param name="data">待签名的内容</param>
/// <returns></returns>
public static string RSASignCSharp(string data, string privateKeyCSharp, string hashAlgorithm = "MD5", string encoding = "UTF-8")
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(privateKeyCSharp);//加载私钥
var dataBytes = Encoding.GetEncoding(encoding).GetBytes(data);
var HashbyteSignature = rsa.SignData(dataBytes, hashAlgorithm);
return Convert.ToBase64String(HashbyteSignature);
}
#endregion
#region 验签
/// <summary>
/// 验证签名-方法一
/// </summary>
/// <param name="data"></param>
/// <param name="signature"></param>
/// <param name="encoding"></param>
/// <returns></returns>
public static bool VerifyJava(string data, string publicKeyJava, string signature, string hashAlgorithm = "MD5", string encoding = "UTF-8")
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
//导入公钥,准备验证签名
rsa.FromPublicKeyJavaString(publicKeyJava);
//返回数据验证结果
byte[] Data = Encoding.GetEncoding(encoding).GetBytes(data);
byte[] rgbSignature = Convert.FromBase64String(signature);
return rsa.VerifyData(Data, hashAlgorithm, rgbSignature);
//return SignatureDeformatter(publicKeyJava, data, signature);
//return CheckSign(publicKeyJava, data, signature);
//return rsa.VerifyData(Encoding.GetEncoding(encoding).GetBytes(data), "MD5", Encoding.GetEncoding(encoding).GetBytes(signature));
}
/// <summary>
/// 验证签名PEM
/// </summary>
/// <param name="data"></param>
/// <param name="signature"></param>
/// <param name="encoding"></param>
/// <returns></returns>
public static bool VerifyPEM(string data, string publicKeyPEM, string signature, string hashAlgorithm = "MD5", string encoding = "UTF-8")
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
//导入公钥,准备验证签名
rsa.LoadPublicKeyPEM(publicKeyPEM);
//返回数据验证结果
byte[] Data = Encoding.GetEncoding(encoding).GetBytes(data);
byte[] rgbSignature = Convert.FromBase64String(signature);
return rsa.VerifyData(Data, hashAlgorithm, rgbSignature);
}
/// <summary>
/// 验证签名CSharp
/// </summary>
/// <param name="data"></param>
/// <param name="signature"></param>
/// <param name="encoding"></param>
/// <returns></returns>
public static bool VerifyCSharp(string data, string publicKeyCSharp, string signature, string hashAlgorithm = "MD5", string encoding = "UTF-8")
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
//导入公钥,准备验证签名
rsa.LoadPublicKeyPEM(publicKeyCSharp);
//返回数据验证结果
byte[] Data = Encoding.GetEncoding(encoding).GetBytes(data);
byte[] rgbSignature = Convert.FromBase64String(signature);
return rsa.VerifyData(Data, hashAlgorithm, rgbSignature);
}
#region 签名验证-方法二
/// <summary>
/// 签名验证
/// </summary>
/// <param name="publicKey">公钥</param>
/// <param name="p_strHashbyteDeformatter">待验证的用户名</param>
/// <param name="signature">注册码</param>
/// <returns>签名是否符合</returns>
public static bool SignatureDeformatter(string publicKey, string data, string signature, string hashAlgorithm = "MD5")
{
try
{
byte[] rgbHash = ConvertToRgbHash(data);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
//导入公钥,准备验证签名
rsa.FromPublicKeyJavaString(publicKey);
RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(rsa);
deformatter.SetHashAlgorithm("MD5");
byte[] rgbSignature = Convert.FromBase64String(signature);
if (deformatter.VerifySignature(rgbHash, rgbSignature))
{
return true;
}
return false;
}
catch
{
return false;
}
}
/// <summary>
/// 签名数据转化为RgbHash
/// </summary>
/// <param name="data"></param>
/// <param name="encoding"></param>
/// <returns></returns>
public static byte[] ConvertToRgbHash(string data, string encoding = "UTF-8")
{
using (MD5 md5 = new MD5CryptoServiceProvider())
{
byte[] bytes_md5_in = Encoding.GetEncoding(encoding).GetBytes(data);
return md5.ComputeHash(bytes_md5_in);
}
}
#endregion
#region 签名验证-方法三
/// <summary>
/// 验证签名
/// </summary>
/// <param name="data">原始数据</param>
/// <param name="sign">签名</param>
/// <returns></returns>
public static bool CheckSign(string publicKey, string data, string sign, string encoding = "UTF-8")
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromPublicKeyJavaString(publicKey);
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] Data = Encoding.GetEncoding(encoding).GetBytes(data);
byte[] rgbSignature = Convert.FromBase64String(sign);
if (rsa.VerifyData(Data, md5, rgbSignature))
{
return true;
}
return false;
}
#endregion
#endregion
#endregion
}
}
------------------RSAExtensions 类
using System;
using System.Xml;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using System.Security.Cryptography;
using System.IO;
using Org.BouncyCastle.Crypto;
using System.Runtime.InteropServices;
using System.ComponentModel;
namespace RedCross.MDH.Implement.HospitalCustom.Encryption
{
public static class RSAExtensions
{
/// <summary>
/// 把java的私钥转换成.net的xml格式
/// </summary>
/// <param name="rsa"></param>
/// <param name="privateJavaKey"></param>
/// <returns></returns>
public static string ConvertToXmlPrivateKey(this RSA rsa, string privateJavaKey)
{
RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateJavaKey));
string xmlPrivateKey = string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",
Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),
Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));
return xmlPrivateKey;
}
/// <summary>
/// RSA加载JAVA PrivateKey
/// </summary>
/// <param name="privateJavaKey">java提供的第三方私钥</param>
/// <returns></returns>
public static void FromPrivateKeyJavaString(this RSA rsa, string privateJavaKey)
{
string xmlPrivateKey = rsa.ConvertToXmlPrivateKey(privateJavaKey);
rsa.FromXmlString(xmlPrivateKey);
}
/// <summary>
/// 把java的公钥转换成.net的xml格式
/// </summary>
/// <param name="privateKey">java提供的第三方公钥</param>
/// <returns></returns>
public static string ConvertToXmlPublicJavaKey(this RSA rsa, string publicJavaKey)
{
RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicJavaKey));
string xmlpublicKey = string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
return xmlpublicKey;
}
/// <summary>
/// 把java的私钥转换成.net的xml格式
/// </summary>
/// <param name="privateKey">java提供的第三方公钥</param>
/// <returns></returns>
public static void FromPublicKeyJavaString(this RSA rsa, string publicJavaKey)
{
string xmlpublicKey = rsa.ConvertToXmlPublicJavaKey(publicJavaKey);
rsa.FromXmlString(xmlpublicKey);
}
///// <summary>
///// RSA公钥格式转换,java->.net
///// </summary>
///// <param name="publicKey">java生成的公钥</param>
///// <returns></returns>
//private static string ConvertJavaPublicKeyToDotNet(this RSA rsa,string publicKey)
//{
// RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
// return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
// Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
// Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
//}
/// <summary>Extension method for initializing a RSACryptoServiceProvider from PEM data string.</summary>
#region Methods
/// <summary>Extension method which initializes an RSACryptoServiceProvider from a DER public key blob.</summary>
public static void LoadPublicKeyDER(this RSACryptoServiceProvider provider, byte[] DERData)
{
byte[] RSAData = GetRSAFromDER(DERData);
byte[] publicKeyBlob = GetPublicKeyBlobFromRSA(RSAData);
provider.ImportCspBlob(publicKeyBlob);
}
/// <summary>Extension method which initializes an RSACryptoServiceProvider from a DER private key blob.</summary>
public static void LoadPrivateKeyDER(this RSACryptoServiceProvider provider, byte[] DERData)
{
byte[] privateKeyBlob = GetPrivateKeyDER(DERData);
provider.ImportCspBlob(privateKeyBlob);
}
/// <summary>Extension method which initializes an RSACryptoServiceProvider from a PEM public key string.</summary>
public static void LoadPublicKeyPEM(this RSACryptoServiceProvider provider, string sPEM)
{
byte[] DERData = GetDERFromPEM(sPEM);
LoadPublicKeyDER(provider, DERData);
}
/// <summary>Extension method which initializes an RSACryptoServiceProvider from a PEM private key string.</summary>
public static void LoadPrivateKeyPEM(this RSACryptoServiceProvider provider, string sPEM)
{
byte[] DERData = GetDERFromPEM(sPEM);
LoadPrivateKeyDER(provider, DERData);
}
/// <summary>Returns a public key blob from an RSA public key.</summary>
internal static byte[] GetPublicKeyBlobFromRSA(byte[] RSAData)
{
byte[] data = null;
UInt32 dwCertPublicKeyBlobSize = 0;
if (CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING,
new IntPtr((int)CRYPT_OUTPUT_TYPES.RSA_CSP_PUBLICKEYBLOB), RSAData, (UInt32)RSAData.Length, CRYPT_DECODE_FLAGS.NONE,
data, ref dwCertPublicKeyBlobSize))
{
data = new byte[dwCertPublicKeyBlobSize];
if (!CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING,
new IntPtr((int)CRYPT_OUTPUT_TYPES.RSA_CSP_PUBLICKEYBLOB), RSAData, (UInt32)RSAData.Length, CRYPT_DECODE_FLAGS.NONE,
data, ref dwCertPublicKeyBlobSize))
throw new Win32Exception(Marshal.GetLastWin32Error());
}
else
throw new Win32Exception(Marshal.GetLastWin32Error());
return data;
}
/// <summary>Converts DER binary format to a CAPI CRYPT_PRIVATE_KEY_INFO structure.</summary>
internal static byte[] GetPrivateKeyDER(byte[] DERData)
{
byte[] data = null;
UInt32 dwRSAPrivateKeyBlobSize = 0;
IntPtr pRSAPrivateKeyBlob = IntPtr.Zero;
if (CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.PKCS_RSA_PRIVATE_KEY),
DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwRSAPrivateKeyBlobSize))
{
data = new byte[dwRSAPrivateKeyBlobSize];
if (!CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.PKCS_RSA_PRIVATE_KEY),
DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwRSAPrivateKeyBlobSize))
throw new Win32Exception(Marshal.GetLastWin32Error());
}
else
throw new Win32Exception(Marshal.GetLastWin32Error());
return data;
}
/// <summary>Converts DER binary format to a CAPI CERT_PUBLIC_KEY_INFO structure containing an RSA key.</summary>
internal static byte[] GetRSAFromDER(byte[] DERData)
{
byte[] data = null;
byte[] publicKey = null;
CERT_PUBLIC_KEY_INFO info;
UInt32 dwCertPublicKeyInfoSize = 0;
IntPtr pCertPublicKeyInfo = IntPtr.Zero;
if (CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.X509_PUBLIC_KEY_INFO),
DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwCertPublicKeyInfoSize))
{
data = new byte[dwCertPublicKeyInfoSize];
if (CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, new IntPtr((int)CRYPT_OUTPUT_TYPES.X509_PUBLIC_KEY_INFO),
DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwCertPublicKeyInfoSize))
{
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
try
{
info = (CERT_PUBLIC_KEY_INFO)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(CERT_PUBLIC_KEY_INFO));
publicKey = new byte[info.PublicKey.cbData];
Marshal.Copy(info.PublicKey.pbData, publicKey, 0, publicKey.Length);
}
finally
{
handle.Free();
}
}
else
throw new Win32Exception(Marshal.GetLastWin32Error());
}
else
throw new Win32Exception(Marshal.GetLastWin32Error());
return publicKey;
}
/// <summary>Extracts the binary data from a PEM file.</summary>
internal static byte[] GetDERFromPEM(string sPEM)
{
UInt32 dwSkip, dwFlags;
UInt32 dwBinarySize = 0;
if (!CryptStringToBinary(sPEM, (UInt32)sPEM.Length, CRYPT_STRING_FLAGS.CRYPT_STRING_BASE64HEADER, null, ref dwBinarySize, out dwSkip, out dwFlags))
throw new Win32Exception(Marshal.GetLastWin32Error());
byte[] decodedData = new byte[dwBinarySize];
if (!CryptStringToBinary(sPEM, (UInt32)sPEM.Length, CRYPT_STRING_FLAGS.CRYPT_STRING_BASE64HEADER, decodedData, ref dwBinarySize, out dwSkip, out dwFlags))
throw new Win32Exception(Marshal.GetLastWin32Error());
return decodedData;
}
#endregion Methods
#region P/Invoke Constants
/// <summary>Enumeration derived from Crypto API.</summary>
internal enum CRYPT_ACQUIRE_CONTEXT_FLAGS : uint
{
CRYPT_NEWKEYSET = 0x8,
CRYPT_DELETEKEYSET = 0x10,
CRYPT_MACHINE_KEYSET = 0x20,
CRYPT_SILENT = 0x40,
CRYPT_DEFAULT_CONTAINER_OPTIONAL = 0x80,
CRYPT_VERIFYCONTEXT = 0xF0000000
}
/// <summary>Enumeration derived from Crypto API.</summary>
internal enum CRYPT_PROVIDER_TYPE : uint
{
PROV_RSA_FULL = 1
}
/// <summary>Enumeration derived from Crypto API.</summary>
internal enum CRYPT_DECODE_FLAGS : uint
{
NONE = 0,
CRYPT_DECODE_ALLOC_FLAG = 0x8000
}
/// <summary>Enumeration derived from Crypto API.</summary>
internal enum CRYPT_ENCODING_FLAGS : uint
{
PKCS_7_ASN_ENCODING = 0x00010000,
X509_ASN_ENCODING = 0x00000001,
}
/// <summary>Enumeration derived from Crypto API.</summary>
internal enum CRYPT_OUTPUT_TYPES : int
{
X509_PUBLIC_KEY_INFO = 8,
RSA_CSP_PUBLICKEYBLOB = 19,
PKCS_RSA_PRIVATE_KEY = 43,
PKCS_PRIVATE_KEY_INFO = 44
}
/// <summary>Enumeration derived from Crypto API.</summary>
internal enum CRYPT_STRING_FLAGS : uint
{
CRYPT_STRING_BASE64HEADER = 0,
CRYPT_STRING_BASE64 = 1,
CRYPT_STRING_BINARY = 2,
CRYPT_STRING_BASE64REQUESTHEADER = 3,
CRYPT_STRING_HEX = 4,
CRYPT_STRING_HEXASCII = 5,
CRYPT_STRING_BASE64_ANY = 6,
CRYPT_STRING_ANY = 7,
CRYPT_STRING_HEX_ANY = 8,
CRYPT_STRING_BASE64X509CRLHEADER = 9,
CRYPT_STRING_HEXADDR = 10,
CRYPT_STRING_HEXASCIIADDR = 11,
CRYPT_STRING_HEXRAW = 12,
CRYPT_STRING_NOCRLF = 0x40000000,
CRYPT_STRING_NOCR = 0x80000000
}
#endregion P/Invoke Constants
#region P/Invoke Structures
/// <summary>Structure from Crypto API.</summary>
[StructLayout(LayoutKind.Sequential)]
internal struct CRYPT_OBJID_BLOB
{
internal UInt32 cbData;
internal IntPtr pbData;
}
/// <summary>Structure from Crypto API.</summary>
[StructLayout(LayoutKind.Sequential)]
internal struct CRYPT_ALGORITHM_IDENTIFIER
{
internal IntPtr pszObjId;
internal CRYPT_OBJID_BLOB Parameters;
}
/// <summary>Structure from Crypto API.</summary>
[StructLayout(LayoutKind.Sequential)]
struct CRYPT_BIT_BLOB
{
internal UInt32 cbData;
internal IntPtr pbData;
internal UInt32 cUnusedBits;
}
/// <summary>Structure from Crypto API.</summary>
[StructLayout(LayoutKind.Sequential)]
struct CERT_PUBLIC_KEY_INFO
{
internal CRYPT_ALGORITHM_IDENTIFIER Algorithm;
internal CRYPT_BIT_BLOB PublicKey;
}
#endregion P/Invoke Structures
#region P/Invoke Functions
/// <summary>Function for Crypto API.</summary>
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptDestroyKey(IntPtr hKey);
/// <summary>Function for Crypto API.</summary>
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptImportKey(IntPtr hProv, byte[] pbKeyData, UInt32 dwDataLen, IntPtr hPubKey, UInt32 dwFlags, ref IntPtr hKey);
/// <summary>Function for Crypto API.</summary>
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptReleaseContext(IntPtr hProv, Int32 dwFlags);
/// <summary>Function for Crypto API.</summary>
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptAcquireContext(ref IntPtr hProv, string pszContainer, string pszProvider, CRYPT_PROVIDER_TYPE dwProvType, CRYPT_ACQUIRE_CONTEXT_FLAGS dwFlags);
/// <summary>Function from Crypto API.</summary>
[DllImport("crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptStringToBinary(string sPEM, UInt32 sPEMLength, CRYPT_STRING_FLAGS dwFlags, [Out] byte[] pbBinary, ref UInt32 pcbBinary, out UInt32 pdwSkip, out UInt32 pdwFlags);
/// <summary>Function from Crypto API.</summary>
[DllImport("crypt32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptDecodeObjectEx(CRYPT_ENCODING_FLAGS dwCertEncodingType, IntPtr lpszStructType, byte[] pbEncoded, UInt32 cbEncoded, CRYPT_DECODE_FLAGS dwFlags, IntPtr pDecodePara, ref byte[] pvStructInfo, ref UInt32 pcbStructInfo);
/// <summary>Function from Crypto API.</summary>
[DllImport("crypt32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptDecodeObject(CRYPT_ENCODING_FLAGS dwCertEncodingType, IntPtr lpszStructType, byte[] pbEncoded, UInt32 cbEncoded, CRYPT_DECODE_FLAGS flags, [In, Out] byte[] pvStructInfo, ref UInt32 cbStructInfo);
#endregion P/Invoke Functions
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构