C EVP加密核心转储

C EVP加密核心转储,c,encryption,openssl,C,Encryption,Openssl,我正在尝试解密使用EVP中的AES\u 128\u cbc()加密的密码文本,密码文本存在于名为task3.bin的文件中。我正在尝试进行模拟解密试验,这意味着解密不是使用正确的密钥或iv,而是使用有效长度 这两个函数是从EVP复制和粘贴的,但作为解密方法,EVP_aes_256_cbc()已更改为EVP_aes_128_cbc() void handleErrors(void) { ERR_print_errors_fp(stderr); abort(); } int decrypt

我正在尝试解密使用
EVP
中的
AES\u 128\u cbc()
加密的密码文本,密码文本存在于名为
task3.bin
的文件中。我正在尝试进行模拟解密试验,这意味着解密不是使用正确的
密钥
iv
,而是使用有效长度

这两个函数是从EVP复制和粘贴的,但作为解密方法,
EVP_aes_256_cbc()
已更改为
EVP_aes_128_cbc()

void handleErrors(void) {
  ERR_print_errors_fp(stderr);
  abort();
}

int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,unsigned char *iv, unsigned char *plaintext) {
  EVP_CIPHER_CTX *ctx;

  int len;

  int plaintext_len;

  /* Create and initialise the context */
  if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

  /* Initialise the decryption operation. (changed 256 to 128 HERE!!!)*/
  if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv))
    handleErrors();

  /* Provide the message to be decrypted, and obtain the plaintext output.
   * EVP_DecryptUpdate can be called multiple times if necessary
   */
  if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
    handleErrors();
  plaintext_len = len;

  /* Finalise the decryption. Further plaintext bytes may be written at
   * this stage.
   */
  if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors();
  plaintext_len += len;

  /* Clean up */
  EVP_CIPHER_CTX_free(ctx);

  return plaintext_len;
}
这是我的
main
函数,它正在调用
decrypt

int main(void) {
  FILE *f;
  long lSize;
  char *buffer;

  char *ciphertext;
  unsigned char *iv;
  unsigned char *key;

  unsigned char decryptedtext[128];
  int decryptedtext_len;

  // read ciphertext
  f = fopen("task3.bin", "rb");
  fseek( f , 0L , SEEK_END);
  lSize = ftell( f );
  rewind( f );
  ciphertext = calloc( 1, lSize+1 );
  fread(ciphertext , lSize, 1 , f);
  fclose(f);

  // testing key and iv
  key = (unsigned char *)"0123456789012345";
  iv = (unsigned char *)"0000000000000000";

  // decrypt!
  decryptedtext_len = decrypt(ciphertext, strlen((char *)ciphertext), key, iv, decryptedtext);

  return 0;
}
我得到了错误
139864800151232:error:06065064:lib(6):func(101):reason(100):evp_enc.c:529:
中止(内核转储)
,我花了数小时查看它,但没有取得多大成功。任何精通OpenSSL的人,请提供帮助



错误来自
EVP\u decrypt final\u ex
,最后一次
EVP
调用
decrypt
。我只能假设某些长度分配不正确。

如果您解密使用PKCS加密的数据#7填充(通常情况下),使用不正确的密钥解密将在大多数情况下导致填充错误

由于填充在最后一个块中,因此在
EVP\u DecryptFinal
调用中会对其进行检查,以便所有内容都有意义

根据加密算法、模式和填充量等因素,模拟解密很难实现


注意:OpenSSL EVP文档声明:“OpenSSL默认使用PKCS填充”,这是一个借口,因为它不声明PKCS#5或PKCS#7。我必须假设PKCS#7适用于AES。

任何地方都没有错误检查-您是否至少使用了调试器(或printf)来查看它在崩溃之前能走多远?是的。我已经更新了我的问题@john3136在
EVP\u decryptofinal
调用中检查填充,请参阅更新的答案。AES或其他现代算法的密文本质上是随机字节值,可以包括0 aka NUL,因此,使用
strlen
通常会给出错误的长度,即使后面有一个0,正如您通过
calloc
-ing(从而归零)一个额外的字节所保证的那样。在您的示例中,使用读取的长度
lSize
EVP\u Encrypt/Decrypt/Cipher*
EVP\u Cipher\u CTX.*
手册页的注释部分说,“PKCS填充通过添加n个值为n的填充字节来工作,以使加密数据的总长度为块大小的倍数。填充总是添加[偶数]如果数据已经是块大小的倍数……”这无疑是PKCS7,即使它没有使用该标签(我同意它应该使用)。