文档章节

.Net Core下使用 RSA的几个注意事项

SM-ART
 SM-ART
发布于 2017/05/03 19:49
字数 925
阅读 102
收藏 0

.Net Core 下,以前的RSA加密解密的API有较大的改变,这里记录下 使用过程中的一些区别.

要进行.Net Core下的RSA相关操作, 要用到以下几个包:

<ItemGroup>
    <PackageReference Include="System.Security.Cryptography.Csp" Version="4.3.0" />
    <PackageReference Include="System.Security.Cryptography.Algorithms" Version="4.3.0" />
</ItemGroup>
  • RSACryptoServiceProvider 在Windows 环境下依然可以使用RSACryptoServiceProvider, 但在Linux 环境下编译不过. 参考 dudu 的文章 .net core中使用openssl的公钥私钥进行加解密

  • FromXmlString方法和ToXmlString 由于不在使用RSACryptoServiceProvider这两个方法不在提供,我们可以通过扩展方法来添加这两个方法,以处理C#生成的密钥.

相关代码

using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Xml;

namespace demo
{
    public class RsaDemo
    {
        #region Fields
        private const string PubKeyXML="<RSAKeyValue><Modulus>yuW8mDcb1+n/fIKqNaT3LQ3qsKNBg4GC7ZD2KXEJqMOyk5x8JOgwgg3mwnie1LfqryzYHSIJLjxR35WznjrCBT+p07IkitGCPY6JuNI/w1KmaoPueb8V/j8YvPQEs6UIXgj/PJdsw1xPgzIxZj9fyxnXOTqbIee4bTOkT28610yKjiq/90dGvWFRmFWPhjTlet02Dt4Qe0nrK/DMCw2dIIcBqrAJyQCMa8dKObbx0Q7+32X71MB3IyzCWZWou8xMBNAxbIYF3Yu6zjLmcBjWpLAAud3tHp72XJ27sNSfZNR1x4Liqo9NnjOivuRnxIxwCpexBh42Qsfx7JSm3aKeZQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
        private const string PrivKeyXml="<RSAKeyValue><Modulus>yuW8mDcb1+n/fIKqNaT3LQ3qsKNBg4GC7ZD2KXEJqMOyk5x8JOgwgg3mwnie1LfqryzYHSIJLjxR35WznjrCBT+p07IkitGCPY6JuNI/w1KmaoPueb8V/j8YvPQEs6UIXgj/PJdsw1xPgzIxZj9fyxnXOTqbIee4bTOkT28610yKjiq/90dGvWFRmFWPhjTlet02Dt4Qe0nrK/DMCw2dIIcBqrAJyQCMa8dKObbx0Q7+32X71MB3IyzCWZWou8xMBNAxbIYF3Yu6zjLmcBjWpLAAud3tHp72XJ27sNSfZNR1x4Liqo9NnjOivuRnxIxwCpexBh42Qsfx7JSm3aKeZQ==</Modulus><Exponent>AQAB</Exponent><P>5LPiWxYbwHe/i/IRKJ84B5PrSPdtPqn1Uj/FUu+4ZMpNw3UEyt0u73MLgXLjwCrx7A484cLS4el5z0eOBAnjw2d1Hm6E/jh8sH5zQHv7u1rFefUMYRMYXSqirTVlj226ccFRE9OZ3lKPuXrodappqNstjlprV1AMDxfLHA1aUXs=</P><Q>4x1cWbomvGv8JKlginM9GN0sTcM2BeO961dE2K/zBN5CnmW3um7PvDHyb+ntYYoOaW1lx8V/TB3X5w6ywsMiZhe5uXmqiSWaj8vGAyJ+NM+K2AgHDcEqLFUiyTJ/XkqV2k7iMcSLuRO738OECeC/bEu3HGoGGryJWuEC+fEvGZ8=</Q><DP>B0Bk5vp2es3RNwC/5ofV4PehuDiQMDJ3Yto+yXhsYlW/zXjCZCRLPrBpJvubmRZDgXaaG5Zv1VXv1NCyAhLGNAXtwr9CXEUyPu5jfSHxQ2mHZWyNre5LEXkum0tcIwYZqU214mkNMe1wPTNWd5SlsQLyGNdpG+Wf3EKm4AbUXE0=</DP><DQ>Ea8klLwA7iT+YiBqKv2kIT5/h6KOn1DHZf7KlpDEvHlN+KV08+hS9pVxCjPNzw1/58ej6DVBnzynpg8n7jBhik+In5+QntM1wMKeLXpPF2+doQqm+fQzg3Yxmjb7Ye0u0+vWgweJ1aRquZawvlAot5cBsA21YfmSPGhO4gVcpIM=</DQ><InverseQ>bSssYm1rAcXrZ3G9gDki8Qj0HUUXRrjNJCK2QTHhU5cGY5yiyQE+JVkHOkteKDEaGhaMbGj9cn4D6x22FVV6F9zx+L1RFfrtJpdD9/iYKll6nD3HzpSQ+3AoSE8R8e6bQEWlioW8dICm4A1Acaj7kJyJw1JpJKfjnRrsr05dnQI=</InverseQ><D>KB+GTBOZzfjYLScpwbH9r0sxPf0K15ak7ZXdGBTidB0/EzG+2w2Piih1mb+AqVA1eK7Fjf1NE3eaOTzBaGj2NVOBoft4fnsv5jxpv8LUGSwe/LFaV3kSQFT572PSCjR4kx/0WWcYewmmL6udWTrvFprllMuiIfJQ5kdwFsVIPYrrN7D2A6FOyVuXmmr1DW6+6E/MUjvOWA2UBf4VeybQRsjekaD2ckIM0UK/7+8CWIoNtUzK2ZJ1oqyOk5oVk8Ja0VI3AZSZL1s5Xx/estVZfpmtVGg20T21yXZ7PREpcZQxK67ywNFm12dreZw8sByVvLGKazJfGtijSfHadEPngQ==</D></RSAKeyValue>";
        #endregion

        #region Methods
        public byte[] Encrypt(byte[] input)
        {
            Func<byte[], byte[]> encrypt = sou =>
            {
                using (var rsa = RSA.Create())
                {
                    rsa.FromXmlString(PubKeyXML);
                    int maxBlockSize = rsa.KeySize / 8 - 11;
                    if (sou.Length <= maxBlockSize)
                    {
                        return rsa.Encrypt(sou, RSAEncryptionPadding.Pkcs1);
                    }
                    using (MemoryStream plaiStream = new MemoryStream(sou))
                    {
                        using (MemoryStream crypStream = new MemoryStream())
                        {
                            byte[] buffer = new byte[maxBlockSize];
                            int blockSize = plaiStream.Read(buffer, 0, maxBlockSize);

                            while (blockSize > 0)
                            {
                                byte[] toEncrypt = new byte[blockSize];
                                Array.Copy(buffer, 0, toEncrypt, 0, blockSize);

                                byte[] cryptograph = rsa.Encrypt(toEncrypt, RSAEncryptionPadding.Pkcs1);
                                crypStream.Write(cryptograph, 0, cryptograph.Length);

                                blockSize = plaiStream.Read(buffer, 0, maxBlockSize);
                            }

                            return crypStream.ToArray();
                        }
                    }
                }
            };
            return MarkData(encrypt(input));
        }

        public byte[] Decrypt(byte[] input)
        {
            if (IsEncrypt(input))
            {
                Func<byte[], byte[]> decrypt = sou =>
                {
                    using (var rsa = RSA.Create())
                    {
                        rsa.FromXmlString(PrivKeyXml);

                        int maxBlockSize = rsa.KeySize / 8;

                        if (sou.Length <= maxBlockSize)
                            return rsa.Decrypt(sou, RSAEncryptionPadding.Pkcs1);

                        using (MemoryStream crypStream = new MemoryStream(sou))
                        {
                            using (MemoryStream plaiStream = new MemoryStream())
                            {
                                byte[] buffer = new byte[maxBlockSize];
                                int blockSize = crypStream.Read(buffer, 0, maxBlockSize);

                                while (blockSize > 0)
                                {
                                    byte[] toDecrypt = new byte[blockSize];
                                    Array.Copy(buffer, 0, toDecrypt, 0, blockSize);

                                    byte[] plaintext = rsa.Decrypt(toDecrypt, RSAEncryptionPadding.Pkcs1);
                                    plaiStream.Write(plaintext, 0, plaintext.Length);

                                    blockSize = crypStream.Read(buffer, 0, maxBlockSize);
                                }

                                return plaiStream.ToArray();
                            }
                        }
                    }
                };
                return decrypt(ClearDataMark(input));
            }
            return input;
        }
        #endregion

        #region Utilities
        private byte[] MarkData(byte[] input)
        {
            byte[] newBytes = new byte[input.Length + 200];
            for (int i = 0; i < newBytes.Length; i++)
            {
                if (i < 100 || i > newBytes.Length - 100 - 1)
                {
                    newBytes[i] = 0;
                }
                else
                {
                    newBytes[i] = input[i - 100];
                }
            }
            return newBytes;
        }

        private byte[] ClearDataMark(byte[] input)
        {
            byte[] newBytes = new byte[input.Length - 200];
            for (int i = 100; i < input.Length - 100; i++)
            {
                newBytes[i - 100] = input[i];
            }
            return newBytes;
        }
        private bool IsEncrypt(byte[] input)
        {
            for (int i = 0; i < 100; i++)
            {
                if (input[i] != 0 || input[input.Length - i - 1] != 0)
                {
                    return false;
                }
            }
            return true;
        }

        #endregion

    }
}

RSA扩展方法

using System;
using System.IO;
using System.Security.Cryptography;
using System.Xml;

namespace demo
{
    public static class RsaExtention
    {

        public static void FromXmlString(this RSA rsa, string xmlString)
        {
            RSAParameters parameters = new RSAParameters();
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(xmlString);
            if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue"))
            {
                foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
                {
                    switch (node.Name)
                    {
                        case "Modulus": parameters.Modulus = Convert.FromBase64String(node.InnerText); break;
                        case "Exponent": parameters.Exponent = Convert.FromBase64String(node.InnerText); break;
                        case "P": parameters.P = Convert.FromBase64String(node.InnerText); break;
                        case "Q": parameters.Q = Convert.FromBase64String(node.InnerText); break;
                        case "DP": parameters.DP = Convert.FromBase64String(node.InnerText); break;
                        case "DQ": parameters.DQ = Convert.FromBase64String(node.InnerText); break;
                        case "InverseQ": parameters.InverseQ = Convert.FromBase64String(node.InnerText); break;
                        case "D": parameters.D = Convert.FromBase64String(node.InnerText); break;
                    }
                }
            }
            else
            {
                throw new Exception("Invalid XML RSA key.");
            }

            rsa.ImportParameters(parameters);
        }

        public static string ToXmlString(this RSA rsa, bool includePrivateParameters)
        {
            RSAParameters parameters = rsa.ExportParameters(includePrivateParameters);

            if (includePrivateParameters)
            {
                return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",
                    Convert.ToBase64String(parameters.Modulus),
                    Convert.ToBase64String(parameters.Exponent),
                    Convert.ToBase64String(parameters.P),
                    Convert.ToBase64String(parameters.Q),
                    Convert.ToBase64String(parameters.DP),
                    Convert.ToBase64String(parameters.DQ),
                    Convert.ToBase64String(parameters.InverseQ),
                    Convert.ToBase64String(parameters.D));
            }
            return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
                    Convert.ToBase64String(parameters.Modulus),
                    Convert.ToBase64String(parameters.Exponent));
        }

    }
}
  • RNGCryptoServiceProvider 如果以前代码使用RNGCryptoServiceProvider 来生成随机盐值,.Net Core中不在提供该方法,可以使用 RandomNumberGenerator方法替代.
// old
public virtual string CreateSaltKey(int size)
{
    //generate a cryptographic random number
    using (var provider = new RNGCryptoServiceProvider())
    {
        var buff = new byte[size];
        provider.GetBytes(buff);

        // Return a Base64 string representation of the random number
        return Convert.ToBase64String(buff);
    }
}
//new
public virtual string CreateSaltKey(int size)
{
    //generate a cryptographic random number
    using (var random = RandomNumberGenerator.Create())
    {
        var buff = new byte[size];
        random.GetBytes(buff);

        // Return a Base64 string representation of the random number
        return Convert.ToBase64String(buff);
    }
}

相关链接

© 著作权归作者所有

共有 人打赏支持
SM-ART
粉丝 0
博文 1
码字总数 925
作品 0
丰台
程序员
私信 提问
openssl 非对称加密DSA,RSA区别与使用介绍

openssl RSA 加解密 RSA是基于数论中大素数的乘积难分解理论上的非对称加密法,使用公私钥的方法进行加解密 公钥 用于加密,它是向所有人公开的 ; 私钥用于解密,只有密文的接收者持有 生成一...

伽罗kapple
2016/02/22
139
0
SSH无密码登录方法及对应的机制

缺省方式 如果我们希望从localhost主机通过SSH登录remotehost主机,执行如下命令: ssh username@centos-i1 这是 处理认证的缺省方式,它会要求我们输入username的密码,如果我们输入密码, ...

leesbing
2017/05/11
0
0
Ubuntu & GitLab CI & Docker & ASP.NET Core 2.0 自动化发布和部署(1)

相关博文: Ubuntu 简单安装和配置 GitLab Ubuntu 简单安装 Docker Ubuntu Docker 简单安装 GitLab Ubuntu Docker 安装和配置 GitLab CI 持续集成 服务器版本 Ubuntu 16.04 LTS。 经过上面四...

那谁爸爸
2018/01/08
0
0
cacti的安装与注意事项

cacti的介绍: Cacti是一套基于PHP,MySQL,SNMP及RRDTool开发的网络流量监测图形分析工具。 简单的说Cacti 就是一个PHP 程序。它通过使用SNMP 协议获取远端网络设备和相关信息,(其实就是使用...

abiu
2016/03/28
0
0
聊下 git 多账户问题

背景 在使用 git 的时候我们都会面临多账户问题,比较常见的就是公司内部的 gitlab,开源平台 github ,我们都需要在一台电脑上同时使用,这需要解决两个问题。 git 多账号配置 git config –...

王清培
2017/11/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Python中判断字符串是否包含中文

Python import reRE = re.compile(u'[\u4e00-\u9fa5]', re.UNICODE)match = re.search(RE, str)if match is None:# 没有包含中文字符 参考 Python regular expressions return true/f......

亚林瓜子
22分钟前
0
0
《CNCF × Alibaba 云原生技术公开课》正式首播

《CNCF × Alibaba 云原生技术公开课》立即观看:点击立即观看 云原生最初来描述云上应用的典型架构与特性,随着容器、Kubernetes、Serverless、FaaS技术的演进,CNCF(云原生计算基金会)把...

mcy0425
23分钟前
2
0
网站漏洞如何修复网站程序问题

jeecms 最近被爆出高危网站漏洞,可以导致网站被上传webshell木马文件,受影响的版本是jeecms V6.0版本到jeecmsV7.0版本。该网站系统采用的是JAVA语言开发,数据库使用的是oracle,mysql,sql数...

网站安全
26分钟前
2
0
git 中“warning: CRLF will be replaced by LF in”解决方案

https://stackoverflow.com/questions/5834014/lf-will-be-replaced-by-crlf-in-git-what-is-that-and-is-it-important...

qwfys
30分钟前
1
0
Spring Boot配置ssl证书启用HTTPS协议

一 、点睛 SSL是为网络通信提供安全及数据完整性的一种安全协议,SSL在网络传输层对网络连接进行加密。SSL协议位于TCP/IP协议和各种应用层协议之间,为数据通信提供安全支持。 SSL协议分为两...

故久呵呵
32分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部