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

时间:2016-07-18 14:00:14

标签: c encryption openssl aes padding

在我的C代码中,我在CTR模式下使用OpenSSL的AES通过EVP接口进行加密,即我有这样的事情:

ret = EVP_EncryptInit_ex(ctx, EVP_aes_256_ctr(), NULL, key, iv))
...
ret = EVP_EncryptUpdate(ctx, out, &outlen, in, inlen);

输入数据的长度不是AES块大小的倍数,因此如果使用CBC模式,我将不得不在输出缓冲区中为填充分配额外的字节。

我是否需要在点击率模式下做同样的事情?而且我对CFB和OFB模式感到好奇。

EVP_EncryptUpdate上的OpenSSL man没有提到任何关于“类似流”模式的具体内容,他们只是警告需要填充的额外字节。

2 个答案:

答案 0 :(得分:2)

TLDR:执行副总裁不支持点击率(及其他流模式/密码)

实际上EVP_EncryptUpdate本身从不会填充,尽管它可以随身携带'从一个电话到下一个电话的部分阻止;因此,如果代码中的...不包含任何先前的EncryptUpdate,那么此(第一个)EncryptUpdate将始终是块对齐的,并且其输出将永远不会更长:

  

EVP_EncryptUpdate()从缓冲区加密inl字节,并将加密版本写入out。可以多次调用此函数来加密连续的数据块。写入的数据量取决于加密数据的块对齐:因此写入的数据量可以是从零字节到(inl + cipher_block_size - 1)的任何值,因此out应包含足够的空间。写入的实际字节数放在outl中。它还检查in和out是否部分重叠,如果它们为0则返回以指示失败。

EVP_EncryptFinal[_ex]添加了填充,因此添加了额外的'在需要时输出,如手册页的下一段所述:

  

如果启用了填充(默认值),则EVP_EncryptFinal_ex()会加密" final"数据,即保留在部分块中的任何数据。它使用标准块填充(也称为PKCS填充),如下面的NOTES部分所述。加密的最终数据被写入,其中应该有足够的空间用于一个密码块。写入的字节数放在outl中。调用此函数后,加密操作完成,不再调用EVP_EncryptUpdate()。

     

如果禁用填充,则EVP_EncryptFinal_ex()将不再加密任何数据,如果任何数据保留在部分块中,它将返回错误:即总数据长度不是块大小的倍数。

但是,由于密文实际上包含所有Update个呼叫的输出(或只有一个呼叫)加上 Final呼叫的输出,在填充的情况下,总缓冲区确实需要(最多)一个块大于输入

手册页没有说(并且应该)是填充不适用于流密码(如RC4)或流模式(包括CTR OFB * CFB *)。每个密码/模式组合由EVP_CIPHER类型的对象描述,该对象是struct evp_cipher_st的typedef;这是EVP_aes_256_ctr()和类似例程返回指针的内容。除此之外,这个结构包含一个字段block_size,它包含,你猜对了,块大小(以字节为单位)。对于流模式和密码,它包含一个特殊处理的虚拟值1:EncryptFinal_ex即使启用也不添加填充,DecryptFinal_ex即使启用也不会删除和检查填充。

答案 1 :(得分:1)

  

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

不,CTR模式没有这个要求。在这方面,CTR模式类似于OFB和CFB模式。相比之下,ECB和CBC模式需要块大小的倍数。

OpenSSL使用 Init / Update / Final 模式,输入和输出字节都被缓冲,直到需要为止。如果你愿意的话,你可以一次插入一个字节。

在内部,EVP对象将缓冲输入,直到足以执行加密。由于CTR模式可以流式传输,因此在处理一个输入字节后,一个输出字节将可用(它是带有纯文本的加密计数器的简单XOR)。 EVP对象也将缓冲输出字节,直到您调用Final。