Как решить эту ошибку «EVP_DecryptFinal_ex: неправильная длина конечного блока»?

Я хотел бы зашифровать архитектуру нейронной сети, чтобы защитить знание своего исследования.

Пример одного из этих файлов имеет структуру, аналогичную этот< /а> пример.

Код компилируется, но я получаю ошибку времени выполнения, которую не знаю, как решить. Сообщение об ошибке: процедуры цифрового конверта:EVP_DecryptFinal_ex:неверная длина конечного блока.

Я использую OpenSSL версии 1.1.1a 20 ноября 2018 г.

Наиболее актуальные включают

#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/err.h> 

Наиболее релевантный код для ШИФРОВАНИЯ

Открыть и прочитать файл для шифрования

std::ifstream in_file(file_name, std::ios::binary);

in_file.seekg(0, in_file.end);
long size = in_file.tellg();
in_file.seekg(0, in_file.beg);

std::vector<unsigned char> binarydata(size);
in_file.read((char*)binarydata.data(), size);
in_file.close();

Шифровать

EVP_CIPHER_CTX *en;
en = EVP_CIPHER_CTX_new();

unsigned char *salt = (unsigned char *)"12345678";
unsigned char *key_data = (unsigned char *)"super_secret_key_with_32_charact";
int k_len = strlen((const char*)key_data);
int nrounds = 5;
unsigned char key[32], iv[32];

EVP_BytesToKey(
        EVP_aes_256_cbc(), EVP_sha1(), 
        salt, 
        key_data, k_len, nrounds, 
        key, iv);

EVP_CIPHER_CTX_init(en);

// I don't know why, but all examples that I have founded, 
// calls this function twice, so I am doing it too.
EVP_EncryptInit_ex(en, EVP_aes_256_cbc(), NULL, key, iv);
EVP_EncryptInit_ex(en, NULL, NULL, NULL, NULL);

int c_len = size + AES_BLOCK_SIZE, f_len = 0;
std::vector<unsigned char> ciphertext(c_len);

EVP_EncryptUpdate(en, ciphertext.data(), &c_len, binarydata.data(), size);
EVP_EncryptFinal_ex(en, ciphertext.data()+c_len, &f_len);
EVP_CIPHER_CTX_free(en)

Запись зашифрованного текста в новый файл

std::ofstream out_file(output_file, std::ios::binary);
out_file.write((char*)ciphertext.data(), ciphertext.size() * 
sizeof(char));
out_file.close();

Наиболее релевантный код для DECRYPTION

Открыть и прочитать зашифрованный файл

std::ifstream in_file(file_name, std::ios::binary);

in_file.seekg(0, in_file.end);
int size = in_file.tellg();
in_file.seekg(0, in_file.beg);

std::vector<unsigned char> ciphertext(size);
in_file.read((char*)ciphertext.data(), size);
in_file.close();

расшифровать

EVP_CIPHER_CTX *de;
de = EVP_CIPHER_CTX_new();

unsigned char *salt = (unsigned char *)"12345";
unsigned char *key_data = (unsigned char *)"super_secret_key_with_32_charact";
int k_len = strlen((const char*)key_data);
int nrounds = 5;
unsigned char key[32], iv[32];

EVP_BytesToKey(
        EVP_aes_256_cbc(), EVP_sha1(), 
        salt, 
        key_data, k_len, nrounds, 
        key, iv)

EVP_CIPHER_CTX_init(de);

// I don't know why, but all examples that I have founded, 
// calls this function twice, so I am doing it too.
EVP_DecryptInit_ex(de, EVP_aes_256_cbc(), NULL, key, iv);
EVP_DecryptInit_ex(de, NULL, NULL, NULL, NULL);

int p_len = size, f_len = 0;
std::vector<unsigned char> plaintext(p_len);
EVP_DecryptUpdate(de, plaintext.data(), &p_len, ciphertext.data(), size);
EVP_DecryptFinal_ex(de, plaintext.data()+p_len, &f_len);

EVP_CIPHER_CTX_free(de);

return plaintext;

Я хотел бы иметь некоторую помощь в том, как решить эту проблему.


person Carlos Ost    schedule 19.02.2019    source источник
comment
Предложите удалить EVP_EncryptInit_ex(en, NULL, NULL, NULL, NULL). В документах openssl его нет openssl.org/docs/man1.0.2 /man3/EVP_EncryptFinal_ex.html Вы не должны записывать в файл ciphertext.size() байты, а вместо этого c_len+f_len   -  person Oleg    schedule 19.02.2019
comment
@Oleg Я использую версию 1.1.1, и в руководстве говорится, что можно вызывать эту функцию, как я, но я признаю, что просто слепо следую некоторым примерам. Я попытаюсь удалить его, а также попробую c_len+f_len, который вы предложили. Я вернусь сюда с результатами. С Уважением   -  person Carlos Ost    schedule 20.02.2019
comment
EVP_BytesToKey не лучшая функция получения ключа на основе пароля (PBKDF). Но это усугубляется, если вы используете SHA-1. Я бы заменил его на SHA-512, чтобы в результате было достаточно битов для использования как для ключа, так и для IV. Конечно, ваша соль также не должна быть статическим значением; он должен быть случайным и включаться в зашифрованный текст (например, с префиксом, он имеет постоянную длину, поэтому его легко удалить). Предпочтительно количество итераций должно быть 100 000 или что-то подобное. Количество итераций, равное 5, имеет очень мало смысла, вы также можете использовать значение по умолчанию для командной строки OpenSSL: 1.   -  person Maarten Bodewes    schedule 20.02.2019


Ответы (1)


Я не знаю, если это все еще проблема. У меня была точно такая же проблема, и я решил проблему с адаптацией длины зашифрованного текста после шифрования:

EVP_EncryptFinal_ex(en, ciphertext.data()+c_len, &f_len);
ciphertext.erase(ciphertext.begin() + c_len + f_len, ciphertext.end());

При этом длина зашифрованного текста должна быть n * AES_BLOCK_SIZE.

person Daniel    schedule 28.10.2020