我在 CTR 模式下使用 AES128 加密进行加密,针对不同的客户端(Android/Java 和 iOS/ObjC)实现。加密数据包时使用的 16 字节 IV 格式如下:
<11 byte nonce> | <4 byte packet counter> | 0
每发送一个数据包,数据包计数器(包含在发送的数据包中)就会增加一。最后一个字节用作块计数器,因此少于 256 个块的数据包总是获得唯一的计数器值。我假设 CTR 模式指定计数器应该为每个块增加 1,以大端方式使用最后 8 个字节作为计数器,或者这至少是事实上的标准。Sun 加密实现中似乎也是这种情况。
当相应的 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> */
通过逐块解码,每次按照上面指定的方式设置 IV,它都能很好地工作。
我的问题:在一次解码多个块时,是否有一种“正确”的方式来实现 CTR/IV 模式,或者在使用不同的加密库时我是否可以期望它是互操作性问题?CommonCrypto 在这方面是否存在问题,还是只是以不同方式实现 CTR 模式的问题?