AES_cbc_encrypt добавляет дополнение?

Рассмотрим следующий фрагмент кода 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. Что меня беспокоит, так это длина encryption_output. Насколько я понимаю, поскольку AES шифрует в блоках размером AES_BLOCK_SIZE (он же 16 байтов), количество выходных байтов должно быть равно размеру сообщения, округленному до ближайшего кратного AES_BLOCK_SIZE. Это правильно? В частности, что произойдет, если я расширю сообщение длиной ровно 32 байта? Будет ли это работать, или будут добавлены 16 пустых байтов заполнения, что приведет к ошибке сегментации при попытке записи байтов 32–47 в encryption_output?

2

Решение

Правильная прокладка PKCS # 7:

  • округляет длину до кратного размера блока если это было не кратно
  • и это добавляет целый блок иначе

Иначе, при расшифровке вы не могли бы знать, является ли последний блок зашифрованного текста «реальным» или только дополнением. (Также указываются фактические значения байтов для заполнения, но ваш последний последний блок может содержать эти =>, опять же, его невозможно распознать).

Есть и другие схемы, кроме PKCS # 7, но здесь это не актуально.

Однако с AES_cbc_encrypt, вам придется реализовать это самостоятельно, т.е. pad перед шифрованием и удалить padding после расшифровки. Само шифрование будет работать с кратными длинами, но у использованного «заполнения» есть проблема, упомянутая выше. Чтобы ответить на ваш оригинальный вопрос, AES_cbc_encrypt не будет добавлять блоки, округление длины — единственное, что он делает.

Для функций с правильным заполнением (и без ряда других недостатков AES_cbc_encrypt(например, отсутствует поддержка AESNI и т. д.), посмотрите на часть EVP в OpenSSL. AES_cbc_encrypt Это более низкоуровневая часть, в зависимости от ситуации, в которой она также используется функцией высокого уровня.

Кстати, кое-что о C ++: если вы не получите ошибку сегментации,
это не значит, что код правильный.

6

Другие решения