加密错误(QT c++ OpenSSL AES 256 CBC)

Wrong Encryption (QT c++ OpenSSL AES 256 CBC)

我写了一个小程序来使用 OpenSSL AES 256 CBC 加密和解密数据,但在解密加密数据后,我得到了垃圾数据,所以代码中一定有问题,但我无法弄清楚请你看看代码并告诉我我做错了什么:

主要功能:

  /* Message to be encrypted */
    unsigned char* plaintext =
                (unsigned char*)"The quick brown fox jumps over the lazy dog";

  EVP_CIPHER_CTX *en, *de;
   en = EVP_CIPHER_CTX_new();
   de = EVP_CIPHER_CTX_new();

    /* 8 bytes to salt the key_data during key generation. This is an example of
       compiled in salt. We just read the bit pattern created by these two 4 byte
       integers on the stack as 64 bits of contigous salt material -
       ofcourse this only works if sizeof(int) >= 4 */
    unsigned int salt[] = {12345, 54321};
    unsigned char *key_data;
    int key_data_len, i;

    key_data = (unsigned char*)"01234567890123456789012345678901";
    key_data_len = strlen((const char*)key_data);

    Encryption AES;

    /* gen key and iv. init the cipher ctx object */
    if (AES.Init(key_data, key_data_len, (unsigned char *)&salt, en, de)) {
      qDebug() << "Couldn't initialize AES cipher ";
    }

      unsigned char *ciphertext;
      int olen, len;

      /* The enc/dec functions deal with binary data and not C strings. strlen() will
         return length of the string without counting the '[=10=]' string marker. We always
         pass in the marker byte to the encrypt/decrypt functions so that after decryption
         we end up with a legal C string */
      olen = len = strlen((const char*)plaintext)+1;



      ciphertext = AES.Encrypt(en, plaintext, &len);
      plaintext = (unsigned char*)"";
      plaintext = AES.Decrypt(de, ciphertext, &len);

      QString s;
      QString result = "";
      int rev = strlen((const char*)ciphertext);

      for ( int i = 0; i<rev; i++)
           {
              s = QString("%1").arg(ciphertext[i],0,16);

              if(s == "0"){
                s="00";
               }
            result.append(s);

            }

      ui->label_7->setText(result);

      rev = len;
      result = "";
      for ( int i = 0; i<rev; i++)
                     {
                        s = QString("%1").arg(plaintext[i],0,16);

                        if(s == "0"){
                          s="00";
                         }
                      result.append(s);

                      }

      ui->label_8->setText(result);

      free(ciphertext);
      free(plaintext);

    EVP_CIPHER_CTX_free(en);
    EVP_CIPHER_CTX_free(de);

初始化函数:

int Encryption::Init(unsigned char *key_data, int key_data_len, unsigned char *salt, EVP_CIPHER_CTX *e_ctx,
             EVP_CIPHER_CTX *d_ctx)
{
  int i, nrounds = 5;
  unsigned char key[32], iv[32];

  /*
   * Generate key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material.
   * nrounds is the number of times we hash the material. More rounds are more secure but
   * slower.
   */
  i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, key_data_len, nrounds, key, iv);
  if (i != 32) {
    QMessageBox::warning(this, tr("Error while generating the key"), tr("The key isn't 256 bit!"));
    return -1;
  }

  EVP_CIPHER_CTX_init(e_ctx);
  EVP_EncryptInit_ex(e_ctx, EVP_aes_256_cbc(), NULL, key, iv);
  EVP_CIPHER_CTX_init(d_ctx);
  EVP_DecryptInit_ex(d_ctx, EVP_aes_256_cbc(), NULL, key, iv);

  return 0;
}

加密函数:

inline unsigned char* Encryption:: Encrypt(EVP_CIPHER_CTX *e, unsigned char *plaintext, int *len)
{
  // max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE bytes
  int c_len = *len + AES_BLOCK_SIZE, f_len = 0;
  ciphertext = new unsigned char[c_len];

  // allows reusing of 'e' for multiple encryption cycles
  EVP_EncryptInit_ex(e, NULL, NULL, NULL, NULL);

  /* update ciphertext, c_len is filled with the length of ciphertext generated,
    *len is the size of plaintext in bytes */
  int encrypted_bytes = 0;

  for(int i=0;i<*len/AES_BLOCK_SIZE;++i)
  {
      EVP_EncryptUpdate(e, ciphertext+encrypted_bytes, &c_len, plaintext+encrypted_bytes, AES_BLOCK_SIZE);
      encrypted_bytes += AES_BLOCK_SIZE;
      float counter = i , size = *len/AES_BLOCK_SIZE+1;
      emit Encryption_Percentage_Changed(counter/size * 100);
  }
  // update ciphertext with the final remaining bytes
  EVP_EncryptFinal_ex(e, ciphertext+*len, &f_len);

  *len = *len + f_len;

  emit Encryption_Finished();

  return ciphertext;
}

解密函数:

inline unsigned char* Encryption::Decrypt(EVP_CIPHER_CTX *e, unsigned char *ciphertext, int *len)
{
  // plaintext will always be equal to or lesser than length of ciphertext
  int p_len = *len+AES_BLOCK_SIZE, f_len = 0;

  plaintext = new unsigned char[p_len];

  EVP_DecryptInit_ex(e, NULL, NULL, NULL, NULL);

  int decrypted_bytes = 0;

  for(int i=0;i<*len/AES_BLOCK_SIZE;++i){
      EVP_DecryptUpdate(e, plaintext+decrypted_bytes, &p_len, ciphertext+decrypted_bytes, AES_BLOCK_SIZE);
      decrypted_bytes += AES_BLOCK_SIZE;
      float counter = i , size = *len/AES_BLOCK_SIZE;
      emit Decryption_Percentage_Changed(counter/size * 100);
  }

  EVP_DecryptFinal_ex(e, plaintext+*len, &f_len);


  *len = *len + f_len;

  emit Decryption_Finished();

  return plaintext;
}

编辑:我现在已经用实际代码替换了图像。

如有任何帮助,我们将不胜感激。 提前致谢。

当我尝试 result=QString::fromLocal8Bit((char*)ciphertext); 时,我终于意识到显示加密和解密字符串的问题是什么。 它运行良好并显示了原文。