公司业务需求要和第三方进行接口对接。我方使用的是C#,第三方是JAVA ,安全验证使用了AES和RSA加密。
AES加密,机密好弄, RSA就有些麻烦了,C#和JAVA的不一样。C#原生的支持的XML格式密钥。java提供的是pem文件格式密钥。
下图为签名方式:
签名规则详细步骤如下:
(1)合作方、现在支付生成各自 RSA 公私钥、AES 对称密钥。其中,合作方 RSA 公私钥为
(cooperatorPubKey、cooperatorPriKey),合作方 AES 对称密钥为 cooperatorAESKey;现在支付 RSA 公私钥
为(pubKey、priKey),现在支付 AES 对称密钥为 AESKey。生成密钥后交换各自 RSA 公钥。
(2)合作方请求报文时,需要用合作方 AES 对称密钥 cooperatorAESKey 加密请求报文:
encryptData=AES.encryptToBase64(data,cooperatorAESKey),其中 encryptData 是 Base64 编码的字符串;用合
作方 RSA 私钥签名请求报文:signature=RSA.signToBase64(data,cooperatorPriKey),其中 signature 是 Base64
编码的字符串;用现在支付 RSA 公 钥 加 密 合 作 方 AES 对称密钥 cooperatorAESKey :
encryptKey=RSA.encryptToBase64(cooperatorAESKey,pubKey),其中 encryptKey 是 Base64 编码的字符串。
注:以上为伪代码表示。
现在支付收到合作方请求报文(包含 6 个参数:encryptData、encryptKey、cooperator、signature,func
ode,version),根据 cooperator 取出对应的密钥,用现在支付 RSA 私钥解密 encryptKey:cooperatorAESKey=
RSA.decryptFromBase64(encryptKey,priKey);用解密得到的 cooperatorAESKey 解密 encryptData:data=AES.dec
ryptFromBase64(encryptData, cooperatorAESKey);用合作方 RSA 公钥验证签名:boolean result=RSA.checkSig
nFromBase64(data,signature,cooperatorPubKey);
想到2种方法:1、将pem文件格式的内容以文本方式进行处理。
2、将pem转换为xml格式,支持原生。
前提参数准备:
//第三方公钥
string iPayPublicKey = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgBXxP1I2Y2cNpyZZyhEXsM4VYCKv2Y33mXe8BI3KXaBPy87yuNam0YqxsM+ujo6FUXoFThU0XT+9AenFm2opDhG2SSV/8WkPVPx6ZeGLwn0CAudUEPVz3X4lbRJXHsEZWvv6jB8fbX6LlHWqyygy3aIaw0+tB49UTYTEXHfySKQAtaE4MS9GxbmlKb+Hhn+1LCxU6A1jEnS98ZByNPe5/6LDpCEQxrlzj4k+NW3AT5beSPKSmWlUsgsME8JSZLJcnV7omuV+DU5DdVL58QXJoEfFR6GZhxeKLoYtTxSw0xso/q3KLFcdAwfjix7HcmyDhplwwQSn5ydrb5j1Ci2raQIDAQAB-----END PUBLIC KEY-----";
//我方私钥
string privateKey = "-----BEGIN RSA PRIVATE KEY-----MIIEowIBAAKCAQEAh/DIxU4Q7PNPL2cU4spoQK92Rz1CTs7xkA9G1KbMozFGP3o0iuJfWk1NLRXlPKaB9NfjxoLgMJnmFRJSHIGuFQ1ipKb+xaSmCiZ0BnVs5eKZ3vmo+cFLTP9RzYaD5hK9rAc+JrK5IuKhSBp+qzLvENtku0WDmZg0PGm/uuJgvV62geTSgKQdq2sIUsFEM6T8dhPUrpcDdSFpbTudX2J44KIoaF8GnADzKIBioc028jyMfrlru6EnDDPejVWVP3u8l5O7Hg/QZ3ZdbhUOf+4efFym3HAUNkx6Vt62HxCD9O4H4L/oceZN+2IwFEVwtPG9xBbNbK0bpNbaztqSZrpRwwIDAQABAoIBAFgkMjlkFatdUyF8J9movZH7cqhcOusYWR48GYP2JsdFQrQTy4+lmYfWiUzLXphFqguUE5b58tzwXHObLmxXVQVHaYcy1AxYZmQ8bIxnhNVFaNlfbUWLJATnoyWsq0b5Lcwl4hF7XnkVEtfKfgkI/GMkrZqTRvHG80+cjXliILGHjaUKB5YGBlWT4cxPbnImV+Is8bpIoGUYHvKLr4mz1vflC89Lkx9tEcM5AOYqs63Mvs8cgp4xfmjXUsaRnjBe/3jN76hP079ejQgC19PaoYyWT52hC8AoiMGgZ18AHk+buJwIn3HalaElVqBmGSQjC9W/jBUFCsCiYSzON96rLDECgYEAzZzq5gBFhCX07gvhPI00JzSXZ64PRy72UNfG9Uf0HTGlp62b4YiXTFLl5ST+k5KdJ+UEl58UW3xKcQuLf/p6zsMRpCokn4Omh1Q5PdO8gtoRp6d6ZkBaACKHovOE29lcKWsUJYgNexhnZ0iGC6AcbdNlLUDPmsGaSwsMRm9CGHsCgYEAqUD8FsHSgNjn2vtpG3ejNC/lPbI3H43KcDfwcq6KuTvhucL6N+69gwwGPnndFHNmCS3dkWjo/aXkEXiU4D9vk4qzBJ5iuqtlfTMk8qDv7Ros/loMdkTRiSmRPFI4UtgjG1nZKlJOVEPOUZimOJzrh+c6HkXx1OIrX/Drzor3vVkCgYEAltAQI5/zXViR7MDd9pIDvPYAT9YF8sppdSawEl0ymu89eF4IxkZv41Wytn6KFCgoCYkb8zKFtgzWdVBog/hvd5TxLZ6TukTQMtb+HXFfBgN5i6V2S+XLnem13zoLK06lIOQfpN/EM5PU1JcHayOHdq7luWmeXP7Ac2apHEijDF0CgYABghq8+S0vCL/IK8VcAUzrAiJA0n27QkAzj8wMuZFy5R210g74wJ/fsxO7KsrVi9G08zuuOAkbeYb2wORSuz37SpkdyWuHzk8xNmt13glFS55rBdJmm2ZimoQ4zWLDGjn13G8a+XDJP3FvOLUCfCN9KopSCr2E8B8C09rGFGbwwQKBgCsIA4EGs4JNZtVjnPTJtnI4aJWaasc8BkBIu1c+8IFH3PZ5l3bLtfxTpINw05QLU/HI3M4+RuswtZhk9MoNvdDLNv1owTK+o7gBreoCCgJRRcwuGiCsnNKrhymbpGM3ljlOiqfHGTK38U41HRbvrCQhGQQ5maf/3VhFlLFpOlIi-----END RSA PRIVATE KEY-----";
第一步:AES加密,
aeskey 每次都不一样,动态生成
string EncryptKey = Guid.NewGuid().ToString("N").Substring(0, 16);
/// <summary>
/// AES 加密
/// </summary>
/// <param name="sKey"></param>
/// <param name="strEncrypt"></param>
/// <returns></returns>
public static string AESEncrypt(string sKey, string strEncrypt)
{
byte[] K = Encoding.UTF8.GetBytes(sKey);
KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", K);
IBufferedCipher c = CipherUtilities.GetCipher("AES/ECB/PKCS5Padding");// 参数与Java中加密解密的参数一致
c.Init(true, key); // 第一个参数为true表示加密,为false表示解密;第二个参数表示密钥
byte[] DataToEncrypt = Encoding.UTF8.GetBytes(strEncrypt);
byte[] outBytes = c.DoFinal(DataToEncrypt);//加密
string strBase64 = Convert.ToBase64String(outBytes);
return strBase64;
}
string strencrypt = JsonConvert.SerializeObject(encryptModel);
//AES加密
familyCard.encryptData = AESUtil.Encryptdata(CooperatorAESKey, strencrypt);
第二步:RSA私钥加密
/// <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);
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
var HashbyteSignature = rsa.SignData(dataBytes, "SHA1");
return Convert.ToBase64String(HashbyteSignature);
}
其中 rsa.LoadPrivateKeyPEM(privateKeyPEM) 使用的是个扩展类。
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
}
familyCard.signature = RSAUtil.RSASignPEM(strencrypt, privateKey);
第三步:RSA公钥加密
/// <summary>
/// RSA加密PEM秘钥
/// </summary>
/// <param name="publicKeyPEM"></param>
/// <param name="data"></param>
/// <returns></returns>
public static string EncryptPEM(string publicKeyPEM, string plaintext)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.LoadPublicKeyPEM(publicKeyPEM);
Byte[] PlaintextData = Encoding.UTF8.GetBytes(plaintext);
int MaxBlockSize = 1024 / 8 - 11; //加密块最大长度限制
if (PlaintextData.Length <= MaxBlockSize)
return Convert.ToBase64String(rsa.Encrypt(PlaintextData, false));
using (MemoryStream PlaiStream = new MemoryStream(PlaintextData))
using (MemoryStream CrypStream = new MemoryStream())
{
Byte[] Buffer = new Byte[MaxBlockSize];
int BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
while (BlockSize > 0)
{
Byte[] ToEncrypt = new Byte[BlockSize];
Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);
Byte[] Cryptograph = rsa.Encrypt(ToEncrypt, false);
CrypStream.Write(Cryptograph, 0, Cryptograph.Length);
BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
}
return Convert.ToBase64String(CrypStream.ToArray(), Base64FormattingOptions.None);
}
}
familyCard.signature = RSAUtil.RSASignPEM(strencrypt, privateKey);
将加密的各对象组成一个对象,转换成string.就可以使用