c语言 - 如何在文件解密期间解决"EVP_DecryptFInal_ex: bad decrypt"



我有以下查询。谁能给我一个解决方案吗。

我第一次从事文件的加密和解密工作。

我已经通过命令提示符使用命令加密文件:

openssl enc -aes-256-cbc -in file.txt -out file.enc -k "key value" -iv "iv value"

我必须以编程方式解密它。所以我已经为它编写了程序,但它抛出了以下错误:

./exe_file enc_file_directory
...
error: 06065064: digital envelope routines: EVP_DecryptFInal_ex: bad decrypt: evp_enc.c

下面的程序将输入作为目录路径,搜索加密的文件".enc"并尝试解密读取到缓冲区中的文件。

代码:

#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 emptyn");
        return 0;
    }
    if (0 >= fsize)
    {
        printf ("file size is zeron");
        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 %sn", 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] = '';
                printf ("%sn", 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_filesn");
        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;
}

谢谢。

使用不兼容版本的openssl进行加密和解密时,也可能出现此消息digital envelope routines: EVP_DecryptFInal_ex: bad decrypt

我遇到的问题是,我在1.1.0版本的Windows上加密,然后在1.0.2g.的通用Linux系统上解密

这不是一个非常有用的错误消息!


工作解决方案:

@AndrewSavinykh的一个可能的解决方案对许多人都有效(见评论):

默认摘要在这些版本之间已从md5更改为sha256。可以在命令行上将默认摘要分别指定为-md sha256-md md5

我在使用openssl命令行接口时遇到了类似的错误回复,同时使用了正确的二进制密钥(-K)。选项"-nopad"解决了问题:

生成错误的示例:

echo -ne "x32xc8xdex5cx68x19x7ex53xa5x75xe1x76x1dx20x16xb2x72xd8x40x87x25xb3x71x21x89xf6xcax46x9fxd0x0dx08x65x49x23x30x1fxe0x38x48x70xdbx3bxa8x56xb5x4axc6x09x9ex6cx31xcex60xeexa2x58x72xf6xb5x74xa8x9dx0c" | openssl aes-128-cbc -d -K 31323334353637383930313233343536 -iv 79169625096006022424242424242424 | od -t x1

结果:

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

结果正确的示例:

echo -ne "x32xc8xdex5cx68x19x7ex53xa5x75xe1x76x1dx20x16xb2x72xd8x40x87x25xb3x71x21x89xf6xcax46x9fxd0x0dx08x65x49x23x30x1fxe0x38x48x70xdbx3bxa8x56xb5x4axc6x09x9ex6cx31xcex60xeexa2x58x72xf6xb5x74xa8x9dx0c" | openssl aes-128-cbc -d -K 31323334353637383930313233343536 -iv 79169625096006022424242424242424 -nopad | od -t x1

结果:

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

我认为使用命令行加密和使用程序解密所用的Key和IV是不一样的。

请注意,当您使用"-k"(不同于"-k")时,给定的输入被视为密钥的派生密码。通常在这种情况下,不需要"-iv"选项,因为密钥和密码都将从"-k"选项提供的输入中派生出来。

从你的问题中还不清楚,你是如何确保密钥和IV在加密和解密之间是相同的。

在我的建议中,最好使用"-K"one_answers"-iv"选项在加密过程中显式指定Key和iv,并将其用于解密。如果需要使用"-k",则使用"-p"选项打印用于加密的密钥和iv,并在解密程序中使用相同的密钥和iv。

更多详细信息,请访问https://www.openssl.org/docs/manmaster/apps/enc.html

错误:"错误的加密/解密"gitencrypt_smudge:失败:解密文件时出现openssl错误"

根据各自的版本和场景,openssl会抛出各种错误字符串。以下是我在openssl相关问题中使用的检查表:

  1. 理想情况下,openssl能够使用相同的密钥(+salt)&仅限enc-algo
  2. 确保openssl版本(用于加密/解密)是兼容的。例如,openssl中使用的哈希在1.1.0版本从MD5更改为SHA256。这将从相同的密码中生成不同的密钥。修复:在1.1.0中添加"-md-md5"以解密较低版本的数据,以及在较低版本中添加"-md-sha256以解密1.1.0 中的数据

  3. 请确保您的计算机中安装了一个openssl版本。如果同时安装了多个版本(在我的机器中,安装了以下版本:"LibreSSL 2.6.5"one_answers"openssl 1.1.1d"),请确保PATH变量中只显示所需的版本。

当您指定不正确的解密密码时,也可能出现此消息(是的,蹩脚,但从错误消息中不太明显,嗯?)。

我正在使用命令行为我的辅助工具解密最近的数据库备份,突然遇到了这个问题。

最后,经过10分钟的悲伤和阅读这些问题/答案,我想起了密码是不同的,使用正确的密码一切都很好。

您应该使用解密的私钥。例如:youprivatekey.decrypted.key。您可以运行此命令来解密您的私钥文件。

openssl rsa -in <encrypted_private.key> -out <decrypted_private.key>
Enter password:
Enter pass phrase for encrypted_private.key: <enter the password>
Wait:
writing RSA key
it's done...

在我的案例中,服务器在禁用填充的情况下进行加密。但是客户端试图在启用填充的情况下解密。

在使用EVP_CIPHER*时,默认情况下会启用填充。要明确禁用,我们需要进行

EVP_CIPHER_CTX_set_padding(context, 0);

因此,不匹配的填充选项可能是一个原因。

我在ECB模式下尝试用DES进行链加密-解密-加密时遇到了这个错误。关闭填充解决了问题。

最新更新