什么是“长度” AES EVP_Decrypt参数? [英] What is the "length" parameter of AES EVP_Decrypt?

查看:157
本文介绍了什么是“长度” AES EVP_Decrypt参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这与 OpenSSL上的EVP_DecryptFinal_ex错误相关联



我试图找出为什么AES解密不起作用,最后我发现问题是什么,现在寻找一个人来帮助我解决它: / p>

以下是我测试的代码(来自各种帖子):

  #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 =你好,这是patrick immling\\\
'Doctor'.\\\
'Doctor'谁?\\\
Precisely!123910!§$$§%!%% $& $(/ =))?=(#ü++Ü**<,。这里我们走时有时很难,但187!1 $ 5 78 @ 2 14.TӒ 틪 ձ1 z。$ U < ; y;

printf(AES ALGORITHM FOR 128 bit CBC MODE\\\
);
cipher_type = EVP_aes_128_cbc();
AES_BLOCK_SIZE = 128;
passkey = key;
passiv = iv;
plain = input;

printf(iv =);
for(i = 0; i < iv; i ++){
printf(%02x,iv [i]);
// printf(key [%d] =%02x\\\
,i,key [i] );
}
printf(\\\
);
printf(key =);
for(i = 0; i< sizeof key; i ++) {
printf(%02x,key [i]);
// printf(key [%d] =%02x\\\
,i,key [i]);

printf(\\\
);

printf(初始化AES算法为CBC MODE..\\\
);

EV P_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 \\\\
,len);


//对于n字节的明文,最大密文len为n + AES_BLOCK_SIZE -1字节
int c_len = len + AES_BLOCK_SIZE - 1;
int f_len = 0;
ciphertext =(unsigned char *)malloc(c_len);

/ *允许对多个加密周期重用'e'* /
if(!EVP_EncryptInit_ex(& en,NULL,NULL,NULL,NULL)){
printf (EVP_EncryptInit_ex \\\
中的错误));
返回NULL;
}

if(!EVP_EncryptUpdate(& en,ciphertext,& c_len,plain,len)){
printf(EVP_EncryptUpdate \\\
中的ERROR)
返回NULL;
}
printf(更新后的len值\%d \\\\
,len);
// printf(size of ciphertext after update \%d\\\\
,sizeof(ciphertext));
printf(更新后的密文的strlen值\%d\\\\
,strlen(ciphertext));

if(!EVP_EncryptFinal_ex(& en,ciphertext + c_len,& f_len)){
printf(EVP_EncryptFinal_ex \\\
中的ERROR)
返回NULL;
}
printf(len value after final \%d \\\\
,len);
printf(strlen value of ciphertext after final \%d\\\\
,strlen(ciphertext));
EVP_CIPHER_CTX_cleanup(& en);

len = c_len + f_len;
printf(len value after aes_encrypt \%d\\\\
,len);

//这里是问题:如果我使用len = strlen(ciphertext)I GET ERROR
// len = strlen(ciphertext);

printf(strlen value of ciphertext after aes_encrypt \%d \\\\
,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(EVP_DecryptInit_ex \\\
中的ERROR);
返回NULL;
}
EVP_CIPHER_CTX_set_padding(& de,0);

if(!EVP_DecryptUpdate(& de,plaintext,& p_len,ciphertext,len)){
printf(EVP_DecryptUpdate\\\
中的ERROR)
返回NULL;
}
printf(len value after decrypt update \%d \\\\
,len);
if(!EVP_DecryptFinal_ex(& de,plaintext + p_len,& f_len)){
printf(EVP_DecryptFinal_ex\\\
中的ERROR);
ERR_print_errors_fp(stderr);
返回NULL;
}

EVP_CIPHER_CTX_cleanup(& de);
len = p_len + f_len;
printf(解密值=%s\\\
,明文);

printf(len value after aes_decrypt \%d \\\\
,len);


if(strncmp(plaintext,input,olen))
printf(FAIL:enc / dec failed for \%s\\\\
输入);
else
printf(OK:enc / dec ok for \%s\\\\
,plaintext); // \%s\\\\

printf(\\\
);

free(ciphertext);
免费(明文);

return 0;
}

我不明白:



作为openSSL EVP解密例程的len参数,应该怎么做?
什么是这个魔术len = c_len + f_len?



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



我可以看到,如果我使用len = strlen(ciphertext)给我一个错误的答案,sizeof参数也不是一个返回4。



stderr清楚地显示了EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH,我明白你们都指出AES数据应该是16字节的块。
那么我应该改变什么来提供长度?

解决方案

首先,不要从main()返回NULL 。其次,我修改它并注释它,所以希望你可以看到长度变量的意思。我认为您所缺少的关键点在于,您将OpenSSL功能作为缓冲区,可以在其中编写数据。像许多需要缓冲区的函数一样,你给它一个缓冲区大小,它返回到实际写入缓冲区的字节数。为什么?因为你必须知道你的缓冲区是否满了,或者如果你要缓慢地填充你的缓冲区,你必须知道在哪里写下一个数据块。



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

 包括< string.h> 
#include< stdio.h>
#include< stdlib.h>
#include< openssl / evp.h>

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 =你好是patrick immling\\\
'Doctor'.\\\
'Doctor'谁?\\\
Precisely!123910!§$$§%!%% $& ; $(/ =))?=(#ü++Ü**<,。这里我们走了有时很难,但187!1 $ 5 78 @ 2 14.TӒ 틪 ձ1 z。$ ? U < y;

cipher_type = EVP_aes_128_cbc();

EVP_EncryptInit_ex(& en,cipher_type,NULL,key,iv);
EVP_DecryptInit_ex (& de,cipher_type,NULL,key,iv);

//我们要加密的数据是一个字符串,所以我们可以做一个简单的
// strlen来计算它的长度,但加密的缓冲区将要
//用PKCS填充填充最坏的情况下,我们的字符串是AES块大小(16字节)的
//倍数,在那里我们可以通过
//来精确计算缓冲区:
// int input_len = strlen(string_to_encrypt) ;
/ / malloc(input_len + 16 - (input_len%16));
//但是为什么要花哨?只需添加一个额外的AES块,最多只能有16
//未使用的字节,通常小于此值。
static const int MAX_PADDING_LEN = 16;

//我们添加1,因为我们加密一个字符串,它有一个NULL终止符
//,并希望在我们解密时存在NULL终止符。
input_len = strlen(string_to_encrypt)+ 1;
ciphertext =(unsigned char *)malloc(input_len + MAX_PADDING_LEN);

/ *允许对多个加密周期重用'e'* /
if(!EVP_EncryptInit_ex(& en,NULL,NULL,NULL,NULL)){
printf (EVP_EncryptInit_ex \\\
中的错误));
return 1;
}

//此函数适用于二进制数据,而不是字符串。所以我们将
// string转换为一个unsigned char *,并指出长度为空终止符的字符串
// length + 1 byte。
int bytes_written = 0;
int ciphertext_len = 0;
if(!EVP_EncryptUpdate(& en,
ciphertext,& bytes_written,
(unsigned char *)string_to_encrypt,input_len)){
printf(EVP_EncryptUpdate \ N);
return 1;
}
ciphertext_len + = bytes_written;

//现在密码缓冲区只包含直到最后一个完整AES块的输入数据的加密版本
//。例如,如果您的输入
//大小为206,则ciphertext_len将为192,因为您有14个字节
//要加密,这些字节不能填满完整的AES块。但是
// encryptor已经存储了这些字节,并且正在等待更多的字节
//或调用EVP_EncryptFinal,它将添加填充以使
//加密数据的大小相同作为AES块(即,在上述示例中为2字节的填充
//)。
printf(Input len:%d,ciphertext_len:%d\\\
,input_len,ciphertext_len);

// EVP_EncryptFinal_ex写填充。来自EVP_EncryptUpdate的
// bytes_written变量的整点是告诉我们缓冲区的
//多少,所以我们知道我们可以在哪里编写填充。
//请注意,我们知道我们的缓冲区足够大,所以我们不会麻烦
//跟踪缓冲区大小。我们只是跟踪它中有多少数据是
//。

if(!EVP_EncryptFinal_ex(& en,
ciphertext + bytes_written,
& bytes_written)){
printf(EVP_EncryptFinal_ex \\\
中的ERROR) ;
return 1;
}
ciphertext_len + = bytes_written;

EVP_CIPHER_CTX_cleanup(& en);

printf(Input len:%d,ciphertext_len:%d\\\
,input_len,ciphertext_len);

//我们假装我们不知道这里的输入长度。我们知道
//密文长度最多为16字节+输入长度。所以
//因为密文总是大于输入长度,我们可以
//声明明文缓冲区大小=密文缓冲区大小,并知道
//没有办法我们会溢出我们的明文缓冲区。它将在
//最后16个字节的浪费空间,但没关系。
plaintext =(unsigned char *)malloc(ciphertext_len);

if(!EVP_DecryptInit_ex(& de,NULL,NULL,NULL,NULL)){
printf(EVP_DecryptInit_ex \\\
中的ERROR)
return 1;
}

//不!您正在加密任意数据,因此您应该使用填充。你
//只有提前知道你正在加密长度是块大小的倍数的
//数据时,不要使用填充。喜欢运行
// AES已知答案测试。
// EVP_CIPHER_CTX_set_padding(& de,0); / *不! * /

int plaintext_len = 0;
if(!EVP_DecryptUpdate(& de,
plaintext,& bytes_written,
ciphertext,ciphertext_len)){
printf(EVP_DecryptUpdate\\\
中的ERROR);
return 1;
}
plaintext_len + = bytes_written;

//此函数验证填充,然后将其丢弃。它将
//返回一个错误,如果填充不是它期望的,这意味着
//数据格式错误,或者你用错误的密钥解密它。
if(!EVP_DecryptFinal_ex(& de,
plaintext + bytes_written,& bytes_written)){
printf(EVP_DecryptFinal_ex\\\
中的ERROR);
return 1;
}
plaintext_len + = bytes_written;

EVP_CIPHER_CTX_cleanup(& de);

//我们加密了一个字符串,所以我们知道我们解密了一个字符串。所以我们
//可以打印它。请注意,我们知道我们的二进制数据是一个字符串,所以
//我们只是将其转换为char *。我们可以很容易地声明它
//原来是一个char *(我想我从原来的
//程序实际上改变了),然后将其转换为对EVP_DecryptUpdate的调用。
printf(input_len:%d,ciphertext_len:%d,plaintext_len:%d\\\

input_len,ciphertext_len,plaintext_len);

printf(解密值=%s\\\
,明文);
if(strcmp(string_to_encrypt,(char *)plaintext)== 0){
printf(Decrypted data matches input data.\\\
);
}
else {
printf(解密数据不匹配输入数据。\);
}

free(ciphertext);
免费(明文);

return 0;
}


This is linked to EVP_DecryptFinal_ex Error on OpenSSL

I was trying to find out why the AES decrypt won't work and finally I have found what the problem is and now looking for someone to help me solve it :)

Here is the code that I tested with(from various posts here):

#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;
}

What I dont understand:

What should I feed as the "len" parameter for the openSSL EVP Decrypt routines? what is this magic len = c_len+ f_len?

How should I get this in case I am given just the cipher with the key and the iv? This should be always possible right? I know strlen is a bad parametr especially for binary as the ciphertext input to EVP Decrypt is binary: so how should I get this?

I can already see that if I use len= strlen(ciphertext) gives me a wrong answer and sizeof parameter is also not the one as it returns 4.

The stderr shows clearly that the EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH and which I understand as you have all pointed out that the AES data should be 16 byte chunks. So what should I change to feed the length?

解决方案

First, don't return NULL from main(). Second, I fixed it and annotated it so hopefully you can see what the length variables mean. I think the key point you're missing is that you're giving the OpenSSL functions a buffer where it can write its data. Like many functions that take a buffer, you give it a buffer size and it returns to you the number of bytes it actually wrote into the buffer. Why? Because you have to know when your buffer is full, or if you're filling your buffer incrementally you have to know where to write the next chunk of data.

Also, I think you should read some tutorials on how to work with binary data and how it differs from a C-style string. The OpenSSL EVP functions work with binary data, which is why you need to tell every function how many bytes your data is.

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>

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 i s difficult but 187! 1$5 78@2 14  .TӒ��틪�ձ1z.$�?�U���<y";

    cipher_type = EVP_aes_128_cbc();

    EVP_EncryptInit_ex(&en, cipher_type, NULL, key, iv);
    EVP_DecryptInit_ex(&de, cipher_type, NULL, key, iv);

    // The data we want to encrypt is a string.  So we can just do a simple
    // strlen to calculate its length.  But the encrypted buffer is going to
    // be padded with PKCS padding.  In the worst case, our string is a
    // multiple of the AES block size (16 bytes).  In that case, the PKCS
    // padding will be an additional 16 bytes after our data.  So we could
    // precisely calculate the buffer with this:
    // int input_len = strlen(string_to_encrypt);
    // malloc( input_len + 16 - (input_len % 16) );
    // But why get fancy?  Just add an extra AES block and have at most 16
    // unused bytes at the end, and usually less than that.
    static const int MAX_PADDING_LEN = 16;

    // We add 1 because we're encrypting a string, which has a NULL terminator
    // and want that NULL terminator to be present when we decrypt.
    input_len = strlen(string_to_encrypt) + 1;
    ciphertext = (unsigned char *) malloc(input_len + MAX_PADDING_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 1;
      }

      // This function works on binary data, not strings.  So we cast our
      // string to an unsigned char * and tell it that the length is the string
      // length + 1 byte for the null terminator.
      int bytes_written = 0;
      int ciphertext_len = 0;
      if(!EVP_EncryptUpdate(&en,
                           ciphertext, &bytes_written,
                           (unsigned char *) string_to_encrypt, input_len) ) {
        printf("ERROR in EVP_EncryptUpdate \n");
        return 1;
      }
      ciphertext_len += bytes_written;

      // Right now the ciphertext buffer contains only the encrypted version
      // of the input data up to the last full AES block.  E.g., if your input
      // size is 206, then ciphertext_len will be 192 because you have 14 bytes
      // left to encrypt and those bytes can't fill a full AES block.  But the
      // encryptor has stored those bytes and is waiting either for more bytes
      // or the call to EVP_EncryptFinal where it will add padding to make the
      // encrypted data the same size as the AES block (i.e., 2 bytes of padding
      // in the above example).
      printf("Input len: %d, ciphertext_len: %d\n", input_len, ciphertext_len);

      // EVP_EncryptFinal_ex writes the padding.  The whole point of the
      // bytes_written variable from EVP_EncryptUpdate is to tell us how much
      // of the buffer is full so we know where we can write the padding.
      // Note that we know our buffer is large enough so we're not bothering to
      // keep track of the buffer size.  We just keep track of how much data is
      // in it.

      if(!EVP_EncryptFinal_ex(&en,
                              ciphertext + bytes_written,
                              &bytes_written)){
        printf("ERROR in EVP_EncryptFinal_ex \n");
        return 1;
      }
      ciphertext_len += bytes_written;

      EVP_CIPHER_CTX_cleanup(&en);

      printf("Input len: %d, ciphertext_len: %d\n", input_len, ciphertext_len);

      // We'll pretend we don't know the input length here.  We do know that
      // the ciphertext length is at most 16 bytes + the input length.  So
      // since the ciphertext is always greater than the input length, we can
      // declare plaintext buffer size = ciphertext buffer size and know that
      // there's no way we'll overflow our plaintext buffer.  It will have at
      // most 16 bytes of wasted space on the end, but that's ok.
      plaintext = (unsigned char *) malloc(ciphertext_len);

      if(!EVP_DecryptInit_ex(&de, NULL, NULL, NULL, NULL)){
        printf("ERROR in EVP_DecryptInit_ex \n");
        return 1;
      }

      // No!  You're encrypting arbitrary data, so you should use padding.  You
      // don't use padding only if you know in advance that you're encrypting
      // data whose length is a multiple of the block size.  Like when running
      // the AES known-answer tests.
      // EVP_CIPHER_CTX_set_padding(&de, 0); /* no! */

      int plaintext_len = 0;
      if(!EVP_DecryptUpdate(&de,
                            plaintext, &bytes_written,
                            ciphertext, ciphertext_len)){
        printf("ERROR in EVP_DecryptUpdate\n");
        return 1;
      }
      plaintext_len += bytes_written;

      // This function verifies the padding and then discards it.  It will
      // return an error if the padding isn't what it expects, which means that
      // the data was malformed or you are decrypting it with the wrong key.
      if(!EVP_DecryptFinal_ex(&de,
                              plaintext + bytes_written, &bytes_written)){
        printf("ERROR in EVP_DecryptFinal_ex\n");
        return 1;
      }
      plaintext_len += bytes_written;

      EVP_CIPHER_CTX_cleanup(&de);

      // We encrypted a string, so we know that we decrypted a string.  So we
      // can just print it.  Note that we know our binary data is a string so
      // we just cast it to a char *.  We could just have easily declared it
      // originally as a char * (I think I changed that from your original
      // program, actually) and then cast it in the call to EVP_DecryptUpdate.
      printf("input_len: %d, ciphertext_len: %d, plaintext_len: %d\n",
          input_len, ciphertext_len, plaintext_len);

      printf("Decrypted value = %s\n", plaintext);
      if( strcmp(string_to_encrypt, (char *) plaintext) == 0 ) {
          printf("Decrypted data matches input data.\n");
      }
      else {
          printf("Decrypted data does not match input data.\n");
      }

   free(ciphertext);
   free(plaintext);

  return 0;
}

这篇关于什么是“长度” AES EVP_Decrypt参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆