吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1795|回复: 9
收起左侧

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

[复制链接]
ilovecomputer66 发表于 2023-2-15 21:13
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
wfghim 发表于 2023-2-16 09:06
如下代码,希望能帮上楼主

[Asm] 纯文本查看 复制代码
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[bufferSize];
            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[readLen];
                    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[keySize];
            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[readLen];
                    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
[C#] 纯文本查看 复制代码
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")[0].InnerText));
            BigInteger exp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
            BigInteger d = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("D")[0].InnerText));
            BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("P")[0].InnerText));
            BigInteger q = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Q")[0].InnerText));
            BigInteger dp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DP")[0].InnerText));
            BigInteger dq = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DQ")[0].InnerText));
            BigInteger qinv = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("InverseQ")[0].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")[0].InnerText));
            BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].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[bufferSize];
                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[readSize];
                        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[bufferSize];
                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[readSize];
                        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
[mw_shl_code=csharp,true]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

[C#] 纯文本查看 复制代码
/// <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
================================= 自己解决了==========================================
结贴,手工写循环分块加密
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 01:35

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表