我正在制作一个使用AES加密的数据包(即,不是流)的协议。我决定使用GCM(基于CTR),因为它提供了集成的身份验证,并且是NSA套件b的一部分。AES密钥使用ECDH进行协商,其中公钥由可信联系人签名,作为使用ECDSA之类的信任网络的一部分。我认为我需要一个128位的nonce/初始化向量用于GCM,因为即使我使用256位密钥用于AES,它始终是128位分组密码(对吧?)我将在阅读BC代码后使用96位IV。
我绝对没有实现我自己的算法(只是协议-我的加密提供商是BouncyCastle),但我仍然需要知道如何使用这个nonce而不会搬起石头砸自己的脚。具有相同DH密钥的两个人之间使用的AES密钥将保持不变,因此我知道相同的nonce不应该用于多个数据包。
我可以简单地在数据包前添加一个96位的伪随机数,并让接收者使用它作为nonce吗?这是一种点对点软件,任何一方都可以在任何时间发送数据包(例如,即时消息、文件传输请求等),速度是一个大问题,所以最好不要使用安全的随机数源。nonce根本不需要保密,对吧?还是一定要像"加密安全"的PNRG那样随机?维基百科说它应该是随机的,否则它很容易受到选定的明文攻击——但在这两种说法旁边都有一个"需要引用",我不确定这对分组密码是否适用。我是否可以实际使用一个计数器来计算给定AES密钥发送的数据包数量(与128位块数量的计数器分开),从1开始?显然,这将使未来变得可预测。考虑到GCM既要进行身份验证也要进行加密,这会损害其身份验证功能吗?
GCM是一种带认证的分组密码计数器模式。Counter模式有效地将分组密码转换为流密码,因此流密码的许多规则仍然适用。重要的是要注意,相同的Key+IV将始终产生相同的PRNG流,并且重用该PRNG流可能导致攻击者通过简单的异或获得明文。在协议中,只要模式的计数器没有封装(int overflow),就可以在会话的整个生命周期中使用相同的Key+IV。例如,一个协议可以有两方,他们有一个预共享的密钥,然后他们可以协商一个新的加密Nonce,作为每个会话的IV(记住Nonce意味着只使用一次)。
如果您想使用AES作为分组密码,您应该查看CMAC模式或OMAC1变体。对于CMAC模式,仍然适用CBC的所有规则。在这种情况下,您必须确保每个数据包使用的唯一IV也是随机的。然而,重要的是要注意,重用静脉输液并不像重用PRNG流那样有可怕的后果。
我建议不要制定自己的安全协议。您需要考虑几件事情,即使是合格的密码学家也可能出错。我建议你参考TLS协议(RFC5246)和数据报TLS协议(RFC 4347)。选择一个库并使用它们。
关于你关于IV在GCM模式的问题。我会告诉你DTLS和TLS是怎么做的。它们使用显式的nonce,即每个数据包中包含的消息序列号(64位),其中包含不传输的秘密部分(上部32位),并派生自初始密钥交换(查看RFC 5288获取更多信息)。