我应该使用AES加密的TCP流实现数据包分隔符吗?
问题描述:
最近我试图用Python Twisted设计物联网设备的自定义协议。由于大多数物联网设备(终端节点)的功能不足以支持TLS,因此我必须实施经过修改的轻量级传输安全性。但是,与standrad TLS相同,AES128/256用于数据加密。我应该使用AES加密的TCP流实现数据包分隔符吗?
众所周知,TCP是一个流,并且传递的消息可能需要在TCP流中分隔符。在面向文本的消息如HTTP/FTP中,使用\ n \ r。在二进制消息中,我们应该定义自己的结构,如TLV,V代表有效载荷数据。这可以通过Java中的Netty,Python中的Twisted实现。
当TCP被加密时,情况变得复杂。理论上,纯文本应该用AES加密,然后在TCP流上进行。文本消息很容易,但是在二进制消息中,类型/长度字段也被加密。此外,AES是面向块的算法,这意味着消息可能需要下一条消息来进行加密/解密。尽管AES可以是透明传输,但是对于二进制消息分片和解析来说很难实现。还有另一种方法,我们可以将TLV中的TL字段保留为纯文本,同时保持AES加密的V加密。但它只适用于二进制数据。并且它也需要AES中的填充。
是否有任何建议或参考,包括代码或项目?谢谢!
答
AES是一种分组密码,因此以区块大小的块读取数据。在发送端,您的AES加密代码应该根据需要添加填充,它应该是AES实现的一部分。 (我会建议你在这个应用程序中使用AES-CBC)。在发射器上,只需以块大小的块读取数据。
在java中,我会从我的套接字使用DataInputStream,并执行readFully()。
Socket socket;
DataInputStream ins = new DataInputStream(socket.getInputStream());
while(connectionOpen) {
byte[] aes = new Byte[blockSize];
ins.readFully(aes);
//Decrypt received data aes
...
}
由于您使用上面的readFully(),因此您确保始终接收正确大小(即块大小)的数据。
以块大小的倍数读取数据并仅填充最后一个块。 – zaph
现在,我明白了。与AES,事情变得更加简单。接收器只是读取块大小的块(如16B/32B)。而填充方法甚至可以帮助接收者分割数据包流! –