我使用RSA算法加密和解密大小超过rsa密钥大小的文件。
在下面的代码中进行加密,我正在逐块读取文件内容并转换为密文。块大小为32个字节。
FileInputStream fin1 = new FileInputStream(genfile);
FileOutputStream fout = new FileOutputStream(seedcipher);
byte[] block = new byte[32];
int i;
while ((i = fin1.read(block)) != -1)
{
byte[] inputfile= cipher.doFinal(block);
fout.write(inputfile);
}
fin1.close();
在解密部分,在代码中完成相同的逐块解密,其中我已经提到块大小为128字节
FileInputStream fin1 = new FileInputStream(encryptedfile);
FileOutputStream fout = new FileOutputStream(seedcipher);
DataInputStream dos =new DataInputStream(fin1);
DataOutputStream dosnew =new DataOutputStream(fout);
byte[] block = new byte[128];
int i;
while ((i = fin1.read(block)) != -1)
{
byte[] inputfile= cipher.doFinal(block);
fout.write(inputfile);
}
输入文件大小为81.3 kB并且文件包含
0 1 2 3 4.....29000
解密文件后,输出包含一些不相关的额外值。为什么结果中有额外的数据?
用于逐块读取的IO代码不正确:
while ((i = fin1.read(block)) != -1) {
byte[] inputfile= cipher.doFinal(block);
fout.write(inputfile);
}
i
中)。你不应该忽视它。使用RSA加密大文件不是一个好主意。例如,您可以生成随机AES密钥,使用RSA对其进行加密并将其存储在输出文件中,然后使用AES加密文件本身,这样可以更快,并且对大输入没有任何问题。解密将读取加密的AES密钥,对其进行解密,然后使用AES解密文件的其余部分。
混合密码系统
示例:对于1024位密钥,您可以加密大约1024/8 = 128个字节 注意:精确值为128字节 - 填充为11个字节
您可以使用对称密钥来加密和解密要传输的数据(> 128字节)。 RSA只能加密一定程度的数据(例如128字节),这取决于RSA密钥长度。
这意味着如果要传输大于128字节的任何内容,则必须首先传输<128字节的对称密钥,以便您可以拥有以下内容:
- 生成对称密钥(<128字节)
- 使用RSA加密对称密钥
- 传输加密的对称密钥
- 用RSA解密对称密钥
- 使用对称密钥加密数据(> 128字节)
- 传输加密数据
- 使用对称密钥解密加密数据
或(同时传输加密的对称密钥和加密数据)
- 生成对称密钥(<128字节)
- 使用RSA加密对称密钥
- 使用对称密钥加密数据(> 128字节)
- 传输加密的对称密钥和加密数据
- 用RSA解密对称密钥
- 使用对称密钥解密加密数据
有关更多信息,请单击here (Hybrid cryptosystem)
你可以通过runlength编码来解决这个问题。使用DataOutputStream在开头写入一个整数,表示之后写入的字节数。解密时,读取该整数,并仅使用它所说的字节数。
我注意到你以错误的方式使用Cipher类。使用update
方法将字节添加到cipher
并仅使用doFinal
一次。使用this重载版本的更新方法很重要。将inputOffset
参数设置为零,将inputLen
参数设置为i
。这将确保Cipher
仅使用它应该使用的字节。
请参阅JB Nizets的回答。