C# 用Org.BouncyCastle.Crypto库进行RSA加密,报input data too large,但明明选了
https://blog.csdn.net/thc1987/article/details/81383365C#使用的库为:https://www.nuget.org/packages/Portable.BouncyCastle
按上面写法,可以看到engine的 算法是RSA/PKCS1Padding
这不就也用padding了
难道这样还不算进行了分段加密、解密,还会遇到要加密内容超大小的问题?? RSA1024,RSA2048,RSA4096 RSA加密原始数据是有长度限制的哇 如下代码,希望能帮上楼主
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
}
} 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: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型的变成这个?
/// <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; }
}
ilovecomputer66 发表于 2023-2-16 09:54
我就是C# 生成的RSA公钥、私钥,但是通过下面代码生成的string,没有存xml
rsaProvider.FromXmlString ...
你是不是没读题?
RSAPublicKeyDotNet2Java(string publicKey) coolcalf 发表于 2023-2-16 21:24
你是不是没读题?
RSAPublicKeyDotNet2Java(string publicKey)
天啊。我就是生成 BASE64编码的公钥、密钥,压根没用它这个,它这个生成的自然不通用
================================= 自己解决了==========================================
结贴,手工写循环分块加密
页:
[1]