RSA非对称加密。简明扼要吧,直说干货。
C#RSA加签解签加密比较常见,一般遇到的问题是非.NET代码的加签验签、加密解密。以下就是解决此类问题的。
一般情况下是【公钥加密,私钥解密。】
有些变态喜欢乱搞,【私钥加密,公钥解密。】,详见这里:https://www.cnblogs.com/kevin860/p/9557859.html
1、RSA 具体是什么请点击这里
* 重要的事情说三遍,不懂的自己恶补去。
* RSA加密解密:私钥解密,公钥加密。
* RSA数字签名-俗称加签验签:私钥加签,公钥验签。
* RSA加密解密:私钥解密,公钥加密。
* RSA数字签名-俗称加签验签:私钥加签,公钥验签。
* RSA加密解密:私钥解密,公钥加密。
* RSA数字签名-俗称加签验签:私钥加签,公钥验签。
关于hashAlgorithm参数值有:MD5、SHA1、SHA256、SHA384、SHA512。其它的自己试吧,可能这个不全。
具体java与C#对应的参见这里(仅供参考,详见测试代码部分):https://www.cnblogs.com/kevin860/p/9557859.html
在这里提醒下各位对接其他它非.NET对接时注意事项吧。下面是自己总结的一些方法。
【注意简单的地方,越是简单的地方越容易阴沟里翻船】。
1、首先测试的时候,先给对方提供一整套公私钥,或者问对方要一套,以便方便自己和对方测试使用。因为跟你对接的兄弟多半跟你不在一个频道上,你说的他不明白。他也不明白你说的。
2、对方是否使用safeurl,请问清楚。如没有请忽略以下代码。
1 public static string ConvertEncodeBase64URLSafe(string data) 2 { 3 return data.Replace("=", String.Empty).Replace('+', '-').Replace('/', '_'); 4 } 5 public static string ConvertDecodeBase64URLSafe(string data) 6 { 7 data = data.Replace('-', '+').Replace('_', '/'); 8 int len = data.Length % 4; 9 if (len > 0) 10 { 11 data += "====".Substring(0, 4 - len); 12 } 13 return data; 14 }
3、对方是否使用MD5withRas。请看加签、验签。
4、一些单元测试及使用方法,都在
5、rsa.KeySize / 8-11是可加密的长度,RSA是本意是加密部分及其重要的数据,如果超过,多半是你自己的设计有问题。请改进,网上有分段加密解密超长数据的方法。不建议采用,改进自己的设计去。
6、【注意双方的编码格式。】
【注意双方的编码格式。】
【注意双方的编码格式。】
7、【注意本文的加密、加签结果都是Base64的。】
【注意本文的加密、加签结果都是Base64的。】
【注意本文的加密、加签结果都是Base64的。】
1 byte[] dataBytes = Convert.FromBase64String(data); 2 string base64Str = Convert.ToBase64String(signer.GenerateSignature());
8、对方是个变态,使用【私钥加密、公钥解密】。详见这里:https://www.cnblogs.com/kevin860/p/9557859.html
9、注意加签验签Algorithm参数。详见这里:https://www.cnblogs.com/kevin860/p/9557859.html C#与JAVA对应的关系,暂无。
10、JAVA 使用PEM的为PKCS8,转换命令如下
PKCS8转换为普通的PKCS1,本示列使用普通PEM私钥
openssl pkcs8 -in private_key_pkcs8.pem -nocrypt -out private_key.pem
11、微信RSA支付。必须使用.NET4.6以上版本 。
使用如下代码。
https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_7&index=4
1 public static string DecryptPEMByWeiXin(string privateKeyPEM, string data, string encoding = "UTF-8") 2 { 3 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 4 byte[] cipherbytes; 5 rsa.LoadPrivateKeyPEM(privateKeyPEM); 6 var padding = System.Security.Cryptography.RSAEncryptionPadding.Pkcs1; 7 cipherbytes = rsa.Decrypt(Convert.FromBase64String(data), padding); 8 9 return Encoding.GetEncoding(encoding).GetString(cipherbytes); 10 }
以下是RSA的帮助类:
加签:
1 class="language-csharp"> #region 加签
2
3 ///
4 /// RSA签名
5 ///
6 /// 私钥
7 /// 待签名的内容
8 ///
9 public static string RSASignJava(string data, string privateKeyJava, string hashAlgorithm = "MD5", string encoding = "UTF-8")
10 {
11 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
12 rsa.FromPrivateKeyJavaString(privateKeyJava);//加载私钥
13 //RSAPKCS1SignatureFormatter RSAFormatter = new RSAPKCS1SignatureFormatter(rsa);
14 ////设置签名的算法为MD5 MD5withRSA 签名
15 //RSAFormatter.SetHashAlgorithm(hashAlgorithm);
16
17
18 var dataBytes = Encoding.GetEncoding(encoding).GetBytes(data);
19 var HashbyteSignature = rsa.SignData(dataBytes, hashAlgorithm);
20 return Convert.ToBase64String(HashbyteSignature);
21
22 //byte[] HashbyteSignature = ConvertToRgbHash(data, encoding);
23
24 //byte[] dataBytes =Encoding.GetEncoding(encoding).GetBytes(data);
25 //HashbyteSignature = rsa.SignData(dataBytes, hashAlgorithm);
26 //return Convert.ToBase64String(HashbyteSignature);
27 //执行签名
28 //EncryptedSignatureData = RSAFormatter.CreateSignature(HashbyteSignature);
29 //return Convert.ToBase64String(RSAFormatter.CreateSignature(HashbyteSignature));
30 //return result.Replace("=", String.Empty).Replace('+', '-').Replace('/', '_');
31 }
32 ///
33 /// RSA签名
34 ///
35 /// 私钥
36 /// 待签名的内容
37 ///
38 public static string RSASignPEM(string data, string privateKeyPEM, string hashAlgorithm = "MD5", string encoding = "UTF-8")
39 {
40 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
41 rsa.LoadPrivateKeyPEM(privateKeyPEM);//加载私钥
42 var dataBytes = Encoding.GetEncoding(encoding).GetBytes(data);
43 var HashbyteSignature = rsa.SignData(dataBytes, hashAlgorithm);
44 return Convert.ToBase64String(HashbyteSignature);
45 }
46 ///
47 /// RSA签名CSharp
48 ///
49 /// 私钥
50 /// 待签名的内容
51 ///
52 public static string RSASignCSharp(string data, string privateKeyCSharp, string hashAlgorithm = "MD5", string encoding = "UTF-8")
53 {
54 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
55 rsa.FromXmlString(privateKeyCSharp);//加载私钥
56 var dataBytes = Encoding.GetEncoding(encoding).GetBytes(data);
57 var HashbyteSignature = rsa.SignData(dataBytes, hashAlgorithm);
58 return Convert.ToBase64String(HashbyteSignature);
59 }
60
61 #endregion
62
验签:
1 #region 验签 2 3 ///4 /// 验证签名-方法一 5 /// 6 /// 7 /// 8 /// 9 /// 10 public static bool VerifyJava(string data, string publicKeyJava, string signature, string hashAlgorithm = "MD5", string encoding = "UTF-8") 11 { 12 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 13 //导入公钥,准备验证签名 14 rsa.FromPublicKeyJavaString(publicKeyJava); 15 //返回数据验证结果 16 byte[] Data = Encoding.GetEncoding(encoding).GetBytes(data); 17 byte[] rgbSignature = Convert.FromBase64String(signature); 18 19 return rsa.VerifyData(Data, hashAlgorithm, rgbSignature); 20 21 //return SignatureDeformatter(publicKeyJava, data, signature); 22 23 //return CheckSign(publicKeyJava, data, signature); 24 25 //return rsa.VerifyData(Encoding.GetEncoding(encoding).GetBytes(data), "MD5", Encoding.GetEncoding(encoding).GetBytes(signature)); 26 } 27 /// 28 /// 验证签名PEM 29 /// 30 /// 31 /// 32 /// 33 /// 34 public static bool VerifyPEM(string data, string publicKeyPEM, string signature, string hashAlgorithm = "MD5", string encoding = "UTF-8") 35 { 36 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 37 //导入公钥,准备验证签名 38 rsa.LoadPublicKeyPEM(publicKeyPEM); 39 //返回数据验证结果 40 byte[] Data = Encoding.GetEncoding(encoding).GetBytes(data); 41 byte[] rgbSignature = Convert.FromBase64String(signature); 42 43 return rsa.VerifyData(Data, hashAlgorithm, rgbSignature); 44 } 45 46 /// 47 /// 验证签名CSharp 48 /// 49 /// 50 /// 51 /// 52 /// 53 public static bool VerifyCSharp(string data, string publicKeyCSharp, string signature, string hashAlgorithm = "MD5", string encoding = "UTF-8") 54 { 55 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 56 //导入公钥,准备验证签名 57 rsa.LoadPublicKeyPEM(publicKeyCSharp); 58 //返回数据验证结果 59 byte[] Data = Encoding.GetEncoding(encoding).GetBytes(data); 60 byte[] rgbSignature = Convert.FromBase64String(signature); 61 62 return rsa.VerifyData(Data, hashAlgorithm, rgbSignature); 63 } 64 65 #region 签名验证-方法二 66 /// 67 /// 签名验证 68 /// 69 /// 公钥 70 /// 待验证的用户名 71 /// 注册码 72 /// 签名是否符合 73 public static bool SignatureDeformatter(string publicKey, string data, string signature, string hashAlgorithm = "MD5") 74 { 75 try 76 { 77 byte[] rgbHash = ConvertToRgbHash(data); 78 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 79 //导入公钥,准备验证签名 80 rsa.FromPublicKeyJavaString(publicKey); 81 82 RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(rsa); 83 deformatter.SetHashAlgorithm("MD5"); 84 byte[] rgbSignature = Convert.FromBase64String(signature); 85 if (deformatter.VerifySignature(rgbHash, rgbSignature)) 86 { 87 return true; 88 } 89 return false; 90 } 91 catch 92 { 93 return false; 94 } 95 } 96 97 /// 98 /// 签名数据转化为RgbHash 99 /// 100 /// 101 /// 102 /// 103 public static byte[] ConvertToRgbHash(string data, string encoding = "UTF-8") 104 { 105 using (MD5 md5 = new MD5CryptoServiceProvider()) 106 { 107 byte[] bytes_md5_in = Encoding.GetEncoding(encoding).GetBytes(data); 108 return md5.ComputeHash(bytes_md5_in); 109 } 110 } 111 #endregion 112 113 #region 签名验证-方法三 114 /// 115 /// 验证签名 116 /// 117 /// 原始数据 118 /// 签名 119 /// 120 public static bool CheckSign(string publicKey, string data, string sign, string encoding = "UTF-8") 121 { 122 123 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 124 rsa.FromPublicKeyJavaString(publicKey); 125 MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); 126 127 byte[] Data = Encoding.GetEncoding(encoding).GetBytes(data); 128 byte[] rgbSignature = Convert.FromBase64String(sign); 129 if (rsa.VerifyData(Data, md5, rgbSignature)) 130 { 131 return true; 132 } 133 return false; 134 } 135 #endregion 136 #endregion
加密:
1 #region 加密 2 3 4 ///5 /// RSA加密 6 /// 7 /// 8 /// 9 /// 10 public static string EncryptJava(string publicKeyJava, string data, string encoding = "UTF-8") 11 { 12 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 13 byte[] cipherbytes; 14 rsa.FromPublicKeyJavaString(publicKeyJava); 15 16 //☆☆☆☆.NET 4.6以后特有☆☆☆☆ 17 //HashAlgorithmName hashName = new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm); 18 //RSAEncryptionPadding padding = RSAEncryptionPadding.OaepSHA512;//RSAEncryptionPadding.CreateOaep(hashName);//.NET 4.6以后特有 19 //cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding); 20 //☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ 21 22 //☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆ 23 cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), false); 24 25 return Convert.ToBase64String(cipherbytes); 26 } 27 /// 28 /// RSA加密 29 /// 30 /// 31 /// 32 /// 33 public static string EncryptCSharp(string publicKeyCSharp, string data, string encoding = "UTF-8") 34 { 35 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 36 byte[] cipherbytes; 37 rsa.FromXmlString(publicKeyCSharp); 38 39 //☆☆☆☆.NET 4.6以后特有☆☆☆☆ 40 //HashAlgorithmName hashName = new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm); 41 //RSAEncryptionPadding padding = RSAEncryptionPadding.OaepSHA512;//RSAEncryptionPadding.CreateOaep(hashName);//.NET 4.6以后特有 42 //cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding); 43 //☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ 44 45 //☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆ 46 cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), false); 47 48 return Convert.ToBase64String(cipherbytes); 49 } 50 51 /// 52 /// RSA加密PEM秘钥 53 /// 54 /// 55 /// 56 /// 57 public static string EncryptPEM(string publicKeyPEM, string data, string encoding = "UTF-8") 58 { 59 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 60 byte[] cipherbytes; 61 rsa.LoadPublicKeyPEM(publicKeyPEM); 62 63 //☆☆☆☆.NET 4.6以后特有☆☆☆☆ 64 //HashAlgorithmName hashName = new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm); 65 //RSAEncryptionPadding padding = RSAEncryptionPadding.OaepSHA512;//RSAEncryptionPadding.CreateOaep(hashName);//.NET 4.6以后特有 66 //cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding); 67 //☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ 68 69 //☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆ 70 cipherbytes = rsa.Encrypt(Encoding.GetEncoding(encoding).GetBytes(data), false); 71 72 return Convert.ToBase64String(cipherbytes); 73 } 74 #endregion
解密:
1 #region 解密 2 3 4 ///5 /// RSA解密 6 /// 7 /// 8 /// 9 /// 10 public static string DecryptJava(string privateKeyJava, string data, string encoding = "UTF-8") 11 { 12 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 13 byte[] cipherbytes; 14 rsa.FromPrivateKeyJavaString(privateKeyJava); 15 //☆☆☆☆.NET 4.6以后特有☆☆☆☆ 16 //RSAEncryptionPadding padding = RSAEncryptionPadding.CreateOaep(new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm));//.NET 4.6以后特有 17 //cipherbytes = rsa.Decrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding); 18 //☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ 19 20 //☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆ 21 cipherbytes = rsa.Decrypt(Convert.FromBase64String(data), false); 22 23 return Encoding.GetEncoding(encoding).GetString(cipherbytes); 24 } 25 /// 26 /// RSA解密 27 /// 28 /// 29 /// 30 /// 31 public static string DecryptCSharp(string privateKeyCSharp, string data, string encoding = "UTF-8") 32 { 33 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 34 byte[] cipherbytes; 35 rsa.FromXmlString(privateKeyCSharp); 36 //☆☆☆☆.NET 4.6以后特有☆☆☆☆ 37 //RSAEncryptionPadding padding = RSAEncryptionPadding.CreateOaep(new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm));//.NET 4.6以后特有 38 //cipherbytes = rsa.Decrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding); 39 //☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ 40 41 //☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆ 42 cipherbytes = rsa.Decrypt(Convert.FromBase64String(data), false); 43 44 return Encoding.GetEncoding(encoding).GetString(cipherbytes); 45 } 46 /// 47 /// RSA解密 48 /// 49 /// 50 /// 51 /// 52 public static string DecryptPEM(string privateKeyPEM, string data, string encoding = "UTF-8") 53 { 54 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 55 byte[] cipherbytes; 56 rsa.LoadPrivateKeyPEM(privateKeyPEM); 57 //☆☆☆☆.NET 4.6以后特有☆☆☆☆ 58 //RSAEncryptionPadding padding = RSAEncryptionPadding.CreateOaep(new System.Security.Cryptography.HashAlgorithmName(hashAlgorithm));//.NET 4.6以后特有 59 //cipherbytes = rsa.Decrypt(Encoding.GetEncoding(encoding).GetBytes(data), padding); 60 //☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ 61 62 //☆☆☆☆.NET 4.6以前请用此段代码☆☆☆☆ 63 cipherbytes = rsa.Decrypt(Convert.FromBase64String(data), false); 64 65 return Encoding.GetEncoding(encoding).GetString(cipherbytes); 66 } 67 #endregion
RSA扩展方法:
1 public static class RSAExtensions 2 { 3 ///4 /// 把java的私钥转换成.net的xml格式 5 /// 6 /// 7 /// 8 /// 9 public static string ConvertToXmlPrivateKey(this RSA rsa, string privateJavaKey) 10 { 11 RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateJavaKey)); 12 string xmlPrivateKey = string.Format(" ", 13 Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()), 14 Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()), 15 Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()), 16 Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()), 17 Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()), 18 Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()), 19 Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()), 20 Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned())); 21 return xmlPrivateKey; 22 } 23 /// {0} {1} {2}
{3}{4} {5} {6} {7} 24 /// RSA加载JAVA PrivateKey 25 /// 26 /// java提供的第三方私钥 27 /// 28 public static void FromPrivateKeyJavaString(this RSA rsa, string privateJavaKey) 29 { 30 string xmlPrivateKey = rsa.ConvertToXmlPrivateKey(privateJavaKey); 31 rsa.FromXmlString(xmlPrivateKey); 32 } 33 34 /// 35 /// 把java的公钥转换成.net的xml格式 36 /// 37 /// java提供的第三方公钥 38 /// 39 public static string ConvertToXmlPublicJavaKey(this RSA rsa, string publicJavaKey) 40 { 41 RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicJavaKey)); 42 string xmlpublicKey = string.Format(" ", 43 Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), 44 Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); 45 return xmlpublicKey; 46 } 47 48 /// {0} {1} 49 /// 把java的私钥转换成.net的xml格式 50 /// 51 /// java提供的第三方公钥 52 /// 53 public static void FromPublicKeyJavaString(this RSA rsa, string publicJavaKey) 54 { 55 string xmlpublicKey = rsa.ConvertToXmlPublicJavaKey(publicJavaKey); 56 rsa.FromXmlString(xmlpublicKey); 57 } 58 ///// 59 ///// RSA公钥格式转换,java->.net 60 ///// 61 ///// java生成的公钥 62 ///// 63 //private static string ConvertJavaPublicKeyToDotNet(this RSA rsa,string publicKey) 64 //{ 65 // RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey)); 66 // return string.Format(" ", 67 // Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), 68 // Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); 69 //} 70 71 /// {0} {1} Extension method for initializing a RSACryptoServiceProvider from PEM data string. 72 73 #region Methods 74 75 /// Extension method which initializes an RSACryptoServiceProvider from a DER public key blob. 76 public static void LoadPublicKeyDER(this RSACryptoServiceProvider provider, byte[] DERData) 77 { 78 byte[] RSAData = GetRSAFromDER(DERData); 79 byte[] publicKeyBlob = GetPublicKeyBlobFromRSA(RSAData); 80 provider.ImportCspBlob(publicKeyBlob); 81 } 82 83 /// Extension method which initializes an RSACryptoServiceProvider from a DER private key blob. 84 public static void LoadPrivateKeyDER(this RSACryptoServiceProvider provider, byte[] DERData) 85 { 86 byte[] privateKeyBlob = GetPrivateKeyDER(DERData); 87 provider.ImportCspBlob(privateKeyBlob); 88 } 89 90 /// Extension method which initializes an RSACryptoServiceProvider from a PEM public key string. 91 public static void LoadPublicKeyPEM(this RSACryptoServiceProvider provider, string sPEM) 92 { 93 byte[] DERData = GetDERFromPEM(sPEM); 94 LoadPublicKeyDER(provider, DERData); 95 } 96 97 /// Extension method which initializes an RSACryptoServiceProvider from a PEM private key string. 98 public static void LoadPrivateKeyPEM(this RSACryptoServiceProvider provider, string sPEM) 99 { 100 byte[] DERData = GetDERFromPEM(sPEM); 101 LoadPrivateKeyDER(provider, DERData); 102 } 103 104 /// Returns a public key blob from an RSA public key. 105 internal static byte[] GetPublicKeyBlobFromRSA(byte[] RSAData) 106 { 107 byte[] data = null; 108 UInt32 dwCertPublicKeyBlobSize = 0; 109 if (CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, 110 new IntPtr((int)CRYPT_OUTPUT_TYPES.RSA_CSP_PUBLICKEYBLOB), RSAData, (UInt32)RSAData.Length, CRYPT_DECODE_FLAGS.NONE, 111 data, ref dwCertPublicKeyBlobSize)) 112 { 113 data = new byte[dwCertPublicKeyBlobSize]; 114 if (!CryptDecodeObject(CRYPT_ENCODING_FLAGS.X509_ASN_ENCODING | CRYPT_ENCODING_FLAGS.PKCS_7_ASN_ENCODING, 115 new IntPtr((int)CRYPT_OUTPUT_TYPES.RSA_CSP_PUBLICKEYBLOB), RSAData, (UInt32)RSAData.Length, CRYPT_DECODE_FLAGS.NONE, 116 data, ref dwCertPublicKeyBlobSize)) 117 throw new Win32Exception(Marshal.GetLastWin32Error()); 118 } 119 else 120 throw new Win32Exception(Marshal.GetLastWin32Error()); 121 return data; 122 } 123 124 /// Converts DER binary format to a CAPI CRYPT_PRIVATE_KEY_INFO structure. 125 internal static byte[] GetPrivateKeyDER(byte[] DERData) 126 { 127 byte[] data = null; 128 UInt32 dwRSAPrivateKeyBlobSize = 0; 129 IntPtr pRSAPrivateKeyBlob = IntPtr.Zero; 130 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), 131 DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwRSAPrivateKeyBlobSize)) 132 { 133 data = new byte[dwRSAPrivateKeyBlobSize]; 134 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), 135 DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwRSAPrivateKeyBlobSize)) 136 throw new Win32Exception(Marshal.GetLastWin32Error()); 137 } 138 else 139 throw new Win32Exception(Marshal.GetLastWin32Error()); 140 return data; 141 } 142 143 /// Converts DER binary format to a CAPI CERT_PUBLIC_KEY_INFO structure containing an RSA key. 144 internal static byte[] GetRSAFromDER(byte[] DERData) 145 { 146 byte[] data = null; 147 byte[] publicKey = null; 148 CERT_PUBLIC_KEY_INFO info; 149 UInt32 dwCertPublicKeyInfoSize = 0; 150 IntPtr pCertPublicKeyInfo = IntPtr.Zero; 151 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), 152 DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwCertPublicKeyInfoSize)) 153 { 154 data = new byte[dwCertPublicKeyInfoSize]; 155 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), 156 DERData, (UInt32)DERData.Length, CRYPT_DECODE_FLAGS.NONE, data, ref dwCertPublicKeyInfoSize)) 157 { 158 GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); 159 try 160 { 161 info = (CERT_PUBLIC_KEY_INFO)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(CERT_PUBLIC_KEY_INFO)); 162 publicKey = new byte[info.PublicKey.cbData]; 163 Marshal.Copy(info.PublicKey.pbData, publicKey, 0, publicKey.Length); 164 } 165 finally 166 { 167 handle.Free(); 168 } 169 } 170 else 171 throw new Win32Exception(Marshal.GetLastWin32Error()); 172 } 173 else 174 throw new Win32Exception(Marshal.GetLastWin32Error()); 175 return publicKey; 176 } 177 178 /// Extracts the binary data from a PEM file. 179 internal static byte[] GetDERFromPEM(string sPEM) 180 { 181 UInt32 dwSkip, dwFlags; 182 UInt32 dwBinarySize = 0; 183 184 if (!CryptStringToBinary(sPEM, (UInt32)sPEM.Length, CRYPT_STRING_FLAGS.CRYPT_STRING_BASE64HEADER, null, ref dwBinarySize, out dwSkip, out dwFlags)) 185 throw new Win32Exception(Marshal.GetLastWin32Error()); 186 187 byte[] decodedData = new byte[dwBinarySize]; 188 if (!CryptStringToBinary(sPEM, (UInt32)sPEM.Length, CRYPT_STRING_FLAGS.CRYPT_STRING_BASE64HEADER, decodedData, ref dwBinarySize, out dwSkip, out dwFlags)) 189 throw new Win32Exception(Marshal.GetLastWin32Error()); 190 return decodedData; 191 } 192 193 #endregion Methods 194 195 #region P/Invoke Constants 196 197 /// Enumeration derived from Crypto API. 198 internal enum CRYPT_ACQUIRE_CONTEXT_FLAGS : uint 199 { 200 CRYPT_NEWKEYSET = 0x8, 201 CRYPT_DELETEKEYSET = 0x10, 202 CRYPT_MACHINE_KEYSET = 0x20, 203 CRYPT_SILENT = 0x40, 204 CRYPT_DEFAULT_CONTAINER_OPTIONAL = 0x80, 205 CRYPT_VERIFYCONTEXT = 0xF0000000 206 } 207 208 /// Enumeration derived from Crypto API. 209 internal enum CRYPT_PROVIDER_TYPE : uint 210 { 211 PROV_RSA_FULL = 1 212 } 213 214 /// Enumeration derived from Crypto API. 215 internal enum CRYPT_DECODE_FLAGS : uint 216 { 217 NONE = 0, 218 CRYPT_DECODE_ALLOC_FLAG = 0x8000 219 } 220 221 /// Enumeration derived from Crypto API. 222 internal enum CRYPT_ENCODING_FLAGS : uint 223 { 224 PKCS_7_ASN_ENCODING = 0x00010000, 225 X509_ASN_ENCODING = 0x00000001, 226 } 227 228 /// Enumeration derived from Crypto API. 229 internal enum CRYPT_OUTPUT_TYPES : int 230 { 231 X509_PUBLIC_KEY_INFO = 8, 232 RSA_CSP_PUBLICKEYBLOB = 19, 233 PKCS_RSA_PRIVATE_KEY = 43, 234 PKCS_PRIVATE_KEY_INFO = 44 235 } 236 237 /// Enumeration derived from Crypto API. 238 internal enum CRYPT_STRING_FLAGS : uint 239 { 240 CRYPT_STRING_BASE64HEADER = 0, 241 CRYPT_STRING_BASE64 = 1, 242 CRYPT_STRING_BINARY = 2, 243 CRYPT_STRING_BASE64REQUESTHEADER = 3, 244 CRYPT_STRING_HEX = 4, 245 CRYPT_STRING_HEXASCII = 5, 246 CRYPT_STRING_BASE64_ANY = 6, 247 CRYPT_STRING_ANY = 7, 248 CRYPT_STRING_HEX_ANY = 8, 249 CRYPT_STRING_BASE64X509CRLHEADER = 9, 250 CRYPT_STRING_HEXADDR = 10, 251 CRYPT_STRING_HEXASCIIADDR = 11, 252 CRYPT_STRING_HEXRAW = 12, 253 CRYPT_STRING_NOCRLF = 0x40000000, 254 CRYPT_STRING_NOCR = 0x80000000 255 } 256 257 #endregion P/Invoke Constants 258 259 #region P/Invoke Structures 260 261 /// Structure from Crypto API. 262 [StructLayout(LayoutKind.Sequential)] 263 internal struct CRYPT_OBJID_BLOB 264 { 265 internal UInt32 cbData; 266 internal IntPtr pbData; 267 } 268 269 /// Structure from Crypto API. 270 [StructLayout(LayoutKind.Sequential)] 271 internal struct CRYPT_ALGORITHM_IDENTIFIER 272 { 273 internal IntPtr pszObjId; 274 internal CRYPT_OBJID_BLOB Parameters; 275 } 276 277 /// Structure from Crypto API. 278 [StructLayout(LayoutKind.Sequential)] 279 struct CRYPT_BIT_BLOB 280 { 281 internal UInt32 cbData; 282 internal IntPtr pbData; 283 internal UInt32 cUnusedBits; 284 } 285 286 /// Structure from Crypto API. 287 [StructLayout(LayoutKind.Sequential)] 288 struct CERT_PUBLIC_KEY_INFO 289 { 290 internal CRYPT_ALGORITHM_IDENTIFIER Algorithm; 291 internal CRYPT_BIT_BLOB PublicKey; 292 } 293 294 #endregion P/Invoke Structures 295 296 #region P/Invoke Functions 297 298 /// Function for Crypto API. 299 [DllImport("advapi32.dll", SetLastError = true)] 300 [return: MarshalAs(UnmanagedType.Bool)] 301 internal static extern bool CryptDestroyKey(IntPtr hKey); 302 303 /// Function for Crypto API. 304 [DllImport("advapi32.dll", SetLastError = true)] 305 [return: MarshalAs(UnmanagedType.Bool)] 306 internal static extern bool CryptImportKey(IntPtr hProv, byte[] pbKeyData, UInt32 dwDataLen, IntPtr hPubKey, UInt32 dwFlags, ref IntPtr hKey); 307 308 /// Function for Crypto API. 309 [DllImport("advapi32.dll", SetLastError = true)] 310 [return: MarshalAs(UnmanagedType.Bool)] 311 internal static extern bool CryptReleaseContext(IntPtr hProv, Int32 dwFlags); 312 313 /// Function for Crypto API. 314 [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 315 [return: MarshalAs(UnmanagedType.Bool)] 316 internal static extern bool CryptAcquireContext(ref IntPtr hProv, string pszContainer, string pszProvider, CRYPT_PROVIDER_TYPE dwProvType, CRYPT_ACQUIRE_CONTEXT_FLAGS dwFlags); 317 318 /// Function from Crypto API. 319 [DllImport("crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)] 320 [return: MarshalAs(UnmanagedType.Bool)] 321 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); 322 323 /// Function from Crypto API. 324 [DllImport("crypt32.dll", SetLastError = true)] 325 [return: MarshalAs(UnmanagedType.Bool)] 326 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); 327 328 /// Function from Crypto API. 329 [DllImport("crypt32.dll", SetLastError = true)] 330 [return: MarshalAs(UnmanagedType.Bool)] 331 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); 332 333 #endregion P/Invoke Functions 334 }
单元测试:
1 [TestClass] 2 public class RSAHelperTest 3 { 4 string publicKeyJava = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkixtIe0MzCFDW3eCDSq/6SFFN+eK+zg1q62SX 5 TbJprt7zOD6D9A8zU1fTEzY9+0gVUYmOMPOF8jI8EMZOnl2jDUtn3KdD2Uuee3/cmEfMpAN++KMG 6 6Tfm3p3Iz4kw/dLmM1EAkADIp4zFmkvxd/BN+dmT/1Tp87mMUQBS8mvdRwIDAQAB"; 7 string privateKeyJava = @"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKSLG0h7QzMIUNbd4INKr/pIUU35 8 4r7ODWrrZJdNsmmu3vM4PoP0DzNTV9MTNj37SBVRiY4w84XyMjwQxk6eXaMNS2fcp0PZS557f9yY 9 R8ykA374owbpN+bencjPiTD90uYzUQCQAMinjMWaS/F38E352ZP/VOnzuYxRAFLya91HAgMBAAEC 10 gYBXJCSq2jzYhgrqAE+quJ9CGZKVjUV8b3vDqC55wvg96BLDFIJnN5XlRLo6Wu5bHP0r7SbAW0Rd 11 J8ta7DdZ450Kow+k2Z69gYO818cptQXYrs4ky6M48NXeSSoYeGESxW7LGJs++o2nGmVRkhj4DMYY 12 8lur1oYsyDAy/d3B0ucnwQJBAP0Kc2KCOl8xnbXUuoFhJHaVoKPWqdhody5sNHK+11Bgc3/ZhqNM 13 T1uIiiZnB3CTyfKeJAgX0fwde7fmtZHaUO8CQQCmd7a3qXvUbnQao03ITrthGRvGAJSAfTAG/VEx 14 2g1knxUmiq+bek+FGi7UYXYRZ/rVqX934ztTAOnBqVtnK4kpAkEAs6KAqVUkFUJG4LfFM2YAGcM9 15 SDJzXvNCcI1WaoM6nY/rTr7hCvp4d9WlpX+M04nHWtqTX79xTdasZrB9A68FtwJAHXWmIk6eGXQK 16 nAQ2abJ1OrPE1H+ZyDtfWn1N9zKNmDcG+TEl7q/wjq+ZhgBRcrciDtnWMxNFlmTc+WbNRC7SMQJB 17 AIBSE1kfhy3V63db91Gnr789G2QKy3TI46QEY3dirLiXWF3/tt+9K8itjeB22S5S7cWbzJ+2FIFW 18 mFB/DP3ER8Q="; 19 20 string publicKeyPEM = @"-----BEGIN PUBLIC KEY----- 21 MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe8W+2jrrWY55W8nZcWCBXQSJJ 22 uJxkannRsZbwiwJBftXCzN0wSaujwmT0S0Aqttnqg/sO+jDHVnpph8omZdSvnySt 23 /PiGEqmsk+6AsgZ7eczeokVkrFvVbjq13s6NVF8tgMds/w5VG8+uEECmiHCKM8/V 24 3oXhq7aLPLINFYggcQIDAQAB 25 -----END PUBLIC KEY----- 26 "; 27 string privateKeyPEM = @"-----BEGIN RSA PRIVATE KEY----- 28 MIICWwIBAAKBgQDe8W+2jrrWY55W8nZcWCBXQSJJuJxkannRsZbwiwJBftXCzN0w 29 SaujwmT0S0Aqttnqg/sO+jDHVnpph8omZdSvnySt/PiGEqmsk+6AsgZ7eczeokVk 30 rFvVbjq13s6NVF8tgMds/w5VG8+uEECmiHCKM8/V3oXhq7aLPLINFYggcQIDAQAB 31 AoGAN9OnkMRe/u6FKOqgPvGGb7MMvf8vkmmjRaI91NBKaVI0fwpD3SKli2VTWGU7 32 lTaijPottQtriY8bKi/prAHV5wiSetsiPB9DQq8bN3rLtJPG6NCmwiOUhamBg9kD 33 VbqOb/1dg0vGL1zEKxtscaK5yDCBnyX+4LfAR5Upg0Q4t70CQQD8n5XxSdQpHNAf 34 sl26cTxf6YHCzHoqUfDo4SE74jWy8ooNF3qk0jaYy6+N1EOLwpMfm2MeWdxCYFmC 35 9NdbowIDAkEA4exKy9FGTPVkkVhAwva0fm7/mJSHsl7btPTJvmgEfO9eHbozYacQ 36 2PmbZd46uPzaI0LaDh8ICbaLvf8IPiVjewJAXIMUpggjaerjTLhFGsHdGkKpAm1f 37 T6AyWRYY1ZVBlQa9B45Rm4pf9BSjdY0GL2hR+IEvCy5dOvGN1idTtns7gQJAfiqO 38 TqptPxcfdYe6iuZpP95PAO+ZpEQTIEg/zgSa1QZ8Ic/VV+iLoRAr90SWuK4ESALS 39 cWZk/7+g5JbjDImmtwJAfBpGw+TVeMw+2Oo9GJnIM9Ga/hiYQDCkZ9A/4fYrNxxr 40 znkMqFQ28dhYQbKK9/WcPTjHGakpY/2hY/9dki6CJw== 41 -----END RSA PRIVATE KEY----- 42 "; 43 [TestMethod] 44 public void RSA_Java_MD5Verify() 45 { 46 string data = "hello word!"; 47 string hashAlgorithm = "MD5"; 48 string signResult = RSAHelper.RSASignJava(data,privateKeyJava, hashAlgorithm); 49 string sign1 = "bI/x8LHsuvCVgO7YEBA0hvQWdpLzqdThfYKYEeo4YFTclhFV+R4QCN2FgYshZqjDTBzHAvRHxoRk4kbYWeOuVNG+W3exdtqfUuUp29EgxEPFfqECUqucgN/bFxrtKtNGOCAqOBSx6SBkRpByKEAH7FHsRmPS4Bd4MUT4xr9gGg8="; 50 if (sign1 == signResult) 51 { 52 53 } 54 bool result = RSAHelper.VerifyJava(data, publicKeyJava, signResult, hashAlgorithm); 55 if (!result) 56 { 57 int a = 0; 58 int b = 0 / a; 59 } 60 Console.WriteLine(hashAlgorithm + ":" + result); 61 } 62 [TestMethod] 63 public void RSA_Java_SHA1Verify() 64 { 65 //通过测试 66 string data = "hello word!"; 67 string hashAlgorithm = "SHA1"; 68 string signResult = RSAHelper.RSASignJava(data,privateKeyJava, hashAlgorithm); 69 bool result = RSAHelper.VerifyJava(data,publicKeyJava, signResult, hashAlgorithm); 70 if (!result) 71 { 72 int a = 0; 73 int b = 0 / a; 74 } 75 Console.WriteLine(hashAlgorithm + ":" + result); 76 } 77 78 [TestMethod] 79 public void RSA_Java_SHA256Verify() 80 { 81 //未通过 82 string data = "hello word!"; 83 string hashAlgorithm = "SHA256"; 84 string signResult = RSAHelper.RSASignJava(data,privateKeyJava, hashAlgorithm); 85 bool result = RSAHelper.VerifyJava(data,publicKeyJava, signResult, hashAlgorithm); 86 if (!result) 87 { 88 int a = 0; 89 int b = 0 / a; 90 } 91 Console.WriteLine(hashAlgorithm + ":" + result); 92 } 93 [TestMethod] 94 public void RSASign_JAVA_WithVerify() 95 { 96 string data = "hello word!"; 97 //"RIPEMD160", 98 List<string> hashAlgorithmList = new List<string>() { "MD5", "SHA1", "SHA256", "SHA384", "SHA512" };//{MD5、RIPEMD160、SHA1、SHA256、SHA384、SHA512} 99 foreach (var hashAlgorithm in hashAlgorithmList) 100 { 101 string signResult = RSAHelper.RSASignJava(data,privateKeyJava, hashAlgorithm); 102 bool result = RSAHelper.VerifyJava(data,publicKeyJava, signResult, hashAlgorithm); 103 if (!result) 104 { 105 int a = 0; 106 int b = 0 / a; 107 } 108 Console.WriteLine(hashAlgorithm + ":" + result); 109 } 110 111 112 } 113 [TestMethod] 114 public void RSASign_PEM_WithVerify() 115 { 116 string data = "hello word!"; 117 //"RIPEMD160", 118 List<string> hashAlgorithmList = new List<string>() { "MD5", "SHA1", "SHA256", "SHA384", "SHA512" };//{MD5、RIPEMD160、SHA1、SHA256、SHA384、SHA512} 119 foreach (var hashAlgorithm in hashAlgorithmList) 120 { 121 string signResult = RSAHelper.RSASignPEM(data, privateKeyPEM, hashAlgorithm); 122 bool result = RSAHelper.VerifyPEM(data, publicKeyPEM, signResult, hashAlgorithm); 123 if (!result) 124 { 125 int a = 0; 126 int b = 0 / a; 127 } 128 Console.WriteLine(hashAlgorithm + ":" + result); 129 } 130 131 132 } 133 134 [TestMethod] 135 public void RSA_Java_EncryptWithDecrypt() 136 { 137 138 string data = "hello word!";//"MD5", 139 140 string encryptResult = RSAHelper.EncryptJava(publicKeyJava,data); 141 string decryptResult = RSAHelper.DecryptJava(privateKeyJava,encryptResult); 142 if (data != decryptResult) 143 { 144 int a = 0; 145 int b = 0 / a; 146 } 147 148 149 } 150 [TestMethod] 151 public void RSA_PEM_EncryptWithDecrypt() 152 { 153 string data = "hello word!";//"MD5", 154 155 string encryptResult = RSAHelper.EncryptPEM(publicKeyPEM,data); 156 string decryptResult = RSAHelper.DecryptPEM(privateKeyPEM,encryptResult); 157 if (data != decryptResult) 158 { 159 int a = 0; 160 int b = 0 / a; 161 } 162 } 163 }
测试结果:
下载地址:
https://files.cnblogs.com/files/kevin860/RSA.zip