Cryptography AES CTR模式的互操作性?

Cryptography AES CTR模式的互操作性?,cryptography,aes,commoncrypto,ctr-mode,Cryptography,Aes,Commoncrypto,Ctr Mode,我在CTR模式下使用AES128加密,为不同的客户端(Android/Java和iOS/ObjC)实现。加密数据包时使用的16字节IV格式如下: <11 byte nonce> | <4 byte packet counter> | 0 || 0 对于每个发送的分组,分组计数器(包括在发送的分组中)增加一个。最后一个字节用作块计数器,因此小于256个块的数据包始终获得唯一的计数器值。我假设CTR模式指定每个块的计数器应增加1,以大端方式使用最后8个字节作为计数器,或者

我在CTR模式下使用AES128加密,为不同的客户端(Android/Java和iOS/ObjC)实现。加密数据包时使用的16字节IV格式如下:

<11 byte nonce> | <4 byte packet counter> | 0
|| 0
对于每个发送的分组,分组计数器(包括在发送的分组中)增加一个。最后一个字节用作块计数器,因此小于256个块的数据包始终获得唯一的计数器值。我假设CTR模式指定每个块的计数器应增加1,以大端方式使用最后8个字节作为计数器,或者这至少是事实上的标准。Sun crypto实现中似乎也是如此

当相应的iOS实现(使用CommonCryptor,iOS 5.1)在解码数据包时未能解码除第一个块之外的每个块时,我有点惊讶。似乎CommonCryptor以其他方式定义了计数器。CommonCryptor可以在big-endian和little-endian模式下创建,但CommonCryptor代码中的一些模糊注释表明,这并没有(或至少还没有)得到充分支持:

http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-60026/Source/API/CommonCryptor.c

/* corecrypto only implements CTR_BE.  No use of CTR_LE was found so we're marking
   this as unimplemented for now.  Also in Lion this was defined in reverse order.
   See <rdar://problem/10306112> */
http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-60026/Source/API/CommonCryptor.c
/*corecrypto仅实现CTR_BE。没有发现CTR_LE的用途,因此我们正在标记
这是目前尚未实施的。同样,在Lion中,这是以相反的顺序定义的。
看*/
通过逐块解码,每次按上述规定设置IV,它都能很好地工作


我的问题是:当在一次go中解码多个块时,是否有一种实现CTR/IV模式的“正确”方法,或者当使用不同的crypto LIB时,是否会出现互操作性问题?CommonCrypto在这方面是否存在缺陷,或者只是以不同方式实现CTR模式的问题?

中(松散地)指定了计数器的定义。请注意,NIST仅规定如何在安全方面使用CTR模式;它没有为计数器定义一个标准算法

为了直接回答您的问题,无论您做什么,您都应该期望计数器每次递增一。根据NIST规范,计数器应表示128位大端整数。可能只有最低有效位(最右边的)才递增,但除非传递2^32-1或2^64-1值,否则通常不会产生差异

为了兼容性,您可以决定将第一个(最左边的)12字节用作randomnonce,并将后一个字节保留为零,然后让CTR的实现执行增量。在这种情况下,您只需在开始时随机使用96位/12字节,在这种情况下,不需要数据包计数器

但是,在计数器用完所有可用位之前,您只能使用2^32*16字节的明文。如果计数器返回零或计数器中包含nonce本身,则这是特定于实现的,因此您可能希望将自己的消息限制为68719476736=~68 GB(是的,这是基数10,Giga表示100000000)

  • 由于生日问题,您有2^48的机会(48=96/2)为当前时间创建冲突(每个消息需要,而不是每个块),因此您应该限制消息的数量
  • 如果某个攻击者欺骗您在同一时间解密2^32个数据包,则计数器将耗尽

如果仍然不兼容(测试!),则使用初始8字节作为nonce。不幸的是,这确实意味着由于生日问题,您需要限制邮件的数量。

进一步的调查揭示了常见的加密问题:

在iOS 6.0.1中,little endian选项现在尚未实现。此外,我还验证了CommonCrypto存在缺陷,因为CCCryptorReset方法实际上并没有改变IV,而是使用预先存在的IV。6.0.1中的行为不同于5.x


如果使用空IV初始化CommonCrypto,并在加密之前将其重置为实际IV,则这可能是一个安全risc。这将导致您的所有数据都使用相同的(空的)IV进行加密,并且多个流(可能应该具有不同的IV,但使用相同的密钥)将通过具有相应ctr的简单数据包异或泄漏数据。

计数器中包含的位数似乎变化很大。一些使用64位,另一些使用整个128位。但这对您的情况没有任何影响,因为LSB为0,并且您每IV的块数从未超过256个。@CodesInChaos确实如此,而且您加密超过2^64个块的可能性也不高,因此,前64位将不受影响。@owlstead 2^32数据包足以导致回滚到OP方案中的最高位。但这还是不太可能。在整个IV是随机的方案中,即使是第二个块也可能导致128位和64位计数器之间的差异。@CodesInChaos:我同意,但为了询问者的缘故,我希望包号是完全唯一的,并且它包含的字节数永远不会超过blocksize*256字节。在我看来,有人在CommonCrypto实现中被破坏了,或者库的使用方式与预期不同(过早地完成加密而不是更新)。@owlstead是的,它们是唯一的,不应该重复使用相同的IV,除非随机的nonce是偶然重复使用的。此外,密钥从不重复使用,因此每个新的nonce都会附带一个新的随机密钥。请注意,阅读规范后,您可以合理地确定NIST只使用Big-Endian模式,因此苹果最终只选择Big-Endian模式也就不足为奇了。在加密库中这样的评论确实让我不寒而栗,但这似乎表明实现者没有阅读规范,或者不理解规范。在这种情况下,他们不应该被允许创建加密库。谢谢你提供的信息。我会的