【问题标题】:Openssl C++ AES decryption adding unexpected symbolsOpenssl C++ AES解密添加意外符号
【发布时间】:2019-03-20 13:16:46
【问题描述】:

我正在尝试在 C++ 中解密已使用 Linux 命令加密的文件:openssl enc -aes-256-cbc -nosalt -K "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855" -iv "5DF6E0E27615359D .json -out file.enc
解密效果很好,但是我在终端打印的时候文件末尾出现了意想不到的符号,如下图Image
这是我的 C++ 代码,有人可以帮助我吗?

int main(int argc, char **argv)
{
  EVP_CIPHER_CTX *en, *de;
  en = EVP_CIPHER_CTX_new();
  de = EVP_CIPHER_CTX_new();

  unsigned char key_data[] = {0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24, 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B,0x78, 0x52, 0xB8, 0x55};
  int key_data_len = 32;

  std::ifstream in("file.enc");
  std::string contents((std::istreambuf_iterator<char>(in)), 
  std::istreambuf_iterator<char>());


  unsigned char iv[] = {0x5D, 0xF6, 0xE0, 0xE2, 0x76, 0x13, 0x59, 0xD3, 0x0A, 0x82, 0x75, 0x05, 0x8E, 0x29, 0x9F, 0xCC};

  EVP_CIPHER_CTX_init(en);
  EVP_EncryptInit_ex(en, EVP_aes_256_cbc(), NULL, key_data, iv);
  EVP_CIPHER_CTX_init(de);
  EVP_DecryptInit_ex(de, EVP_aes_256_cbc(), NULL, key_data, iv);


  char *plaintext;
  int len = strlen(contents.c_str())+1;

  plaintext = (char *)aes_decrypt(de, (unsigned char *)contents.c_str(), &len);
  printf("%s", plaintext);


  free(plaintext);
  EVP_CIPHER_CTX_cleanup(en);
  EVP_CIPHER_CTX_cleanup(de);
}

以及解密函数:

unsigned char *aes_decrypt(EVP_CIPHER_CTX *e, unsigned char *ciphertext, int *len)
{
  int p_len = *len, f_len = 0;
  unsigned char *plaintext = (unsigned char *)calloc(sizeof(char*), p_len);

  EVP_DecryptInit_ex(e, NULL, NULL, NULL, NULL);
  EVP_DecryptUpdate(e, plaintext, &p_len, ciphertext, *len);
  EVP_DecryptFinal_ex(e, plaintext+p_len, &f_len);

  *len = p_len + f_len;
  return plaintext;
}

已解决:我必须删除编码器 PKCS#7 Padding 添加的 PKCS#7 填充

【问题讨论】:

  • malloc plaintext 但你永远不会将字节清零,所以我怀疑最后一个字符是随机字符或 null-terminator.. 使用 calloc 或在 @ 上执行 memset 987654330@ 就在malloc 电话之后,看看它是否有帮助?另外,为什么不使用new 运算符而不是malloc,毕竟这是C++?也许您还需要为数据和解密数据设置不同的长度?也许 malloc 需要是 len+1 但解密的参数不需要是..
  • @Brandon 我用 calloc 修改了上面的代码,但没有任何变化......最后一个字节是'0x01'......
  • 数据使用PKCS#7填充,解密后需要剥离
  • @yachoor 你能解释一下怎么做吗?
  • 检查最后一个字节并在最后删除/忽略那么多字节。填充是 x 字节,值为 x,其中 x 介于 1 和 8 之间。

标签: c++ encryption openssl


【解决方案1】:

输入长度不正确 - strlen(contents.c_str()) + 1 将返回长度,包括不应包含的额外空字节,因为它不是加密数据的一部分,或者返回加密数据中第一个空字节的数据长度(如果有) .您应该改用contents.size()。 这会导致EVP_DecryptUpdate 解密所有数据,包括最后一个带有填充的块,并期望更多数据和EVP_DecryptFinal_ex 在那之后失败。如果长度正确,最后一个块的填充将按预期剥离。

输出缓冲区长度也存在问题 - 它是 sizeof(char*) * p_len 而不是 sizeof(char) * (p_len + EVP_CIPHER_block_size(EVP_aes_256_cbc()))EVP_DecryptUpdate 要求输出缓冲区足够大以容纳输入长度 + 密码块大小。

您还应确保仅在 plaintext 缓冲区中使用 len 数据 - printf 将输出数据直到空字节,这可能不包含在解密数据中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-12
    • 2013-08-11
    • 1970-01-01
    • 2013-01-07
    • 1970-01-01
    • 1970-01-01
    • 2020-01-20
    • 2021-12-20
    相关资源
    最近更新 更多