【发布时间】:2020-09-14 00:12:56
【问题描述】:
正如标题所说,我正在尝试使用 2 个线程加密文件并使用 1 个线程解密。
由于加密不是线程安全的,我使用FileChannel 来指定在第二个线程中读取的位置。
我正在使用一个 512 字节的缓冲区,因此我将文件大小除以 1024,从而获得在 while 中执行的迭代以到达文件前半部分的末尾。
第二个线程在第一个线程结束后立即开始并迭代直到文件结束。
解密函数一次只读取一个文件,将第二个附加到第一个文件的末尾。
我已经用图像进行了测试,但不幸的是,解密后只能看到图像的前半部分,其余部分是白色的。
在解密结束时我得到Error while decrypting: java.io.IOException: javax.crypto.BadPaddingException
EDIT1:我想我已经向前迈进了一步,现在我可以通过在 2 个不同的地方读取文件来实现多线程加密,但解密后我仍然得到Error while decrypting: java.io.IOException: javax.crypto.BadPaddingException
public void encrypt(File inputFile, File outputFile, String secret, int threadNum, long iteration)
{
try
{
setKey(secret);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
FileInputStream fis = new FileInputStream(inputFile);
FileOutputStream fos = new FileOutputStream(outputFile);
byte[] buffer = new byte[512];
long val = inputFile.length()/100, numIteration = 0;
int count;
if(threadNum == 1)
{
while(true)
{
if(numIteration == iteration)
{
fis.read(buffer);
fos.write(cipher.doFinal(buffer));
System.out.println("Dofinal 1°");
break;
}
else {
fis.read(buffer);
fos.write(cipher.update(buffer));
}
System.out.println("Num iteration: "+numIteration);
numIteration++;
}
}
else if(threadNum == 2)
{
while(numIteration <= iteration)
{
if(numIteration <= iteration/2)
{
fis.skip(512);
}
else if(numIteration >= iteration/2) {
fis.read(buffer);
fos.write(cipher.update(buffer));
System.out.println("Iteration"+numIteration);
}
else if(numIteration == iteration)
{
fis.read(buffer);
fos.write(cipher.doFinal(new byte[(int) inputFile.length()%512]));
break;
}
System.out.println("NumIteration: "+numIteration);
numIteration++;
}
}
}
catch (Exception e)
{
System.out.println("Error while encrypting: " + e.toString());
}
}
public void decrypt(File inputFile[], File outputFile, String secret)
{
System.out.println("Decryption");
try
{
setKey(secret);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
for(int i = 0; i < 2; i++)
{
CipherInputStream in = new CipherInputStream(new FileInputStream(inputFile[i]), cipher);
CountingInputStream cis = new CountingInputStream(in);
FileOutputStream out;
if(i == 0)
out = new FileOutputStream(outputFile);
else
out = new FileOutputStream(outputFile, true);
CountingOutputStream cos = new CountingOutputStream(out);
int count;
double val = (inputFile[i].length()/100);
byte[] buffer = new byte[512];
while((count = cis.read(buffer)) != -1)
{
cos.write(buffer, 0, count);
cos.flush();
}
cis.close();
cos.close();
}
}
catch (Exception e)
{
System.out.println("Error while decrypting: " + e.toString());
}
}
【问题讨论】:
-
FileChannel也不是线程安全的,并且由于磁盘本身不是多线程的,因此多线程加密没有任何好处。 -
为什么你认为“加密”不是线程安全的?密码对象不是线程安全的,因此您在每个线程中创建和使用密码对象。
-
@MarquisofLorne 我使用 nvme ssd 作为存储,所以应该可以实现多线程读取,但此时我不知道是什么原因导致解密期间出现此问题,如果未设置文件通道正常或其他的东西
-
我也会质疑这种工作方式,但让我们假装吧。由于使用了 ECB(密码处理块不需要先前的状态)和 PKCS5(相同的原因),这可能起作用。但只要 1) 你有线程不安全的计算/发布/重置
key和secretKey静态变量 2) 你有无序写入(块 N 在块 N-1 之前完成?),3 ) 你没有将你的读取限制在块大小上,4) 没有人控制对 Cipher 上doFinal()的调用(这将很难)。 Ultim:它有多安全?
标签: java aes filechannel