• .Net Core下使用 RSA


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

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

    <ItemGroup>
    <PackageReferenceInclude="System.Security.Cryptography.Csp"Version="4.3.0"/>
    <PackageReferenceInclude="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 libs
    {
        public class RsaHelper
        {
            #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
    publicvirtualstringCreateSaltKey(int size)
    {
        //generate a cryptographic random number
        using(var provider =newRNGCryptoServiceProvider())
        {
            var buff =newbyte[size];
            provider.GetBytes(buff);
            // Return a Base64 string representation of the random number
            returnConvert.ToBase64String(buff);
        }
    }
    //new
    publicvirtualstringCreateSaltKey(int size)
    {
        //generate a cryptographic random number
        using(var random =RandomNumberGenerator.Create())
        {
            var buff =newbyte[size];
            random.GetBytes(buff);
            // Return a Base64 string representation of the random number
            returnConvert.ToBase64String(buff);
        }
    }            

     

    相关链接

  • 相关阅读:
    Linux centos7 安装 phpMyAdmin
    centos7安装显示中文
    js限制按钮每隔一段时间才能再次点击
    PHPMailer 发送邮件
    jquery click事件中的return false
    安装composer
    生成目录树查看目录结构
    VMware桥接模式下虚拟机ping主机不通
    编译U-Boot时command not found的解决方法
    强制删除文件(夹)的方法
  • 原文地址:https://www.cnblogs.com/yoze/p/6796843.html
Copyright © 2020-2023  润新知