[WP8.1]RSA 使用BouncyCastle 公钥解密

      写应用的时候遇到个服务器返回私钥加密过的数据 ,然后要在客户端用公钥解密的需求 ,一直没找到方法,应用搁置了一个学期,多方搜索,结论就是.net没有实现公钥解密的方法,要自己实现,于是硬着头皮开始看 portable.bouncycastle

      关于RSA的原理,这是我从MSDN盗的图,链接在这https://msdn.microsoft.com/zh-cn/library/system.security.cryptography.rsaparameters.aspx

简单说就是

密文 = (明文 ^privateExponent) mod modulus

明文 = (密文 ^publicExponent) mod modulus

 

公钥中含有两个参数 一个是modulus ,另一个是publicExponent,私钥中有 modulus和privateExponent两个参数(当然私钥中不止这两个参数,但方法里只用到这两个,其他不管)

由于拿到的公钥和私钥都是PEM格式的,所以要先从PEM格式的公钥和私钥中提取这些参数 ,然后进行大数运算就能得出结果

这里要感谢前辈的努力,详细的解析了PEM文件格式

现在假设假设公钥和私钥分别为

 1      const string PUBLICKEY =
 2              @"-----BEGIN PUBLIC KEY-----
 3                 MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpsDr+W45aFHIkvotZaGK/THlF
 4                 FpuZfUtghhWkHAm3H7yvL42J4xHrTr6IeUDCl4eKe6qiIgvYSNoL3u4SERGOeYmV
 5                 1F+cocu9IMGnNoicbh1zVW6e8/iGT3xaYQizJoVuWA/TC/zdds2ihCJfHDBDsouO
 6                 CXecPapyWCGQNsH5sQIDAQAB
 7                 -----END PUBLIC KEY-----";
 8         const string PRIVATEKEY =
 9                 @"-----BEGIN RSA PRIVATE KEY-----
10                 MIICXQIBAAKBgQDpsDr+W45aFHIkvotZaGK/THlFFpuZfUtghhWkHAm3H7yvL42J
11                 4xHrTr6IeUDCl4eKe6qiIgvYSNoL3u4SERGOeYmV1F+cocu9IMGnNoicbh1zVW6e
12                 8/iGT3xaYQizJoVuWA/TC/zdds2ihCJfHDBDsouOCXecPapyWCGQNsH5sQIDAQAB
13                 AoGBAM/JbFs4y5WbMncrmjpQj+UrOXVOCeLrvrc/4kQ+zgCvTpWywbaGWiuRo+cz
14                 cXrVQ6bGGU362e9hr8f4XFViKemDL4SmJbgSDa1K71i+/LnnzF6sjiDBFQ/jA9SK
15                 4PYrY7a3IkeBQnJmknanykugyQ1xmCjbuh556fOeRPaHnhx1AkEA/flrxJSy1Z+n
16                 Y1RPgDOeDqyG6MhwU1Jl0yJ1sw3Or4qGRXhjTeGsCrKqV0/ajqdkDEM7FNkqnmsB
17                 +vPd116J6wJBAOuNY3oOWvy2fQ32mj6XV+S2vcG1osEUaEuWvEgkGqJ9co6100Qp
18                 j15036AQEEDqbjdqS0ShfeRSwevTJZIap9MCQCeMGDDjKrnDA5CfB0YiQ4FrchJ7
19                 a6o90WdAHW3FP6LsAh59MZFmC6Ea0xWHdLPz8stKCMAlVNKYPRWztZ6ctQMCQQC8
20                 iWbeAy+ApvBhhMjg4HJRdpNbwO6MbLEuD3CUrZFEDfTrlU2MeVdv20xC6ZiY3Qtq
21                 /4FPZZNGdZcSEuc3km5RAkApGkZmWetNwDJMcUJbSBrQMFfrQObqMPBPe+gEniQq
22                 Ttwu1OULHlmUg9eW31wRI2uiXcFCJMHuro6iOQ1VJ4Qs
23                 -----END RSA PRIVATE KEY-----";

于是获取公钥参数的方法为

 1  // 获取modulus和publicExponent
 2  string publicKey = PUBLICKEY.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", ""); 
 3  byte[] btPem = Convert.FromBase64String(publicKey);
 4  int pemModulus = 128, pemPublicExponent = 3;
 5  byte[] btPemModulus = new byte[128];
 6  byte[] btPemPublicExponent = new byte[3];
 7  for (int i = 0; i < pemModulus; i++)
 8  {
 9      btPemModulus[i] = btPem[29 + i];
10  }
11  for (int i = 0; i < pemPublicExponent; i++)
12  {
13      btPemPublicExponent[i] = btPem[159 + i];
14  }

 公钥解密的方法为

1 BigInteger biModulus = new BigInteger(1, btPemModulus);
2 BigInteger biExponent = new BigInteger(1, btPemPublicExponent);
3 RsaKeyParameters publicParameters = new RsaKeyParameters(false, biModulus, biExponent);
4 IAsymmetricBlockCipher eng = new Pkcs1Encoding(new RsaEngine());
5 eng.Init(false, publicParameters);
6 // 解密已加密的数据
7 byte[] encryptedData = Convert.FromBase64String(rawData);
8 encryptedData = eng.ProcessBlock(encryptedData, 0, encryptedData.Length);
9 string result = Encoding.UTF8.GetString(encryptedData, 0, encryptedData.Length);

公钥加密的方法为

1 BigInteger biModulus = new BigInteger(1, btPemModulus);
2 BigInteger biExponent = new BigInteger(1, btPemPublicExponent);
3 RsaKeyParameters publicParameters = new RsaKeyParameters(false, biModulus, biExponent);
4 IAsymmetricBlockCipher eng = new Pkcs1Encoding(new RsaEngine());
5 eng.Init(true, publicParameters);
6 // 加密数据
7 byte[] encryptData = Encoding.UTF8.GetBytes(rawData);
8 encryptData = eng.ProcessBlock(encryptData, 0, encryptData.Length);
9 string result = Convert.ToBase64String(encryptData);

私钥的通过PEM文件格式详细解析里的图也可以方便的写出来,mark下以后写……( ̄o ̄) . z Z

顺便贴上WP 8.1里自带的RSA公钥加密 私钥解密

 1      /// <summary>
 2         /// WPRT的RSA公钥加密
 3         /// </summary>
 4         /// <param name="rawData">源数据</param>
 5         /// <returns>加密后的数据</returns>
 6         public static string PublicEncrypt(string rawData)
 7         {
 8             try
 9             {
10                 /*将文本转换成IBuffer*/
11                 IBuffer bufferRawData = CryptographicBuffer.ConvertStringToBinary(rawData, BinaryStringEncoding.Utf8);
12 
13                 /*加密算法提供程序*/
14                 AsymmetricKeyAlgorithmProvider provider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm
15                     (AsymmetricAlgorithmNames.RsaPkcs1);
16 
17                 /*导入公钥*/
18                 string PUBLIC_KEY = PUBLICKEY.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "");
19                 CryptographicKey publicKey = provider.ImportPublicKey(CryptographicBuffer.DecodeFromBase64String(PUBLIC_KEY));
20 
21                 //加密
22                 IBuffer result = CryptographicEngine.Encrypt(publicKey, bufferRawData, null);
23                 byte[] res;
24                 CryptographicBuffer.CopyToByteArray(result, out res);
25                 Debug.WriteLine("WinRT公钥加密后:" + Convert.ToBase64String(res));
26                 return Convert.ToBase64String(res);
27             }
28             catch (Exception e)
29             {
30                 Debug.WriteLine("Encrypt Exception:" + e.StackTrace);
31                 return rawData;
32             }
33         }
34 
35         /// <summary>
36         /// WPRT的RSA私钥解密
37         /// </summary>
38         /// <param name="rawData"></param>
39         /// <returns></returns>
40         public static string PrivateDecrypt(string rawData)
41         {
42             try
43             {
44                 /*将文本转换成IBuffer*/
45                 IBuffer bufferRawData = CryptographicBuffer.ConvertStringToBinary(rawData, BinaryStringEncoding.Utf8);
46 
47                 /*加密算法提供程序*/
48                 AsymmetricKeyAlgorithmProvider provider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm
49                     (AsymmetricAlgorithmNames.RsaPkcs1);
50 
51                 /*导入私钥*/
52                 string PRIVATE_KEY = PRIVATEKEY.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "");
53                 CryptographicKey privateKey = provider.ImportKeyPair(CryptographicBuffer.DecodeFromBase64String(PRIVATE_KEY));
54 
55                 //解密
56                 IBuffer result = CryptographicEngine.Decrypt(privateKey, bufferRawData, null);
57                 byte[] res;
58                 CryptographicBuffer.CopyToByteArray(result, out res);
59                 Debug.WriteLine("WinRT私钥解密后:" + Encoding.UTF8.GetString(res,0,res.Length));
60                 return Encoding.UTF8.GetString(res,0,res.Length);
61             }
62             catch (Exception e)
63             {
64                 Debug.WriteLine("Decrypt Exception:" + e.StackTrace);
65                 return rawData;
66             }
67         }

 

参考链接

PEM文件格式详细解析

BouncyCastle

posted @ 2015-11-23 13:24  arcsinW  阅读(3745)  评论(1编辑  收藏  举报