EVP_EncryptUpdate отсутствует 4 байта - PullRequest
0 голосов
/ 10 апреля 2019

Я хочу зашифровать входные данные блоками по 100 байт с помощью шифрования OpenSSL AES-256-cbc. Однако EVP_EncryptUpdate шифрует только 96 байтов (параметр tmp = 96). Следующий вызов EVP_EncryptUpdate зашифровывает остальные данные (за исключением тех, которые отсутствуют 4).

Расшифровка в порядке, кроме тех 4 пропущенных байтов.

Если я вызову EVP_EncryptUpdate только один раз и передам все данные сразу, все в порядке.

Я не понимаю, почему эти 4 байта отсутствуют, если я передаю только 100 байтов в EVP_EncryptUpdate.

std::string data = "A12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123hgfedcba";

unsigned char key[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
                        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
unsigned char iv[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };

int  i = 0, tmp = 0, ol = 0;

int res = EVP_EncryptInit(&ctx, EVP_aes_256_ecb(), key, iv);   

std::unique_ptr<unsigned char[]> ret(new unsigned char[dataLen+EVP_CIPHER_CTX_block_size(&ctx)]);

for (i = 0; i < dataLen / 100; i++)
{  
   EVP_EncryptUpdate(&ctx,
   &ret[ol], &tmp, &data[ol], 100); 
   ol += tmp;
}


if (dataLen % 100)
{  
    EVP_EncryptUpdate(&ctx, &ret[ol], &tmp, &data[ol], dataLen % 100);
    ol += tmp;
}

EVP_EncryptFinal(&ctx, &ret[ol], &tmp);

1 Ответ

0 голосов
/ 13 апреля 2019

EVP_EncryptUpdate ДОЛЖЕН сопровождаться EVP_EncryptFinal. Режим CBC может только шифровать / дешифровать полные блоки. Библиотека не знает, что за последним вызовом EVP_EncryptUpdate не последовал еще один, поэтому EVP_EncryptFinal должен использоваться, чтобы сигнализировать об окончании открытого текста сообщения для шифрования / дешифрования.

EVP_EncryptUpdate попытается зашифровать столько блоков, сколько возможно, а оставшиеся оставит во внутреннем буфере. Во время EVP_EncryptFinal заполнение, совместимое с PKCS # 7, добавляется к данным, которые находятся в буфере, и последние блоки зашифровываются, и возвращается последняя часть зашифрованного текста. Обратите внимание, что заполнение всегда применяется, даже если внутренний буфер пуст.

В целом, ваши последние четыре байта дополняются и шифруются, когда вы звоните EVP_EncryptFinal или добавляете достаточно данных, используя обновления, чтобы создать полный блок открытого текста для шифрования. Если вы не вызовете EVP_EncryptFinal, то зашифрованный текст не будет дополнен, и ваше дешифрование завершится ошибкой или - если последняя часть зашифрованного текста может рассматриваться как допустимое заполнение - это отбросит некоторые байты конца и вернуть то, что осталось. Опять же, при использовании обновлений вы должны завершить.

Если вам не нравится этот тип поведения, вы можете посмотреть на режим CTR, который - по крайней мере теоретически - является потоковым режимом и может возвращать зашифрованные байты напрямую, не требуя заполнения. Это называется «онлайн» свойством режима блочного шифрования. Иногда реализации все еще буферизуют открытый текст, пока не будет заполнен полный блок, так что будьте осторожны.


Примечания по кодированию:

  • 100 не кратно размеру блока (16 байт), поэтому очевидно, что осталось 4 байта.

  • CBC требует уникального, непредсказуемого ключа / IV для режима CBC, а CTR требует уникального одноразового номера.

Вам лучше изучить эти алгоритмы, иначе вам не удастся создать безопасный код. Для безопасности на транспорте вы захотите использовать аутентифицированный шифр.

...