c - 对于 CTR 模式,我是否需要输出缓冲区为 AES block 大小的倍数?

标签 c encryption openssl aes padding

在我的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/

相关文章:

python - C 中的简单 Python 扩展

c - C语言中全局变量和局部变量都存储在内存中

encryption - 40bit - 256 加密到底是什么意思?

android - 优化密码(技术上)是什么意思? (Java中的AES案例)

encryption - 创建一个小的(<10 位)、不(非常)安全的 "hash"的想法

c - 没有填充的OpenSSL RSA加密无法正确加密

.net - 使用 Openssl.net 创建 PKCS12 文件

xcode - 编译时没有OpenSSL支持错误

c - C语言中的优先级队列

创建选择号码代码