在我的C代码中,我在CTR模式下使用OpenSSL的AES通过EVP接口(interface)进行加密,也就是说我有这样的东西:
ret = EVP_EncryptInit_ex(ctx, EVP_aes_256_ctr(), NULL, key, iv))
...
ret = EVP_EncryptUpdate(ctx, out, &outlen, in, inlen);
输入数据的长度不是 AES block 大小的倍数,因此如果使用 CBC 模式,我将必须分配额外的字节用于输出缓冲区中的填充。
我需要在 CTR 模式下做同样的事情吗?而且我对 CFB 和 OFB 模式也很好奇。
EVP_EncryptUpdate 上的 OpenSSL 人员没有提及任何有关“类似流”模式的具体内容,他们只是警告需要额外的字节进行填充。
最佳答案
TLDR:EVP 不会填充 CTR(和其他流模式/密码)
实际上,EVP_EncryptUpdate
本身永远不会填充,尽管它可以将部分块从一个调用“携带”到下一个调用;因此,如果代码中的 ...
不包含任何先前的 EncryptUpdate
,则此(第一个)EncryptUpdate
将始终是 block 对齐的,并且其输出永远不会更长:
EVP_EncryptUpdate() encrypts inl bytes from the buffer in and writes the encrypted version to out. This function can be called multiple times to encrypt successive blocks of data. The amount of data written depends on the block alignment of the encrypted data: as a result the amount of data written may be anything from zero bytes to (inl + cipher_block_size - 1) so out should contain sufficient room. The actual number of bytes written is placed in outl. It also checks if in and out are partially overlapping, and if they are 0 is returned to indicate failure.
它是 EVP_EncryptFinal[_ex]
添加填充,从而在需要时添加“额外”输出,如手册页下一段所述:
If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts the "final" data, that is any data that remains in a partial block. It uses standard block padding (aka PKCS padding) as described in the NOTES section, below. The encrypted final data is written to out which should have sufficient space for one cipher block. The number of bytes written is placed in outl. After this function is called the encryption operation is finished and no further calls to EVP_EncryptUpdate() should be made.
If padding is disabled then EVP_EncryptFinal_ex() will not encrypt any more data and it will return an error if any data remains in a partial block: that is if the total data length is not a multiple of the block size.
但是,由于密文实际上由所有 Update
调用(或只有一个调用)的输出组成加上 Final
调用时,在应用填充的情况下,总缓冲区确实需要(最多)比输入大一个 block 。
手册页没有说(也应该说)的是,填充根本不适用于流密码(如 RC4)或流模式(包括 CTR OFB* CFB*)。每个密码/模式组合都由 EVP_CIPHER
类型的对象描述,该对象是 struct evp_cipher_st
的 typedef;这就是 EVP_aes_256_ctr()
和类似例程返回的指针。除此之外,该结构还包含一个字段 block_size
,您猜对了,它包含 block 大小(以字节为单位)。对于流模式和密码,它包含一个经过特殊处理的虚拟值 1:即使启用,EncryptFinal_ex
也不会添加填充,并且 DecryptFinal_ex
即使启用也不会删除和检查填充.
关于c - 对于 CTR 模式,我是否需要输出缓冲区为 AES block 大小的倍数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38445688/