如何解决" EVP_DecryptFInal_ex:解密错误"在文件解密期间

时间:2015-12-16 05:30:22

标签: c encryption openssl

我有以下查询。请问任何人请建议我解决。

我是第一次加密和解密文件。

我使用以下命令通过命令提示符加密文件:

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 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] = '\0';
                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;
}

谢谢。

5 个答案:

答案 0 :(得分:8)

我认为使用命令行和使用程序解密的密钥和IV不相同。

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

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

在我的建议中,最好使用“-K”和“-iv”选项在加密期间明确指定密钥和IV,并使用相同的方法进行解密。如果需要使用“-k”,则使用“-p”选项打印密钥,使用iv进行加密,并在解密程序中使用相同的密码。

可以在https://www.openssl.org/docs/manmaster/apps/enc.html

获取更多详情

答案 1 :(得分:5)

错误: “错误的加密/解密” “ gitencrypt_smudge:失败:openssl错误解密文件”

openssl会抛出各种错误字符串,具体取决于各自的版本和方案。以下是在与openssl相关的情况下使用的清单:

  1. 理想情况下,openssl只能使用相同的密钥(+盐)和enc算法进行加密/解密。
  2. 确保openssl版本(用于加密/解密)兼容。例如。 openssl中使用的哈希在版本1.1.0中从MD5更改为SHA256。这将产生与相同密码不同的密钥。 固定: 在1.1.0中添加“ -md md5”以解密较低版本的数据,并且 在较低版本中添加“ -md sha256”以从1.1.0解密数据

  3. 确保您的计算机中安装了单个openssl版本。如果同时安装了多个版本(在我的机器上,这些版本已安装:-'LibreSSL 2.6.5'和'openssl 1.1.1d'),请确保PATH变量中仅出现所需的版本。

答案 2 :(得分:4)

我在使用openssl命令行界面时遇到了类似的错误回复,同时使用了正确的二进制密钥(-K)。选项&#34; -nopad&#34;解决了这个问题:

产生错误的示例:

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

结果:

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 "\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

结果:

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

答案 3 :(得分:1)

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

在使用EVP_CIPHER *时,默认情况下启用填充。要明确禁用,我们需要这样做

EVP_CIPHER_CTX_set_padding(context, 0);

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

答案 4 :(得分:0)

当您指定不正确的解密密码时也会出现此消息(是的,跛脚,但从错误消息中实现这一点并不是很明显,是吗?)。

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

最后,经过10分钟的悲伤,再加上阅读这个问题/答案,我记得密码不同,一切正常,密码正确。