Расшифровка Openssl C AES с добавлением неожиданных символов

#c #encryption #openssl

#c #шифрование #openssl

Вопрос:

Я пытаюсь расшифровать на C файл, который был зашифрован с помощью команды Linux: openssl enc -aes-256-cbc -nosalt -K «E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855″ -iv » 5DF6E0E2761359D30A8275058E299FCC» -файл p -in.файл json -out.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(), amp;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, amp;p_len, ciphertext, *len);
  EVP_DecryptFinal_ex(e, plaintext p_len, amp;f_len);

  *len = p_len   f_len;
  return plaintext;
}
  

РЕШЕНО: мне пришлось удалить дополнение PKCS # 7, добавленное кодировщиком Дополнение PKCS # 7

Комментарии:

1.Вы malloc plaintext , но вы никогда не обнуляете байты, поэтому я подозреваю, что последний символ является случайным символом или null-terminator .. Либо используйте calloc , либо сделайте memset on plaintext сразу после malloc вызова и посмотрите, поможет ли это? Кроме того, почему бы вам не использовать new operator вместо malloc , в конце концов, это C ? Возможно, вам также необходимо иметь разную длину для данных и расшифрованных данных? Возможно, значение malloc должно быть len 1, но параметры для расшифровки не обязательно должны быть такими..

2. @Brandon Я модифицировал приведенный выше код с помощью calloc, но ничего не меняется… Последний байт равен ‘0x01’…

3. Данные дополняются с использованием заполнения PKCS # 7, которое необходимо удалить после расшифровки

4. @yachoor Можете ли вы объяснить мне, как это сделать?

5. Проверьте последний байт и удалите / проигнорируйте это количество байтов в конце. Заполнение — это x байт со значением x, где x находится между 1 и 8.

Ответ №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 требуется, чтобы выходной буфер был достаточно большим, чтобы вместить длину ввода размер блока шифрования.

Вы также должны убедиться, что используете только len данные в plaintext буфере — printf будут выводиться данные до нулевого байта, который может не быть включен в расшифрованные данные.