C# RSA加密、解密、加签、验签、支持JAVA格式公钥私钥、PEM格式公钥私钥、.NET格式公钥私钥、一般模式【支持公钥加密,私钥解密】(一)...

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("{0}{1}

{2}

{3}{4}{5}{6}{7}
", 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 /// 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("{0}{1}", 43 Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), 44 Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); 45 return xmlpublicKey; 46 } 47 48 /// 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("{0}{1}", 67 // Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), 68 // Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); 69 //} 70 71 /// 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

你可能感兴趣的:(C# RSA加密、解密、加签、验签、支持JAVA格式公钥私钥、PEM格式公钥私钥、.NET格式公钥私钥、一般模式【支持公钥加密,私钥解密】(一)...)