Java通过套接字发送加密文件

5
我一直在尝试编写一个小文件服务器。我已经将它运作到可以正常传输文件了,但是现在我尝试添加加密时出现了奇怪的问题。我正在尝试使用密码输入/输出流来发送文件并使用DES加密。文件似乎已经完全被服务器传输,但是客户端无法正确接收它。
无论我传输什么样的文件,客户端都无法离开我用于接收文件的循环。即便如此,我已经成功接收了 .pdf 和 .doc 文件,两者都没有任何错误,并且可以完美打开。当我发送一张图片时,末尾似乎无法正确地传输。这张图片打开了,但是末尾从未显示,只有一个灰色区域。
我想这些问题之间可能有关联,但我不知道该如何解决它们。
以下是我在服务器端用于发送文件的代码:
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
CipherOutputStream cipherOut = new CipherOutputStream(outToClient, cipher);
byte[] fileBuffer = new byte[BUFFER_SIZE];
InputStream fileReader = new BufferedInputStream(new FileInputStream(aFile));
int bytesRead;
while((bytesRead = fileReader.read(fileBuffer)) != EOF){
    cipherOut.write(fileBuffer, 0, bytesRead);
}
cipherOut.flush();

客户端接收它的代码:

Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, serverPublicKey);
CipherInputStream cipherIn = new CipherInputStream(inFromServer, cipher);

byte[] fileBuffer = new byte[BUFFER_SIZE];
FileOutputStream fileWriter = new FileOutputStream(newFileName);
int bytesRead;
while((bytesRead = cipherIn.read(fileBuffer)) != EOF){
    fileWriter.write(fileBuffer, 0, bytesRead);
}
fileWriter.flush();
fileWriter.close();

任何指向正确方向的指导都将非常有用。

4
顺带一提,DES是一种用于对称加密的算法,也就是说,在处理DES时没有公钥(或私钥)的概念。您变量中的publicKeyserverPublicKey名称具有误导性,因为它们实际上代表了一个共享秘密 - Bruno Reis
你没有在服务器端关闭输出流。EOF是-1还是0,应该是-1。 - ratchet freak
2个回答

2
  while((bytesRead = cipherIn.read(fileBuffer)) != EOF){

您只是不断地读取,直到'bytesRead'的数量给出EOF,但这不会发生,因为您没有关闭另一端的套接字(至少我在您的代码中没有看到)。

我明白了。

cipherOut.flush() ;

但这并不会关闭套接字。如果它只是“超出范围”,它将一直保持打开状态,直到垃圾收集器回收对象。


我看到你接受了这个答案,但关闭套接字并不是必要的,也不是最好的解决方案。 - jedwards
1
同意,但问题是“哪里出了问题?”而不是“怎么做得对?” - Andrew
@jdedwards 如果接收器读取到EOS,则必须关闭。可以通过长度字前缀或其他叠加协议来避免这两种情况。但考虑到现有的客户端代码,关闭是必要的。 - user207421

2

你没有在服务器端关闭CipherOutputStream

使用分块密码时,刷新操作可能导致一些字节直到填满块或执行关闭操作(此时填充将生效),才会被发送,这将使接收方找到EOF。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接