前言

这两天主要是公司同事用到了RSA加密,事后也看了下,以为很简单,最终利用RSACryptoServiceProvider来实现RSA加密,然后大致了解到RSACryptoServiceProvider不支持跨平台,此类原先存在于.NET Framework中,本文我讲讲利用RSA.Create来实现各种加密模式统一封装。

RSA加密或解密

主要是在查找资料时看到了dudu老大写的有关RSA加密的文章(http://www.cnblogs.com/dudu/p/dotnet-core-rsa-openssl.html),刚好找到了我们项目中需要用到的openssl加密模式对应.NET Core中的Pkcs1,这里实现代码实在有点多,然后自己也遇到如评论中所说加密长度超出的情况,这个时候只能采取分段加密的方式。接下来我们来看看。首先看看如下代码:

  1. var privateKey = "<RSAKeyValue><Modulus>0wE26IHp4U9OLtPhJ+fT8ej6aWORFP8pd++MjUuhkQQm/zhcImbxQbjxtSAftz+kkDwGDFJpSldQPyigOGcUx7PofTc6VhiFik9E9SsxV9n0iEEtqUndDfmBJfPAWt+4UDMwKakgZqFoapDuwjKlTErFvKCyKCs+qN9OZvZwKWk=</Modulus><Exponent>AQAB</Exponent><P>8Ei6NIsZtgV3DQjuGHfGLS6o1O+IUXxzjqLxdMm77yhEPUxR9YPIxODJ2VVTddXSAHxViJJt30yJ7JhVz6cpQw==</P><Q>4M49NrmalgVQFMsea2RMB1qN8fAPfIw5G9q9hzsLcWSCmkeRRIQlvPYflVEKAYKiDVVzENETbnnduFXWBABx4w==</Q><DP>t+JQbemN0Zi5FQaif6MZzHYKynpNTl75aE0Wj5Pa+RlNr8N6bXNe8Bw/HM2Jw4HQ5oJASvYUk3DVlHS4JuP8VQ==</DP><DQ>lT62iv9brp9mU/epgVh71SH8PJPIZEJfo6tryjyb0zMMNcqvmZI1z6aCv0mm3+vPFBUXqCF1yhFj7n4l8FAvSw==</DQ><InverseQ>flrvgxHvf4l+fdymEVDgKjsfGqshOpppoNgZj9kpeWBto3o8z++Ki6eSLQT3nVnpx2QCZeTWkxTED4nhSLKscw==</InverseQ><D>cQTCg1Eqk7sltmFYxUYgOP/AOPjSufteG9acYwYymPkvZh6rAuY+rSRBmvGE62NUYskzuB/gM6iG2/2HrA5SixfNgCvZ+nsK+kX5pzQRsYdD71ViQW0hOanXwj45I2zHRgBiuTtCUP0fs5pISmQkaeJkDL5pO2l+wvlgl+wunj0=</D></RSAKeyValue>";
  2. var publicKey = "<RSAKeyValue><Modulus>0wE26IHp4U9OLtPhJ+fT8ej6aWORFP8pd++MjUuhkQQm/zhcImbxQbjxtSAftz+kkDwGDFJpSldQPyigOGcUx7PofTc6VhiFik9E9SsxV9n0iEEtqUndDfmBJfPAWt+4UDMwKakgZqFoapDuwjKlTErFvKCyKCs+qN9OZvZwKWk=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
  3.  
  4. using (var rsa = RSA.Create())
  5. {
  6. rsa.FromXmlString(publicKey);
  7. }

经到github上查找解决方案,我们需要手动设置值,如下:

  1. public static void FromXmlString(RSA rsa, string xmlString)
  2. {
  3. RSAParameters parameters = new RSAParameters();
  4.  
  5. XmlDocument xmlDoc = new XmlDocument();
  6. xmlDoc.LoadXml(xmlString);
  7.  
  8. if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue"))
  9. {
  10. foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
  11. {
  12. switch (node.Name)
  13. {
  14. case "Modulus": parameters.Modulus = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  15. case "Exponent": parameters.Exponent = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  16. case "P": parameters.P = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  17. case "Q": parameters.Q = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  18. case "DP": parameters.DP = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  19. case "DQ": parameters.DQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  20. case "InverseQ": parameters.InverseQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  21. case "D": parameters.D = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  22. }
  23. }
  24. }
  25. else
  26. {
  27. throw new Exception("Invalid XML RSA key.");
  28. }
  29.  
  30. rsa.ImportParameters(parameters);
  31. }

其中经过很多尝试,要么是Base64格式不正确,要么是待解密的数据长度和Key Size无效,我第一次尝试是返回的加密字符串,然后进行解密,就是有问题,最后还是返回字节数组来进行加密和解密,直接看代码,这里解决了加密数据长度超出问题以及各种加密模式的统一,如下RSAHelper。

  1. public static class RSAHelper
  2. {
  3. private const string privateKey = "<RSAKeyValue><Modulus>0wE26IHp4U9OLtPhJ+fT8ej6aWORFP8pd++MjUuhkQQm/zhcImbxQbjxtSAftz+kkDwGDFJpSldQPyigOGcUx7PofTc6VhiFik9E9SsxV9n0iEEtqUndDfmBJfPAWt+4UDMwKakgZqFoapDuwjKlTErFvKCyKCs+qN9OZvZwKWk=</Modulus><Exponent>AQAB</Exponent><P>8Ei6NIsZtgV3DQjuGHfGLS6o1O+IUXxzjqLxdMm77yhEPUxR9YPIxODJ2VVTddXSAHxViJJt30yJ7JhVz6cpQw==</P><Q>4M49NrmalgVQFMsea2RMB1qN8fAPfIw5G9q9hzsLcWSCmkeRRIQlvPYflVEKAYKiDVVzENETbnnduFXWBABx4w==</Q><DP>t+JQbemN0Zi5FQaif6MZzHYKynpNTl75aE0Wj5Pa+RlNr8N6bXNe8Bw/HM2Jw4HQ5oJASvYUk3DVlHS4JuP8VQ==</DP><DQ>lT62iv9brp9mU/epgVh71SH8PJPIZEJfo6tryjyb0zMMNcqvmZI1z6aCv0mm3+vPFBUXqCF1yhFj7n4l8FAvSw==</DQ><InverseQ>flrvgxHvf4l+fdymEVDgKjsfGqshOpppoNgZj9kpeWBto3o8z++Ki6eSLQT3nVnpx2QCZeTWkxTED4nhSLKscw==</InverseQ><D>cQTCg1Eqk7sltmFYxUYgOP/AOPjSufteG9acYwYymPkvZh6rAuY+rSRBmvGE62NUYskzuB/gM6iG2/2HrA5SixfNgCvZ+nsK+kX5pzQRsYdD71ViQW0hOanXwj45I2zHRgBiuTtCUP0fs5pISmQkaeJkDL5pO2l+wvlgl+wunj0=</D></RSAKeyValue>";
  4. private const string publicKey = "<RSAKeyValue><Modulus>0wE26IHp4U9OLtPhJ+fT8ej6aWORFP8pd++MjUuhkQQm/zhcImbxQbjxtSAftz+kkDwGDFJpSldQPyigOGcUx7PofTc6VhiFik9E9SsxV9n0iEEtqUndDfmBJfPAWt+4UDMwKakgZqFoapDuwjKlTErFvKCyKCs+qN9OZvZwKWk=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
  5.  
  6. public static byte[] Encrypt(byte[] encryptBytes, RSAEncryptionPadding padding)
  7. {
  8. using (var rsa = RSA.Create())
  9. {
  10.  
  11. FromXmlString(rsa, publicKey);
  12.  
  13. var maxBlockSize = GetMaxBlockSize(rsa, padding);
  14.  
  15. if (encryptBytes.Length <= maxBlockSize)
  16. {
  17. var @bytes = rsa.Encrypt(encryptBytes, padding);
  18. return @bytes;
  19. }
  20.  
  21. using (var memoryStream = new MemoryStream(encryptBytes))
  22. {
  23. using (var readStream = new MemoryStream())
  24. {
  25. byte[] buffer = new byte[maxBlockSize];
  26.  
  27. int blockSize = memoryStream.Read(buffer, , maxBlockSize);
  28.  
  29. while (blockSize > )
  30. {
  31. var blockByte = new byte[blockSize];
  32.  
  33. Array.Copy(buffer, , blockByte, , blockSize);
  34.  
  35. var encrypts = rsa.Encrypt(blockByte, padding);
  36.  
  37. readStream.Write(encrypts, , encrypts.Length);
  38.  
  39. blockSize = memoryStream.Read(buffer, , maxBlockSize);
  40. }
  41.  
  42. return readStream.ToArray();
  43. }
  44. }
  45. }
  46. }
  47.  
  48. public static byte[] Decrypt(byte[] decryptBytes, RSAEncryptionPadding padding)
  49. {
  50. using (var rsa = RSA.Create())
  51. {
  52. FromXmlString(rsa, privateKey);
  53.  
  54. var maxBlockSize = rsa.KeySize / ;
  55.  
  56. if (decryptBytes.Length <= maxBlockSize)
  57. {
  58. var @bytes = rsa.Decrypt(decryptBytes, padding);
  59. return @bytes;
  60. }
  61.  
  62. using (var memoryStream = new MemoryStream(decryptBytes))
  63. {
  64. using (var readStream = new MemoryStream())
  65. {
  66. var buffer = new byte[maxBlockSize];
  67.  
  68. var blockSize = memoryStream.Read(buffer, , maxBlockSize);
  69.  
  70. while (blockSize > )
  71. {
  72. var blockByte = new byte[blockSize];
  73.  
  74. Array.Copy(buffer, , blockByte, , blockSize);
  75.  
  76. var decrypts = rsa.Decrypt(blockByte, padding);
  77.  
  78. readStream.Write(decrypts, , decrypts.Length);
  79.  
  80. blockSize = memoryStream.Read(buffer, , maxBlockSize);
  81. }
  82.  
  83. return readStream.ToArray();
  84. }
  85. }
  86. }
  87. }
  88.  
  89. public static void FromXmlString(RSA rsa, string xmlString)
  90. {
  91. RSAParameters parameters = new RSAParameters();
  92.  
  93. XmlDocument xmlDoc = new XmlDocument();
  94. xmlDoc.LoadXml(xmlString);
  95.  
  96. if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue"))
  97. {
  98. foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
  99. {
  100. switch (node.Name)
  101. {
  102. case "Modulus": parameters.Modulus = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  103. case "Exponent": parameters.Exponent = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  104. case "P": parameters.P = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  105. case "Q": parameters.Q = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  106. case "DP": parameters.DP = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  107. case "DQ": parameters.DQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  108. case "InverseQ": parameters.InverseQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  109. case "D": parameters.D = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
  110. }
  111. }
  112. }
  113. else
  114. {
  115. throw new Exception("Invalid XML RSA key.");
  116. }
  117.  
  118. rsa.ImportParameters(parameters);
  119. }
  120.  
  121. static int GetMaxBlockSize(RSA rsa, RSAEncryptionPadding padding)
  122. {
  123. var offset = ;
  124. if (padding.Mode == RSAEncryptionPaddingMode.Pkcs1)
  125. {
  126. offset = ;
  127. }
  128. else
  129. {
  130. if (padding.Equals(RSAEncryptionPadding.OaepSHA1))
  131. {
  132. offset = ;
  133. }
  134.  
  135. if (padding.Equals(RSAEncryptionPadding.OaepSHA256))
  136. {
  137. offset = ;
  138. }
  139.  
  140. if (padding.Equals(RSAEncryptionPadding.OaepSHA384))
  141. {
  142. offset = ;
  143. }
  144.  
  145. if (padding.Equals(RSAEncryptionPadding.OaepSHA512))
  146. {
  147. offset = ;
  148. }
  149. }
  150. return rsa.KeySize / - offset;
  151. }
  152. }

我们开始进行如下测试,加密数据长度为6890,如下。

  1. static void Main(string[] args)
  2. {
  3. var encryptString = "";
  4. for (int i = ; i < ; i++)
  5. {
  6. encryptString += i;
  7. }
  8.  
  9. Console.WriteLine(encryptString.Length);
  10.  
  11. var encryptBytes = Encoding.UTF8.GetBytes(encryptString);
  12.  
  13. //加密后字节数组
  14. var resultBytes = RSAHelper.Encrypt(encryptBytes, RSAEncryptionPadding.Pkcs1);
  15.  
  16. //解密后字节数组
  17. var decryptBytes = RSAHelper.Decrypt(resultBytes, RSAEncryptionPadding.Pkcs1);
  18.  
  19. //解密结果
  20. var result = Encoding.UTF8.GetString(decryptBytes);
  21.  
  22. //比较加密字符串和解密结果是否相等
  23. Console.WriteLine(encryptString == result);
  24. Console.ReadKey();
  25. }

总结

本文通过实现RSA加密和解密,同时也对加密数据超出采取分段加密的方式,测试在windows上通过,由于没有linux和mac环境未经测试,不知是否好使,一试见分晓。

ASP.NET Core RSA加密或解密的更多相关文章

  1. 通过ios实现RSA加密和解密

    在加密和解密中,我们需要了解的知识有什么事openssl:RSA加密算法的基本原理:如何通过openssl生成最后我们需要的der和p12文件. 废话不多说,直接写步骤: 第一步:openssl来生成 ...

  2. C#实现RSA加密和解密详解

    原文:C#实现RSA加密和解密详解 RSA加密解密源码: Code highlighting produced by Actipro CodeHighlighter (freeware) http:/ ...

  3. C#实现RSA加密与解密、签名与认证(转)

    一.RSA简介 RSA公钥加密算法是1977年由Ron Rivest.Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的.RSA取名来自开发他们三者的名字.RSA是目前最有影响力 ...

  4. RSA加密和解密工具类

    import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; import java.security.*; i ...

  5. IOS, Android, Java Web Rest : RSA 加密和解密问题

    IOS, Android, Java Web Rest :  RSA 加密和解密问题 一对公钥私钥可以使用 OpenSSL创建, 通常 1024位长度够了. 注意: 1. 公钥私钥是BASE64编码的 ...

  6. C#实现RSA加密与解密、签名与认证

    一.RSA简介 RSA公钥加密算法是1977年由Ron Rivest.Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的.RSA取名来自开发他们三者的名字.RSA是目前最有影响力 ...

  7. C# -- RSA加密与解密

    1.  RSA加密与解密  --  使用公钥加密.私钥解密 public class RSATool { public string Encrypt(string strText, string st ...

  8. python RSA加密、解密、签名

    python RSA加密.解密.签名 python中用于RSA加解密的库有好久个,本文主要讲解rsa.M2Crypto.Crypto这三个库对于RSA加密.解密.签名.验签的知识点. 知识基础 加密是 ...

  9. RSA加密、解密实现原理

    RSA加密.解密实现原理 1.公钥.私钥

随机推荐

  1. 机器学习中如何处理不平衡数据(imbalanced data)?

    推荐一篇英文的博客: 8 Tactics to Combat Imbalanced Classes in Your Machine Learning Dataset 1.不平衡数据集带来的影响 一个不 ...

  2. Java泛型的重要目的:别让猫别站在狗队里

    <Java编程思想>第四版足足用了75页来讲泛型——厚厚的一沓内容,很容易让人头大——但其实根本不用这么多,只需要一句话:我是一个泛型队列,狗可以站进来,猫也可以站进来,但最好不要既站猫, ...

  3. LindDotNetCore~ISoftDelete软删除接口

    回到目录 概念 ISoftDelete即软删除,数据在进行delete后不会从数据库清除,而只是标记一个状态,在业务范围里都不能获取到这个数据,这在ORM框架里还是比较容易实现的,对传统的ado来说需 ...

  4. 一个用来爬小说的简单的Node.js爬虫

    小说就准备点天下霸唱和南派三叔的系列,本人喜欢看,而且数据也好爬.貌似因为树大招风的原因,这两作者的的书被盗版的很多,乱改的也多.然后作者就直接在网上开放免费阅读了,还提供了官网,猜想作者应该是允许爬 ...

  5. API接口通讯参数规范(2)

    针对[API接口通讯参数规范]这篇文章留下的几个问题进行探讨. 问题1 试想一下,如果一个http请求返回一个500给我们,那我们是不是都不用看详情都知道该次请求发生了什么?这正是一个标准的结果码意义 ...

  6. 分布式事务解决方案FESCAR

    项目地址:FESCAR 以下是官网的文档.简介2019年,Fescar 是 阿里巴巴 开源的 分布式事务中间件,以 高效 并且对业务 0 侵入 的方式,解决 微服务 场景下面临的分布式事务问题. 1. ...

  7. 从PRISM开始学WPF(六)MVVM(二)Command-更新至Prism7.1

    命令绑定(Command) [7.1updated]这一节除了基础app部分,并没有什么变化 什么是Command? 先看下微软官方的说明: Commanding is an input mechan ...

  8. sql学习笔记(三)—— 联表查询

    上篇写了一些sql查询的知识,这篇接着写一下有关联表查询的知识. 既然是联表查询,那肯定得多个表啊,所以,我们先创建一个教师表,表名为 teacher,并且向表中插入数据. 准备工作: 创建表语句: ...

  9. .net core中使用autofac进行IOC

    .net Core中自带DI是非常简单轻量化的,但是如果批量注册就得扩展,下面使用反射进行批量注册的 public void AddAssembly(IServiceCollection servic ...

  10. QT5.6.0 VS2013 Win764位系统QT环境搭建过程

    QT5.6.0 VS2013 Win764位系统QT环境搭建过程 没用过QT自己跟同事要了安装包,按照同事指导方法操作安装部署开发环境结果遇到好多问题,错误网上搜遍了所有帖子也没有找到合适的解决方案. ...