ilovecomputer66 发表于 2023-2-15 21:13

C# 用Org.BouncyCastle.Crypto库进行RSA加密,报input data too large,但明明选了

https://blog.csdn.net/thc1987/article/details/81383365

C#使用的库为:https://www.nuget.org/packages/Portable.BouncyCastle


按上面写法,可以看到engine的 算法是RSA/PKCS1Padding

这不就也用padding了

难道这样还不算进行了分段加密、解密,还会遇到要加密内容超大小的问题??

kenxy 发表于 2023-2-16 08:54

RSA1024,RSA2048,RSA4096

icysky0605 发表于 2023-2-16 09:01

RSA加密原始数据是有长度限制的哇

wfghim 发表于 2023-2-16 09:06

如下代码,希望能帮上楼主

using System.Security.Cryptography;
using System;
using System.Text;
using System.IO;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using System.Security.Cryptography;

namespace Test
{
    public static class RSAUtils
    {

      #region RSA加密
      /// <summary>
      /// RSA加密
      /// </summary>
      /// <param name="data"></param>
      /// <returns></returns>
      public static string RSAEncrypt(string data)
      {
            string key_Java = BaseDataHelp.pubilcKey;//银行的java的公钥key
            string Key_CSharp = RSAPublicKeyJava2DotNet(key_Java);//转换成c#的公钥key
            return RSAEncrypt(data, Key_CSharp);
      }


      /// <summary>
      /// RSA加密
      /// </summary>
      /// <param name="Jdata"></param>
      /// <param name="publicKey"></param>
      /// <returns></returns>
      public static string RSAEncrypt(string Jdata, string publicKey)
      {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            byte[] data = Encoding.UTF8.GetBytes(Jdata);         //要加密的数据
            rsa.FromXmlString(publicKey);//加载公钥
            int keySize = rsa.KeySize / 8;
            int bufferSize = keySize - 11;
            byte[] buffer = new byte;
            byte[] result;//返回结果
            MemoryStream msInput = new MemoryStream(data);
            using (MemoryStream msOuput = new MemoryStream())
            {
                int readLen = msInput.Read(buffer, 0, bufferSize);//分段加密
                while (readLen > 0)
                {
                  byte[] dataToEnc = new byte;
                  Array.Copy(buffer, 0, dataToEnc, 0, readLen);
                  byte[] encData = rsa.Encrypt(dataToEnc, false);
                  msOuput.Write(encData, 0, encData.Length);
                  readLen = msInput.Read(buffer, 0, bufferSize);
                }
                msInput.Close();
                result = msOuput.ToArray();    //得到加密结果
                msOuput.Close();
                rsa.Clear();
            }
            return Convert.ToBase64String(result);
      }
      #endregion

      #region RSA解密
      /// <summary>
      /// RSA解密
      /// </summary>
      /// <param name="data"></param>
      /// <returns></returns>
      public static string RSADecrypt(string data)
      {
            string key = BaseDataHelp.privateKey;
            return RSADecrypt(data, key);
      }

      /// <summary>
      /// RSA解密
      /// </summary>
      /// <param name="data"></param>
      /// <param name="privateKey"></param>
      /// <returns></returns>
      public static string RSADecrypt(string data, string privateKey)
      {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            byte[] dataEnc = Convert.FromBase64String(data);   //加载密文
            rsa.FromXmlString(privateKey);//加密
            int keySize = rsa.KeySize / 8;
            byte[] buffer = new byte;
            byte[] result;
            MemoryStream msInput = new MemoryStream(dataEnc);
            using (MemoryStream msOuput = new MemoryStream())
            {
                int readLen = msInput.Read(buffer, 0, keySize);
                while (readLen > 0)
                {
                  byte[] dataToDec = new byte;
                  Array.Copy(buffer, 0, dataToDec, 0, readLen);
                  byte[] decData = rsa.Decrypt(dataToDec, false);
                  msOuput.Write(decData, 0, decData.Length);
                  readLen = msInput.Read(buffer, 0, keySize);
                }
                msInput.Close();
                result = msOuput.ToArray();    //得到解密结果
                msOuput.Close();
                rsa.Clear();
            }
            return Encoding.UTF8.GetString(result);
      }
      #endregion

      #region 公钥转换
      /// <summary>      
      /// RSA公钥格式转换,java->.net      
      /// </summary>      
      /// <param name="publicKey">java生成的公钥</param>      
      /// <returns></returns>      
      public static string RSAPublicKeyJava2DotNet(string publicKey)
      {
            RsaKeyParameters publicKeyParam = (RsaKeyParameters) PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
            return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
                Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
                Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
      }

      /*
      // https://www.cnblogs.com/taiyonghai/p/6150353.html
       //https://blog.csdn.net/starfd/article/details/51838589
       非对称加密为数据的加密与解密提供了一个非常安全的方法,它使用了一对密钥,公钥(public key)和私钥(private key)。
私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。非对称加密使用这对密钥中的一个进行加密,而解密则需要另一个密钥。
比如,你向银行请求公钥,银行将公钥发给你,你使用公钥对消息加密,那么只有私钥的持有人--银行才能对你的消息解密。
与对称加密不同的是,银行不需要将私钥通过网络发送出去,因此安全性大大提高。
常用非对称加密:DSA、RSA等
目前C#中提供的RSA非对称加密(其他语言如JAVA是可以逆向加解密的,但没有测试过),只能使用公钥进行加密,只能使用私钥进行解密,不能逆向使用(私钥无法加密,公钥无法解密),
因为这样的安全性更高,不会出现私钥加密后的数据,所有公钥持有者都可以解密的问题,如果一定要有这种需求出现,则可以使用
第三方的加解密组件BouncyCastle来实现
       */
      #endregion
    }
}

coolcalf 发表于 2023-2-16 09:30

using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Xml;

namespace Aeasy.Common
{
    /**
   * RSA 加密解密
   * 需要引用包 BouncyCastle.Cryptography
   *
   * 使用示例:   
   * var s = RsaUtils.Decrypt(str, RsaUtils.RSAPrivateKeyJava2DotNet(key));
   */
    public static class RsaUtils
    {
      /// <summary>
      /// RSA私钥格式转换,java->.net
      /// </summary>
      /// <param name="privateKey">java生成的RSA私钥</param>
      /// <returns></returns>
      public static string RSAPrivateKeyJava2DotNet(string privateKey)
      {
            RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));
            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(privateKeyParam.Modulus.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));
      }

      /// <summary>
      /// RSA私钥格式转换,.net->java
      /// </summary>
      /// <param name="privateKey">.net生成的私钥</param>
      /// <returns></returns>
      public static string RSAPrivateKeyDotNet2Java(string privateKey)
      {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(privateKey);
            BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus").InnerText));
            BigInteger exp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent").InnerText));
            BigInteger d = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("D").InnerText));
            BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("P").InnerText));
            BigInteger q = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Q").InnerText));
            BigInteger dp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DP").InnerText));
            BigInteger dq = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DQ").InnerText));
            BigInteger qinv = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("InverseQ").InnerText));

            RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(m, exp, d, p, q, dp, dq, qinv);

            PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
            byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();
            return Convert.ToBase64String(serializedPrivateBytes);
      }

      /// <summary>
      /// RSA公钥格式转换,java->.net
      /// </summary>
      /// <param name="publicKey">java生成的公钥</param>
      /// <returns></returns>
      public static string RSAPublicKeyJava2DotNet(string publicKey)
      {
            RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
            return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
                Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
                Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
      }

      /// <summary>
      /// RSA公钥格式转换,.net->java
      /// </summary>
      /// <param name="publicKey">.net生成的公钥</param>
      /// <returns></returns>
      public static string RSAPublicKeyDotNet2Java(string publicKey)
      {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(publicKey);
            BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus").InnerText));
            BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent").InnerText));
            RsaKeyParameters pub = new RsaKeyParameters(false, m, p);

            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pub);
            byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
            return Convert.ToBase64String(serializedPublicBytes);
      }

      /// <summary>
      /// RSA 加密
      /// </summary>
      /// <param name="rawInput"></param>
      /// <param name="publicKey">公钥(Base64编码后的)</param>
      /// <returns></returns>
      /// <exception cref="ArgumentException"></exception>
      public static string RsaEncrypt(string rawInput, string publicKey)
      {
            if (string.IsNullOrEmpty(rawInput))
            {
                return string.Empty;
            }

            if (string.IsNullOrWhiteSpace(publicKey))
            {
                throw new ArgumentException("Invalid Public Key");
            }

            using (var rsaProvider = new RSACryptoServiceProvider())
            {
                var inputBytes = Encoding.UTF8.GetBytes(rawInput);//有含义的字符串转化为字节流
                rsaProvider.FromXmlString(publicKey);//载入公钥
                int bufferSize = (rsaProvider.KeySize / 8) - 11;//单块最大长度
                var buffer = new byte;
                using (MemoryStream inputStream = new MemoryStream(inputBytes),
                outputStream = new MemoryStream())
                {
                  while (true)
                  { //分段加密
                        int readSize = inputStream.Read(buffer, 0, bufferSize);
                        if (readSize <= 0)
                        {
                            break;
                        }

                        var temp = new byte;
                        Array.Copy(buffer, 0, temp, 0, readSize);
                        var encryptedBytes = rsaProvider.Encrypt(temp, false);
                        outputStream.Write(encryptedBytes, 0, encryptedBytes.Length);
                  }
                  return Convert.ToBase64String(outputStream.ToArray());//转化为字节流方便传输
                }
            }
      }

      /// <summary>
      /// RSA 解密
      /// </summary>
      /// <param name="encryptedInput">待解密的内容</param>
      /// <param name="privateKey">私钥(Base64编码后的)</param>
      /// <returns></returns>
      /// <exception cref="ArgumentException"></exception>
      public static string Decrypt(string encryptedInput, string privateKey)
      {
            if (string.IsNullOrEmpty(encryptedInput))
            {
                return string.Empty;
            }

            if (string.IsNullOrWhiteSpace(privateKey))
            {
                throw new ArgumentException("Invalid Private Key");
            }

            using (var rsaProvider = new RSACryptoServiceProvider())
            {
                var inputBytes = Convert.FromBase64String(encryptedInput);
                rsaProvider.FromXmlString(privateKey);
                int bufferSize = rsaProvider.KeySize / 8;
                var buffer = new byte;
                using (MemoryStream inputStream = new MemoryStream(inputBytes),
                outputStream = new MemoryStream())
                {
                  while (true)
                  {
                        int readSize = inputStream.Read(buffer, 0, bufferSize);
                        if (readSize <= 0)
                        {
                            break;
                        }

                        var temp = new byte;
                        Array.Copy(buffer, 0, temp, 0, readSize);
                        var rawBytes = rsaProvider.Decrypt(temp, false);
                        outputStream.Write(rawBytes, 0, rawBytes.Length);
                  }
                  return Encoding.UTF8.GetString(outputStream.ToArray());
                }
            }
      }
    }
}

楼上比我先一步,前几天才在这个事情上被坑了两个小时。 java和.net的私钥格式必须要转换一下。

ilovecomputer66 发表于 2023-2-16 09:54

本帖最后由 ilovecomputer66 于 2023-2-16 09:57 编辑

coolcalf 发表于 2023-2-16 09:30
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using ...
我就是C# 生成的RSA公钥、私钥,但是通过下面代码生成的string,没有存xml

rsaProvider.FromXmlString(publicKey);//载入公钥

那么这句话,怎么用string型的变成这个?

ilovecomputer66 发表于 2023-2-16 09:57



/// <summary>
      /// 生成一对RSA加解密用的公钥和私钥
      /// </summary>
      public static RSAKey GenerateRSAKey()
      {
            RsaKeyPairGenerator keyGenerator = new RsaKeyPairGenerator();

            RsaKeyGenerationParameters param = new RsaKeyGenerationParameters(
                Org.BouncyCastle.Math.BigInteger.ValueOf(3),
                new SecureRandom(),
                RSA_KEY_SIZE, // 密钥长度
                25);
            // 用参数初始化密钥构造器
            keyGenerator.Init(param);
            // 产生密钥对
            AsymmetricCipherKeyPair keyPair = keyGenerator.GenerateKeyPair();
            // 获取公钥和密钥
            AsymmetricKeyParameter publicKey = keyPair.Public;
            AsymmetricKeyParameter privateKey = keyPair.Private;

            SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
            PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey);

            Asn1Object asn1ObjectPublic = subjectPublicKeyInfo.ToAsn1Object();

            byte[] publicInfoByte = asn1ObjectPublic.GetEncoded(ENCODING.BodyName.ToUpper());
            Asn1Object asn1ObjectPrivate = privateKeyInfo.ToAsn1Object();
            byte[] privateInfoByte = asn1ObjectPrivate.GetEncoded(ENCODING.BodyName.ToUpper());

            RSAKey key = new RSAKey()
            {
                PublicKey = Convert.ToBase64String(publicInfoByte),
                PrivateKey = Convert.ToBase64String(privateInfoByte)
            };
            return key;
      }

public struct RSAKey
    {
      public string PublicKey { get; set; }
      public string PrivateKey { get; set; }
    }

coolcalf 发表于 2023-2-16 21:24

ilovecomputer66 发表于 2023-2-16 09:54
我就是C# 生成的RSA公钥、私钥,但是通过下面代码生成的string,没有存xml

rsaProvider.FromXmlString ...

你是不是没读题?
RSAPublicKeyDotNet2Java(string publicKey)

ilovecomputer66 发表于 2023-2-17 07:59

coolcalf 发表于 2023-2-16 21:24
你是不是没读题?
RSAPublicKeyDotNet2Java(string publicKey)

天啊。我就是生成 BASE64编码的公钥、密钥,压根没用它这个,它这个生成的自然不通用

ilovecomputer66 发表于 2023-2-17 08:00

================================= 自己解决了==========================================
结贴,手工写循环分块加密
页: [1]
查看完整版本: C# 用Org.BouncyCastle.Crypto库进行RSA加密,报input data too large,但明明选了