长度是多少? AES EVP_Decrypt 的参数?

发布于 2024-11-02 10:32:03 字数 5203 浏览 5 评论 0原文

这链接到 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;
}

我不明白的是:

我应该将什么作为 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 字节块。 那么我应该改变什么来满足长度呢?

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!§$§% !%%
amp;$(/=))?=(#ü++Ü**<,.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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

暗藏城府 2024-11-09 10:32:03

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

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

#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!§$§% !%%
amp;$(/=))?=(#ü++Ü**<,.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);

      // 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);

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

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!§$§% !%%
amp;$(/=))?=(#ü++Ü**<,.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);

      // 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);

      // 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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文