C语言 如何解决文件解密过程中的“EVP_DecryptFInal_ex:错误解密”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34304570/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to resolve the "EVP_DecryptFInal_ex: bad decrypt" during file decryption
提问by Sai
I have the following query.Could any one please suggest me a solution.
我有以下查询。有人可以给我建议一个解决方案。
I'm working on encryption and decryption of file for first time.
我是第一次研究文件的加密和解密。
I have encrypted file through command prompt using the command:
我使用以下命令通过命令提示符加密文件:
openssl enc -aes-256-cbc -in file.txt -out file.enc -k "key value" -iv "iv value"
I have to decrypt it programmatically. So I have written the program for it, but it is throwing the following error:
我必须以编程方式解密它。所以我为它编写了程序,但它抛出以下错误:
./exe_file enc_file_directory
...
error: 06065064: digital envelope routines: EVP_DecryptFInal_ex: bad decrypt: evp_enc.c
The program below takes input as directory path and search for encrypted file ".enc" and try to decrypt it read into buffer.
下面的程序将输入作为目录路径并搜索加密文件“.enc”并尝试将其解密读入缓冲区。
Code:
代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/conf.h>
#include <libxml/globals.h>
void handleErrors(char *msg)
{
{
ERR_print_errors_fp(stderr);
printf("%s", msg);
abort();
}
}
void freeMemory(char *mem)
{
if (NULL != mem)
{
free(mem);
mem = NULL;
}
}
/* Function to decrypt the XML files */
int decryptXML(unsigned char *indata, unsigned char *outdata, int fsize)
{
int outlen1 = 0, outlen2 = 0;
unsigned char iv[] = "b63e541bc9ece19a1339df4f8720dcc3";
unsigned char ckey[] = "70bbc518c57acca2c2001694648c40ddaf19e3b4fe1376ad656de8887a0a5ec2" ;
if (NULL == indata)
{
printf ("input data is empty\n");
return 0;
}
if (0 >= fsize)
{
printf ("file size is zero\n");
return 0;
}
outdata = (char *) malloc (sizeof (char) * fsize * 2);
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
if (! EVP_DecryptInit_ex (&ctx, EVP_aes_256_cbc(), NULL, ckey, iv))
{
EVP_CIPHER_CTX_cleanup(&ctx);
handleErrors("DInit");
}
if (! EVP_DecryptUpdate (&ctx, outdata, &outlen1, indata, fsize))
{
EVP_CIPHER_CTX_cleanup(&ctx);
handleErrors("DUpdate");
}
if (! EVP_DecryptFinal_ex (&ctx, outdata + outlen1, &outlen2))
{
EVP_CIPHER_CTX_cleanup(&ctx);
handleErrors("DFinal");
}
EVP_CIPHER_CTX_cleanup(&ctx);
return outlen1+outlen2;
}
int isDirectory(char *path)
{
DIR *dir = NULL;
FILE *fin = NULL, *fout = NULL;
int enc_len = 0, dec_len = 0, fsize = 0, ksize = 0;
unsigned char *indata = NULL, *outdata = NULL;
char buff[BUFFER_SIZE], file_path[BUFFER_SIZE], cur_dir[BUFFER_SIZE];
struct dirent *in_dir;
struct stat s;
if (NULL == (dir = opendir(path)))
{
printf ("ERROR: Failed to open the directory %s\n", path);
perror("cannot open.");
exit(1);
}
while (NULL != (in_dir = readdir(dir)))
{
if (!strcmp (in_dir->d_name, ".") || !strcmp(in_dir->d_name, ".."))
continue;
sprintf (buff, "%s/%s", path, in_dir->d_name);
if (-1 == stat(buff, &s))
{
perror("stat");
exit(1);
}
if (S_ISDIR(s.st_mode))
{
isDirectory(buff);
}
else
{
strcpy(file_path, buff);
if (strstr(file_path, ".enc"))
{
/* File to be decrypted */
fout = fopen(file_path,"rb");
fseek (fout, 0L, SEEK_END);
fsize = ftell(fout);
fseek (fout, 0L, SEEK_SET);
indata = (char*)malloc(fsize);
fread (indata, sizeof(char), fsize, fout);
if (NULL == fout)
{
perror("Cannot open enc file: ");
return 1;
}
dec_len = decryptXML (indata, outdata, fsize);
outdata[dec_len] = 'echo -ne "\x32\xc8\xde\x5c\x68\x19\x7e\x53\xa5\x75\xe1\x76\x1d\x20\x16\xb2\x72\xd8\x40\x87\x25\xb3\x71\x21\x89\xf6\xca\x46\x9f\xd0\x0d\x08\x65\x49\x23\x30\x1f\xe0\x38\x48\x70\xdb\x3b\xa8\x56\xb5\x4a\xc6\x09\x9e\x6c\x31\xce\x60\xee\xa2\x58\x72\xf6\xb5\x74\xa8\x9d\x0c" | openssl aes-128-cbc -d -K 31323334353637383930313233343536 -iv 79169625096006022424242424242424 | od -t x1
';
printf ("%s\n", outdata);
fclose (fin);
fclose (fout);
}
}
}
closedir(dir);
freeMemory(outdata);
freeMemory(indata);
return 1;
}
int main(int argc, char *argv[])
{
int result;
if (argc != 2)
{
printf ("Usage: <executable> path_of_the_files\n");
return -1;
}
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
/* Checking for the directory existance */
result = isDirectory(argv[1]);
EVP_cleanup();
ERR_free_strings();
if (0 == result)
return 1;
else
return 0;
}
Thank you.
谢谢你。
回答by Sean Dawson
This message digital envelope routines: EVP_DecryptFInal_ex: bad decryptcan also occur when you encrypt and decrypt with an incompatible versions of openssl.
digital envelope routines: EVP_DecryptFInal_ex: bad decrypt当您使用不兼容的 openssl 版本进行加密和解密时,也会出现此消息。
The issue I was having was that I was encrypting on Windows which had version 1.1.0 and then decrypting on a generic Linux system which had 1.0.2g.
我遇到的问题是我在具有 1.1.0 版的 Windows 上加密,然后在具有 1.0.2g 的通用 Linux 系统上解密。
It is not a very helpful error message!
这不是一个非常有用的错误消息!
Working solution:
工作解决方案:
A possible solution from @AndrewSavinykh that worked for many (see the comments):
@AndrewSavinykh 的一个可能的解决方案,适用于许多人(见评论):
Default digest has changed between those versions from md5 to sha256. One can specify the default digest on the command line as
-md sha256or-md md5respectively
这些版本之间的默认摘要已从 md5 更改为 sha256。可以在命令行上指定默认摘要为
-md sha256或-md md5分别
回答by Jay
I think the Key and IV used for encryption using command line and decryption using your program are not same.
我认为用于使用命令行加密和使用您的程序解密的密钥和 IV 是不一样的。
Please note that when you use the "-k" (different from "-K"), the input given is considered as a password from which the key is derived. Generally in this case, there is no need for the "-iv" option as both key and password will be derived from the input given with "-k" option.
请注意,当您使用“-k”(与“-K”不同)时,给定的输入被视为派生密钥的密码。通常在这种情况下,不需要“-iv”选项,因为密钥和密码都将从“-k”选项给出的输入中派生出来。
It is not clear from your question, how you are ensuring that the Key and IV are same between encryption and decryption.
从您的问题中不清楚您如何确保加密和解密之间的密钥和 IV 相同。
In my suggestion, better use "-K" and "-iv" option to explicitly specify the Key and IV during encryption and use the same for decryption. If you need to use "-k", then use the "-p" option to print the key and iv used for encryption and use the same in your decryption program.
在我的建议中,最好使用“-K”和“-iv”选项在加密过程中明确指定密钥和 IV,并在解密时使用它们。如果您需要使用“-k”,则使用“-p”选项打印用于加密的密钥和 iv,并在您的解密程序中使用它们。
More details can be obtained at https://www.openssl.org/docs/manmaster/apps/enc.html
可以在https://www.openssl.org/docs/manmaster/apps/enc.html获得更多详细信息
回答by Tobias Braune
I experienced a similar error reply while using the openssl command line interface, while having the correct binary key (-K). The option "-nopad" resolved the issue:
我在使用 openssl 命令行界面时遇到了类似的错误回复,同时具有正确的二进制密钥 (-K)。选项“-nopad”解决了这个问题:
Example generating the error:
生成错误的示例:
bad decrypt
140181876450560:error:06065064:digital envelope
routines:EVP_DecryptFinal_ex:bad decrypt:../crypto/evp/evp_enc.c:535:
0000000 2f 2f 07 02 54 0b 00 00 00 00 00 00 04 29 00 00
0000020 00 00 04 a9 ff 01 00 00 00 00 04 a9 ff 02 00 00
0000040 00 00 04 a9 ff 03 00 00 00 00 0d 79 0a 30 36 38
Result:
结果:
echo -ne "\x32\xc8\xde\x5c\x68\x19\x7e\x53\xa5\x75\xe1\x76\x1d\x20\x16\xb2\x72\xd8\x40\x87\x25\xb3\x71\x21\x89\xf6\xca\x46\x9f\xd0\x0d\x08\x65\x49\x23\x30\x1f\xe0\x38\x48\x70\xdb\x3b\xa8\x56\xb5\x4a\xc6\x09\x9e\x6c\x31\xce\x60\xee\xa2\x58\x72\xf6\xb5\x74\xa8\x9d\x0c" | openssl aes-128-cbc -d -K 31323334353637383930313233343536 -iv 79169625096006022424242424242424 -nopad | od -t x1
Example with correct result:
具有正确结果的示例:
0000000 2f 2f 07 02 54 0b 00 00 00 00 00 00 04 29 00 00
0000020 00 00 04 a9 ff 01 00 00 00 00 04 a9 ff 02 00 00
0000040 00 00 04 a9 ff 03 00 00 00 00 0d 79 0a 30 36 38
0000060 30 30 30 34 31 33 31 2f 2f 2f 2f 2f 2f 2f 2f 2f
0000100
Result:
结果:
EVP_CIPHER_CTX_set_padding(context, 0);
回答by Ankush
Errors: "Bad encrypt / decrypt" "gitencrypt_smudge: FAILURE: openssl error decrypting file"
错误:“加密/解密错误”“gitencrypt_smudge:失败:openssl 解密文件时出错”
There are various error strings that are thrown from openssl, depending on respective versions, and scenarios. Below is the checklist I use in case of openssl related issues:
openssl 会抛出各种错误字符串,具体取决于各自的版本和场景。以下是我在处理 openssl 相关问题时使用的清单:
- Ideally, openssl is able to encrypt/decrypt using same key (+ salt) & enc algo only.
Ensure that openssl versions (used to encrypt/decrypt), are compatible. For eg. the hash used in openssl changed at version 1.1.0 from MD5 to SHA256. This produces a different key from the same password. Fix: add "-md md5" in 1.1.0 to decrypt data from lower versions, and add "-md sha256 in lower versions to decrypt data from 1.1.0
Ensure that there is a single openssl version installed in your machine. In case there are multiple versions installed simultaneously (in my machine, these were installed :- 'LibreSSL 2.6.5' and 'openssl 1.1.1d'), make the sure that only the desired one appears in your PATH variable.
- 理想情况下,openssl 只能使用相同的密钥 (+ salt) 和 enc 算法进行加密/解密。
确保 openssl 版本(用于加密/解密)兼容。例如。openssl 中使用的哈希在 1.1.0 版中从 MD5 更改为 SHA256。这会根据相同的密码生成不同的密钥。修复:1.1.0加“-md md5”对低版本数据解密,低版本加“-md sha256”对1.1.0数据解密
确保您的机器上安装了一个 openssl 版本。如果同时安装了多个版本(在我的机器上,它们安装了:-“LibreSSL 2.6.5”和“openssl 1.1.1d”),请确保只有所需的版本出现在您的 PATH 变量中。
回答by RAM237
This message can also occur when you specify the incorrect decryption password(yeah, lame, but not quite obvious to realize this from the error message, huh?).
当您指定不正确的解密密码时也会出现此消息(是的,蹩脚,但从错误消息中意识到这一点并不是很明显,是吧?)。
I was using the command line to decrypt the recent DataBase backup for my auxiliary tool and suddenly faced this issue.
我正在使用命令行为我的辅助工具解密最近的数据库备份,突然遇到了这个问题。
Finally, after 10 mins of grief and plus reading through this question/answers I have remembered that the password is different and everything worked just fine with the correct password.
最后,经过 10 分钟的悲痛和阅读此问题/答案后,我记得密码不同,并且使用正确的密码一切正常。
回答by Digvijay Chougale
My case, the server was encrypting with padding disabled. But the client was trying to decrypt with the padding enabled.
我的情况是,服务器在禁用填充的情况下进行加密。但是客户端试图在启用填充的情况下解密。
While using EVP_CIPHER*, by default the padding is enabled. To disable explicitly we need to do
使用 EVP_CIPHER* 时,默认情况下启用填充。要明确禁用,我们需要做
##代码##So non matching padding options can be one reason.
因此,不匹配的填充选项可能是原因之一。

