web-dev-qa-db-ja.com

ファイルの復号化中に「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 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;
}

ありがとうございました。

40
Sai

このメッセージdigital envelope routines: EVP_DecryptFInal_ex: bad decryptは、互換性のないバージョンのopensslで暗号化および復号化する場合にも発生する可能性があります。

私が抱えていた問題は、バージョン1.1.0のWindowsで暗号化してから、1.0.2gの汎用Linuxシステムで復号化することでした。

これは非常に役立つエラーメッセージではありません!


実用的なソリューション:

多くの人のために働いた@AndrewSavinykhからの可能な解決策(コメントを参照):

これらのバージョン間では、md5からsha256にデフォルトのダイジェストが変更されています。コマンドラインでデフォルトのダイジェストをそれぞれ-md sha256または-md md5として指定できます

92
Sean Dawson

コマンドラインを使用した暗号化とプログラムを使用した復号化に使用されるキーとIVは同じではないと思います。

「-k」(「-K」とは異なる)を使用する場合、指定された入力はキーの派生元のパスワードと見なされることに注意してください。通常、この場合、キーとパスワードの両方が「-k」オプションで指定された入力から導出されるため、「-iv」オプションは不要です。

暗号化と復号化の間でキーとIVが同じであることをどのように保証しているのかという質問からは明らかではありません。

私の提案では、「-K」と「-iv」オプションを使用して、暗号化中にキーとIVを明示的に指定し、同じものを復号化に使用することをお勧めします。 「-k」を使用する必要がある場合は、「-p」オプションを使用して、暗号化に使用されるキーとivを出力し、復号化プログラムで同じものを使用します。

詳細は https://www.openssl.org/docs/manmaster/apps/enc.html で入手できます。

9
Jay

Opensslコマンドラインインターフェイスを使用しているときに、正しいバイナリキー(-K)を使用しているときに、同様のエラー応答が発生しました。オプション「-nopad」は問題を解決しました:

エラーの生成例:

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
6
Tobias Braune

このメッセージは、不正な復号化パスワード(ええ、ラメですが、エラーメッセージからこれを理解するのは明らかではありません)を指定した場合にも発生する可能性があります。

コマンドラインを使用して、補助ツールの最近のデータベースバックアップを解読していましたが、突然この問題に直面しました。

最後に、10分間の悲しみに加えて、この質問/回答を読んだ後、パスワードが異なり、正しいパスワードですべてがうまく機能したことを思い出しました。

0
RAM237