java中使用Bouncy Castle的分块RSA加密
在C#中,我通过执行以下操作来加密文本数据(请注意,我是以块(blocks)的形式加密数据): 因此,有时解密(发生在基于.Net的服务器上)会出现错误“输入太大,无法使用RSA密码”。因此我怀疑这可能是因为加密和解密数据的逻辑不同(加密发生在基于java的客户端上,逻辑如上所述,解密发生在基于.Net的客户端上,逻辑如下):java中使用Bouncy Castle的分块RSA加密,java,c#,cryptography,rsa,bouncycastle,Java,C#,Cryptography,Rsa,Bouncycastle,在C#中,我通过执行以下操作来加密文本数据(请注意,我是以块(blocks)的形式加密数据): 因此,有时解密(发生在基于.Net的服务器上)会出现错误“输入太大,无法使用RSA密码”。因此我怀疑这可能是因为加密和解密数据的逻辑不同(加密发生在基于java的客户端上,逻辑如上所述,解密发生在基于.Net的客户端上,逻辑如下): 公共字符串解密数据(字符串私钥、字符串base64数据) { 尝试 { var bytesToDecrypt=Convert.FromBase64String(base6
公共字符串解密数据(字符串私钥、字符串base64数据)
{
尝试
{
var bytesToDecrypt=Convert.FromBase64String(base64Data);
非对称密码密钥对;
//var internalEngine=新的RsaEngine();
var decryptEngine=new RsaEngine();//无paddind。我们将查找数据包中的数据
使用(var txtreader=newstringreader(privateKey))
{
keyPair=(AsymmetricipherKeyPair)新的PemReader(txtreader).ReadObject();
decryptEngine.Init(false,keyPair.Private);
}
//循环por todo el bloque y saca数据
字节[]完成=新字节[0];
int blockSize=decryptEngine.GetInputBlockSize();
for(int-chunkPosition=0;chunkPositionblockSize)
{
chunkSize=块大小;
}
var decryptedChunk=decryptEngine.ProcessBlock(bytesToDecrypt、chunkPosition、chunkSize);
//实际解密的数据在中间,找到它!
int idxFirstZero=-1;
int-outlen=decryptedChunk.Length;
int idxNextZero=(int)outlen;
for(int i=0;i0?complete.Length-totalSizeToCopy:0;
BlockCopy(decryptedChunk、idxFirstZero+1、complete、DSTFostate、totalSizeToCopy);
}
var finalString=Encoding.UTF8.GetString(complete.Trim)('\0');
返回最后一环;
}
捕获(InvalidCipherTextException)
{
}
}
正如你所看到的,我正在对数据进行分块解密。所以我的问题是,我们如何用java(使用bouncy castle)进行分块加密(就像我在文章的第一个代码片段中在.Net中所做的那样)?对于大数据(甚至更小的数据),这不是一种常见的操作通常使用混合加密,其中对称密码的操作模式(如CBC)用于加密较大的数据对象 据我所知,没有直接的方法从
Cipher
实例请求RSA/PKCS#1的最大输入大小
但是,这不是什么大问题,因为您可以在给定RSA密钥大小的情况下自行计算。并且该密钥大小与模的大小相同(以字节为单位):
(keysize-1)/Byte.size+1
或者,如果keysize是8的倍数(通常),当然只需keysize/Byte.size
RSAPublicKey
,然后调用getmodule()
,然后对生成的BigInteger
调用bitLength()
请注意,在没有完整性保护(例如签名)的情况下发送密文并不十分安全。PKCS#1也可能成为填充oracle攻击的受害者,特别是在传输模式安全中使用时。RSA/OAEP将是更好的选择,用于混合加密(如RSA/OAEP).这应该是一个学习练习吗?如果不是,请扔掉您的代码并正确实现。RSA不应该用作分组密码。您应该使用AES加密您的邮件,并使用RSA加密随机AES密钥。“…我正在[使用RSA]分块(块)加密数据。”-如果对每个区块应用RSA,则称为ECB模式下的RSA操作。特别警告不要使用这种做法。
public string EncryptData(string publicKey, string data)
{
try
{
var bytesToEncrypt = Encoding.UTF8.GetBytes(data);
int srclen = bytesToEncrypt.Length;
//Prepare encryption engine
var encryptEngine = new Pkcs1Encoding(new RsaEngine());
//Initialize Key
using (var txtreader = new StringReader(publicKey))
{
var keyParameter = (AsymmetricKeyParameter)new PemReader(txtreader).ReadObject();
encryptEngine.Init(true, keyParameter);
}
//Encrypt in loop
byte[] complete = new byte[0];
int src_block_size = encryptEngine.GetInputBlockSize();
for (int idx = 0; idx < srclen; idx += src_block_size)
{
int data_len = srclen - idx;
if (data_len > src_block_size)
{
data_len = src_block_size;
}
var encryptedChunk = encryptEngine.ProcessBlock(bytesToEncrypt, idx, data_len);
complete = CombineByteArrays(complete, encryptedChunk);
}
var finalString = Convert.ToBase64String(complete);
return finalString;
}
catch (InvalidCipherTextException)
{
//catch exception
}
}
public static byte[] encrypt(byte[] text, PublicKey key) throws Exception
{
byte[] cipherText = null;
//
// get an RSA cipher object and print the provider
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(text);
return cipherText;
}
public string DecryptData(string privateKey, string base64Data)
{
try
{
var bytesToDecrypt = Convert.FromBase64String(base64Data);
AsymmetricCipherKeyPair keyPair;
//var internalEngine = new RsaEngine();
var decryptEngine = new RsaEngine(); //No paddind. We'll hunt the data inside packets
using (var txtreader = new StringReader(privateKey))
{
keyPair = (AsymmetricCipherKeyPair)new PemReader(txtreader).ReadObject();
decryptEngine.Init(false, keyPair.Private);
}
//Loop por todo el bloque y saca data
byte[] complete = new byte[0];
int blockSize = decryptEngine.GetInputBlockSize();
for (int chunkPosition = 0; chunkPosition < bytesToDecrypt.Length; chunkPosition += blockSize)
{
//int chunkSize = Math.Min(blockSize, bytesToDecrypt.Length - ((chunkPosition / blockSize) * blockSize));
int chunkSize = bytesToDecrypt.Length - chunkPosition;
if (chunkSize > blockSize)
{
chunkSize = blockSize;
}
var decryptedChunk = decryptEngine.ProcessBlock(bytesToDecrypt, chunkPosition, chunkSize);
//the actual decrypted data is in the middle, locate it!
int idxFirstZero = -1;
int outlen = decryptedChunk.Length;
int idxNextZero = (int)outlen;
for (int i = 0; i < outlen; i++)
{
if (decryptedChunk[i] == 0)
{
if (idxFirstZero < 0)
{
idxFirstZero = i;
}
else
{
idxNextZero = i;
break;
}
}
}
var totalSizeToCopy = idxNextZero - idxFirstZero - 1;
Array.Resize(ref complete, complete.Length + totalSizeToCopy);
int dstOffset = complete.Length - totalSizeToCopy > 0 ? complete.Length - totalSizeToCopy : 0;
Buffer.BlockCopy(decryptedChunk, idxFirstZero + 1, complete, dstOffset, totalSizeToCopy);
}
var finalString = Encoding.UTF8.GetString(complete).Trim('\0');
return finalString;
}
catch (InvalidCipherTextException)
{
}
}