AES_cbc_encrypt是否添加了填充?

时间:2015-07-05 02:01:48

标签: c++ openssl aes cbc-mode

考虑以下C ++代码片段:

#include <iostream>
#include <openssl/aes.h>

#define AES_KEY_LENGTH 32

using namespace std;

int main()
{
    AES_KEY encryption_key;
    AES_KEY decryption_key;

    unsigned char key[AES_KEY_LENGTH] = {'t', 'e', 's', 't', 't', 'e', 's', 't', 't', 'e', 's', 't', 't', 'e', 's', 't', 't', 'e', 's', 't', 't', 'e', 's', 't', 't', 'e', 's', 't', 't', 'e', 's', 't'};

    unsigned char iv[AES_BLOCK_SIZE] = {'t', 'e', 's', 't', 't', 'e', 's', 't', 't', 'e', 's', 't', 't', 'e', 's', 't'};

    unsigned char iv_enc[AES_BLOCK_SIZE];
    unsigned char iv_dec[AES_BLOCK_SIZE];

    memcpy(iv_enc, iv, AES_BLOCK_SIZE);
    memcpy(iv_dec, iv, AES_BLOCK_SIZE);

    AES_set_encrypt_key(key, AES_KEY_LENGTH * 8, &(encryption_key));
    AES_set_decrypt_key(key, AES_KEY_LENGTH * 8, &(decryption_key));

    char message[] = "Attack at dawn! Attack.";

    unsigned char * encryption_output = new unsigned char[32];
    encryption_output[31] = 3;

    AES_cbc_encrypt((unsigned char *) message, encryption_output, sizeof(message), &encryption_key, iv_enc, AES_ENCRYPT);

    unsigned char * decryption_output = new unsigned char[32];

    AES_cbc_encrypt(encryption_output, decryption_output, 32, &decryption_key, iv_dec, AES_DECRYPT);
}

我在这里做的是加密,然后使用openssl aes库解密消息。我关心的是加密输出的长度。据我所知,由于AES以大小为AES_BLOCK_SIZE(又名为16字节)的块进行加密,因此输出字节数应等于消息的大小,向上舍入为AES_BLOCK_SIZE的最接近倍数。它是否正确?特别是,如果我将消息扩展为正好32个字节,会发生什么?这仍然有效,或者是否会添加16个空填充字节,从而在尝试在encryption_output中写入字节32到47时导致分段错误?

1 个答案:

答案 0 :(得分:6)

正确的PKCS#7填充:

  • 将长度向上舍入为blocksize 的倍数,如果之前不是多个
  • 并且添加整个块否则

否则,在解密时,您可能无法知道最后一个ciperhtext块是“真实的”还是仅填充。 (也可以指定要填充的实际字节值,但是您的真实最后一个块可能包含这些=&gt;再次无法识别它)。

还有其他方案而不是PKCS#7,但这与此无关。

然而,对于AES_cbc_encrypt,你必须自己实现,即。在加密之前填充并在解密后删除填充。加密本身将使用非多个长度,但使用的“填充”具有上述问题。要回答你的原始问题,AES_cbc_encrypt不会添加块,只需要对其进行四舍五入。

对于具有适当填充的函数(并且没有AES_cbc_encrypt的其他缺点,例如缺少AESNI支持等等),请查看OpenSSL的EVP部分。 AES_cbc_encrypt是一个更低级别的部分,具体取决于高级函数使用的情况。

顺便说一下,关于C ++的一些事情:如果你没有得到分段错误,那么 这并不意味着代码是正确的。