我正在尝试通过套接字发送加密数据。
我构建了一个服务器和一个客户端,我可以使用典型的成功交换数据(这是一个客户端示例,在服务器上的工作方式相同):
int count = 0;
byte[] buffer = new buffer[4096];
while ((count = fileInputStream.read(buffer)) >= 0)
{
outToServer.write(buffer, 0, count);
outToServer.flush();
}
我还有一种方法可以使用byte[]
和密钥,并返回使用 AES 128位加密的byte[]
。另一种方法以相同的方式解密。
现在,我如何通过Socket
发送加密数据?
我遇到了很多问题,因为加密缓冲区的大小与普通缓冲区不同。例如,我从文件中加载4096
个字节,加密它们并以4112
结束。
这个数字不是转移的最佳选择。我无法解决它,因为显然服务器需要读取“整体”块 - 因为它们是加密的 - 或者它将无法解密。
即使我第一次加密整个文件,然后发送它,我仍然需要逐块加密它,当我读回来解密它时,这些块会崩溃。
显然,服务器无法知道加密块的填充大小(在接收任何内容之前),因此它一次总是读取4096个字节。
我该怎么办?
答案 0 :(得分:0)
如果您已经设定了以4096字节块发送数据的想法,那么您可以用稍小的块读取未加密的数据(如果您的填充按照我认为的方式工作,则可能是4095字节),然后通过线路发送填充的4096字节块。
未加密的明文和加密的密文的大小不一样,但加密任何两个等长的明文应该会产生等长的密文。如果您始终加密相同大小的明文,那么您通过套接字发送的加密密文的大小应该始终相同。因此,作为上述的替代方法,您可以继续以4096的块为单位读取文件,并告诉接收缓冲区预期4112字节。
你没有提到你正在使用哪种AES模式(我怀疑是CBC)或你正在使用哪种填充方案(我怀疑PKCS#7),所以我不是确切地知道填充在您的方案中是如何工作的,但是我猜测您的方案被填充到下一个16字节的倍数(如果它已经是16的倍数,则添加完整的16个字节) 。因此,您应该能够以4095字节或最差4080字节的块来读取文件,并将它们填充到4096字节。
我还建议您切换到GCM模式,其中(1)不需要填充,(2)除了加密之外还为您提供身份验证。
答案 1 :(得分:0)
我该怎么办?
您无需做任何事情。无论你发送什么,TCP都会对它进行分段,IP会以任何方式对其进行分组。在接收端,TCP是字节流,而不是消息传递系统。