AES EVP_Decrypt的“长度”参数是什么?

这与OpenSSL上的EVP_DecryptFinal_ex错误相关联

我试图找出为什么AES解密不起作用,最后我找到了问题所在,现在正在找人帮我解决它:)

这是我测试过的代码(来自各个post):

#include  #include  #include  #include  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 is 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 an 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; } 

我不明白的是:

我应该提供什么作为openSSL EVP Decrypt例程的“len”参数? 什么是魔法len = c_len + f_len?

我应该如何得到这个,以防我只给密钥和iv的密码? 这应该总是可能的吗? 我知道strlen是一个不好的参数,特别是对于二进制文件,因为EVP Decrypt的密文输入是二进制的:所以我该怎么做呢?

我已经可以看到,如果我使用len = strlen(密文)给我一个错误的答案,sizeof参数也不是那个,因为它返回4。

stderr清楚地显示了EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH以及我所理解的所有内容都指出AES数据应该是16个字节的块。 那么我应该改变什么来喂长度呢?

首先,不要从main()返回NULL。 其次,我修复了它并对其进行了注释,希望你能看到长度变量的含义。 我认为你缺少的关键点是你给OpenSSL函数一个可以写入数据的缓冲区。 像许多带缓冲区的函数一样,你给它一个缓冲区大小,它会返回它实际写入缓冲区的字节数。 为什么? 因为您必须知道缓冲区何时已满,或者如果您正在逐步填充缓冲区,则必须知道在哪里写入下一个数据块。

另外,我认为您应该阅读一些有关如何使用二进制数据的教程以及它与C风格字符串的区别。 OpenSSL EVP函数使用二进制数据,这就是为什么你需要告诉每个函数你的数据有多少字节。

 #include  #include  #include  #include  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; unsigned char *plaintext = NULL; unsigned char *ciphertext = NULL; int input_len = 0; unsigned char iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; unsigned char key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; const char *string_to_encrypt = "hi this is patrick immling\n'Doctor'.\n'Doctor' who ?\nPrecisely! 123910!§$$§% !%%$&$(/=))?=(#ü++Ü**<,.here we go sometimes it is difficult but 187! 1$5 78@2 14 .TӒ  틪 ձ1z.$ ? U