Это связано с EVP_DecryptFinal_ex Ошибка в OpenSSL
Я пытался выяснить, почему расшифровка AES не работает, и, наконец, я нашел, в чем проблема, и теперь ищу кого-нибудь, кто поможет мне решить ее:)
Вот код, который я тестировал (из различных постов здесь):
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
int AES_BLOCK_SIZE = 128;
int main(int argc, char **argv)
{
EVP_CIPHER_CTX en;
EVP_CIPHER_CTX de;
EVP_CIPHER_CTX_init(&en);
EVP_CIPHER_CTX_init(&de);
const EVP_CIPHER *cipher_type;
unsigned char *passkey, *passiv, *plaintxt;
char *plain;
char *plaintext;
unsigned char *ciphertext;
int olen, len;
int i =0;
unsigned char iv[] = { 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0 };
unsigned char key[]= { 0x2b, 0x7e, 0x15, 0x16,
0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88,
0x09, 0xcf, 0x4f, 0x3c , 0 };
unsigned char *input = "hi this is patrick immling\n'Doctor'.\n'Doctor' who ?\nPrecisely! 123910!§$$§% !%%$&$(/=))?=(#ü++Ü**<,.here we go sometimes it i s difficult but 187! 1$5 78@2 14 .TӒ��틪�ձ1z.$�?�U���<y";
printf("AES ALGORITHM FOR 128 bit CBC MODE\n");
cipher_type = EVP_aes_128_cbc();
AES_BLOCK_SIZE = 128;
passkey = key;
passiv = iv;
plain = input;
printf("iv=");
for(i = 0; i < sizeof iv; i++){
printf("%02x", iv[i]);
//printf("key[%d]= %02x\n", i, key[i]);
}
printf("\n");
printf("key=");
for(i = 0; i < sizeof key; i++){
printf("%02x", key[i]);
//printf("key[%d]= %02x\n", i, key[i]);
}
printf("\n");
printf("Initializing AES ALGORITHM FOR CBC MODE..\n");
EVP_EncryptInit_ex(&en, cipher_type, NULL, passkey, passiv);
EVP_DecryptInit_ex(&de, cipher_type, NULL, passkey, passiv);
olen = len = strlen(input)+1;
printf("len value before aes_encrypt \"%d\"\n", len);
// max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 bytes
int c_len = len + AES_BLOCK_SIZE - 1;
int f_len = 0;
ciphertext = (unsigned char *)malloc(c_len);
/* allows reusing of 'e' for multiple encryption cycles */
if(!EVP_EncryptInit_ex(&en, NULL, NULL, NULL, NULL)){
printf("ERROR in EVP_EncryptInit_ex \n");
return NULL;
}
if(!EVP_EncryptUpdate(&en, ciphertext, &c_len, plain, len)){
printf("ERROR in EVP_EncryptUpdate \n");
return NULL;
}
printf("len value after update \"%d\"\n", len);
// printf("size of ciphertext after update \"%d\"\n", sizeof(ciphertext));
printf("strlen value of ciphertext after update \"%d\"\n", strlen(ciphertext));
if(!EVP_EncryptFinal_ex(&en, ciphertext+c_len, &f_len)){
printf("ERROR in EVP_EncryptFinal_ex \n");
return NULL;
}
printf("len value after final \"%d\"\n", len);
printf("strlen value of ciphertext after final \"%d\"\n", strlen(ciphertext));
EVP_CIPHER_CTX_cleanup(&en);
len = c_len + f_len;
printf("len value after aes_encrypt \"%d\"\n", len);
//HERE IS THE PROBLEM: IF I USE len= strlen(ciphertext) I GET ERROR
//len = strlen(ciphertext);
printf("strlen value of ciphertext after aes_encrypt \"%d\"\n", len);
int p_len = len;
f_len = 0;
plaintext = (unsigned char *)malloc(p_len);
// memset(plaintext,0,sizeof(plaintext));
if(!EVP_DecryptInit_ex(&de, NULL, NULL, NULL, NULL)){
printf("ERROR in EVP_DecryptInit_ex \n");
return NULL;
}
EVP_CIPHER_CTX_set_padding(&de, 0);
if(!EVP_DecryptUpdate(&de, plaintext, &p_len, ciphertext, len)){
printf("ERROR in EVP_DecryptUpdate\n");
return NULL;
}
printf("len value after decrypt update \"%d\"\n", len);
if(!EVP_DecryptFinal_ex(&de, plaintext+p_len, &f_len)){
printf("ERROR in EVP_DecryptFinal_ex\n");
ERR_print_errors_fp(stderr);
return NULL;
}
EVP_CIPHER_CTX_cleanup(&de);
len = p_len + f_len;
printf("Decrypted value = %s\n", plaintext);
printf("len value after aes_decrypt \"%d\"\n", len);
if (strncmp(plaintext, input, olen))
printf("FAIL: enc/dec failed for \"%s\"\n", input);
else
printf("OK: enc/dec ok for \"%s\"\n", plaintext); // \"%s\"\n
printf("\n");
free(ciphertext);
free(plaintext);
return 0;
}
Что я не понимаю:
Что мне следует указывать в качестве параметра "len" для процедур расшифровки openSSL EVP?
что это за волшебство len = c_len + f_len?
Как мне это получить, если мне дали только шифр с ключом и iv? Это должно быть всегда возможно, верно? Я знаю, что strlen - плохой параметр, особенно для двоичного файла, поскольку вход зашифрованного текста в EVP Decrypt является двоичным: так как мне это получить?
Я уже вижу, что если я использую len = strlen (зашифрованный текст), я получаю неправильный ответ, а параметр sizeof также не тот, который возвращает 4.
Stderr ясно показывает, что EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH и, как я понимаю, вы все указали, что данные AES должны быть 16-байтовыми блоками.
Так что я должен изменить, чтобы кормить длину?