zoukankan      html  css  js  c++  java
  • [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("
    ", "").Replace("
    ", ""); 
     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

  • 相关阅读:
    防抖节流函数
    富文本编辑器tinymce在vue中的使用
    vue脚手架中检测lodop安装情况
    打印插件LODOP Vue中的使用
    vue打包后刷新页面报错:Unexpected token <
    Bootstrap-table表格插件的使用方法
    jsTree树插件
    Vue监控器watch的全面解析
    Vue计算属性computed的全面解析
    基于JQuery可拖动列表格插件DataTables的踩坑记
  • 原文地址:https://www.cnblogs.com/arcsinw/p/4954833.html
Copyright © 2011-2022 走看看