Networking 如何使用流密码加密TCP数据?

Networking 如何使用流密码加密TCP数据?,networking,encryption,cryptography,stream-cipher,Networking,Encryption,Cryptography,Stream Cipher,我尝试在我的网络软件中使用chacha20加密,但遇到了一个问题 如果我加密服务器上的4字节数据:0x01 0x02 0x03 0x04 并获取密文:0xd2 0xd3 0xc4 0xd5,然后将其发送给客户端 客户端可以使用密钥和nonce接收ChaCha20生成流。让(S0、S1、S2、S3)流的第一个字节,并(M0、M1、M2、M3)消息的前4个字节 密文将被计算为(M0⊕S0,M1⊕S1,M2⊕S2,M3⊕S3)。这是如果您有现成的M0…M3 如果使用相同的密钥和nonce加密(M0,M

我尝试在我的网络软件中使用chacha20加密,但遇到了一个问题

如果我加密服务器上的4字节数据:
0x01 0x02 0x03 0x04

并获取密文:
0xd2 0xd3 0xc4 0xd5
,然后将其发送给客户端


客户端可以使用密钥和nonce接收ChaCha20生成流。让
(S0、S1、S2、S3)
流的第一个字节,并
(M0、M1、M2、M3)
消息的前4个字节

密文将被计算为
(M0⊕S0,M1⊕S1,M2⊕S2,M3⊕S3)
。这是如果您有现成的
M0…M3

如果使用相同的密钥和nonce加密
(M0,M1)
,然后
(M2,M3)
,您将得到
(M0)⊕S0,M1⊕S1)
(M2⊕S0,M3⊕S1)
。无法使用
(C0)对其进行解密⊕S0,C1⊕S1,C2⊕S2,C3⊕S3)

更糟糕的是,由于
S0
S1
已与不同的消息一起重复使用,攻击者可以在知道任何消息的情况下恢复它们


要避免这种情况,最简单的方法是缓冲数据直到达到块大小,然后加密整个块,而不是尝试加密部分块。

ChaCha20使用密钥和nonce生成流。让
(S0、S1、S2、S3)
流的第一个字节,并
(M0、M1、M2、M3)
消息的前4个字节

密文将被计算为
(M0⊕S0,M1⊕S1,M2⊕S2,M3⊕S3)
。这是如果您有现成的
M0…M3

如果使用相同的密钥和nonce加密
(M0,M1)
,然后
(M2,M3)
,您将得到
(M0)⊕S0,M1⊕S1)
(M2⊕S0,M3⊕S1)
。无法使用
(C0)对其进行解密⊕S0,C1⊕S1,C2⊕S2,C3⊕S3)

更糟糕的是,由于
S0
S1
已与不同的消息一起重复使用,攻击者可以在知道任何消息的情况下恢复它们


要避免这种情况,最简单的方法是缓冲数据直到达到块大小,然后加密整个块,而不是尝试加密部分块。

而不是重新启动ChaCha20密码实例(或者更一般地说,上下文),您应该让它保持活动状态

大多数加密API将允许您执行逐段加密/解密。这通常意味着为第一部分和第二部分调用
update
方法,当检测到明文/密文的结尾时,通常紧接着调用
final
方法。根据API的不同,您应该期望这些方法中的每个方法都有输出


只有当您的API不允许您正确处理流时,您才应该聚合密文并对完整密文执行解密。

而不是重新启动ChaCha20密码实例(或者更一般地说,上下文),您应该让它保持活动状态

大多数加密API将允许您执行逐段加密/解密。这通常意味着为第一部分和第二部分调用
update
方法,当检测到明文/密文的结尾时,通常紧接着调用
final
方法。根据API的不同,您应该期望这些方法中的每个方法都有输出


只有当您的API不允许您正确处理流时,您才应该聚合密文并对完整密文执行解密。

还请注意,在使用TCP时,几乎总是需要为消息添加长度前缀,因为您很难预测消息将发送多少数据包,您没有正确阅读问题,问题在于解密,而不是加密。除非为“chacha20加密”选择了异常模式,否则加密和解密是相同的操作。也许我没有正确理解这个问题。我读它为“为什么
Dk,n(m0 | m1)!=Dk,n(m0)| Dk,n(m1)
?是的,我也是这样读的。但是根据问题c0 | c1=Ek,n(m0 | m1)被计算出来。然后它被用Dk,n(c0)| Dk,n(c1)解密,这显然是不正确的。所以密文被拆分,而不是明文(消息)。还请注意,在使用TCP时,几乎总是需要为消息添加长度前缀,因为您很难预测消息将发送多少数据包,因为您没有正确阅读问题,问题在于解密,而不是加密。除非为“chacha20加密”选择了不寻常的模式,加密和解密是相同的操作。也许我没有正确理解这个问题。我读它为“为什么
Dk,n(m0 | m1)!=Dk,n(m0)| Dk,n(m1)
?是的,我也是这样读的。但是根据问题c0 | c1=Ek,n(m0 | m1)被计算出来。然后它被用Dk,n(c0)| Dk,n(c1)解密,这显然是不正确的。所以密文被拆分,而不是明文(消息)。