web-dev-qa-db-fra.com

Comment résoudre "EVP_DecryptFInal_ex: Déchiffrement incorrect" lors du déchiffrement de fichier

J'ai la requête suivante. Quelqu'un pourrait-il me suggérer une solution?.

Je travaille sur le cryptage et le décryptage de fichier pour la première fois.

J'ai crypté le fichier par l'invite de commande en utilisant la commande:

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

Je dois le déchiffrer par programme. J'ai donc écrit le programme pour cela, mais l'erreur suivante est générée:

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

Le programme ci-dessous prend en entrée le chemin du répertoire, recherche le fichier crypté ".enc" et tente de le décrypter dans le tampon.

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

Je vous remercie.

40
Sai

Ce message digital envelope routines: EVP_DecryptFInal_ex: bad decrypt peut également se produire lorsque vous chiffrez et déchiffrez avec une version incompatible d’openssl.

Le problème que je rencontrais était que je chiffrais sous Windows, qui possédait la version 1.1.0, puis déchiffrait un système générique Linux, qui possédait 1.0.2g.

Ce n'est pas un message d'erreur très utile!


Solution de travail:

Une solution possible de @AndrewSavinykh qui a fonctionné pour beaucoup (voir les commentaires):

Le résumé par défaut a changé entre ces versions de md5 à sha256. On peut spécifier le résumé par défaut sur la ligne de commande sous la forme -md sha256 ou -md md5 respectivement

92
Sean Dawson

Je pense que la clé et l'IV utilisés pour le chiffrement à l'aide de la ligne de commande et le déchiffrement à l'aide de votre programme ne sont pas les mêmes.

Veuillez noter que lorsque vous utilisez le "-k" (différent de "-K"), l’entrée donnée est considérée comme un mot de passe à partir duquel la clé est dérivée. Généralement, dans ce cas, l’option "-iv" n’est pas nécessaire, car la clé et le mot de passe seront dérivés de la saisie fournie avec l’option "-k".

Votre question ne dit pas clairement comment vous vous assurez que la clé et le vecteur IV sont identiques entre le cryptage et le décryptage.

Dans ma suggestion, il vaut mieux utiliser les options "-K" et "-iv" pour spécifier explicitement la clé et le vecteur IV pendant le chiffrement et les utiliser pour le déchiffrement. Si vous devez utiliser "-k", utilisez l'option "-p" pour imprimer la clé et le périphérique iv utilisés pour le cryptage et utilisez-les de la même manière dans votre programme de décryptage.

Plus de détails peuvent être obtenus à https://www.openssl.org/docs/manmaster/apps/enc.html

9
Jay

J'ai rencontré une réponse d'erreur similaire lors de l'utilisation de l'interface de ligne de commande openssl, tout en ayant la clé binaire correcte (-K). L'option "-nopad" a résolu le problème:

Exemple générant l'erreur:

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

Résultat:

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

Exemple avec résultat correct:

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

Résultat:

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

Ce message peut également apparaître lorsque vous spécifiez le mot de passe de déchiffrement incorrect (ouais, boiteux, mais pas tout à fait évident de s'en rendre compte à partir du message d'erreur, hein?).

J'utilisais la ligne de commande pour déchiffrer la récente sauvegarde de la base de données de mon outil auxiliaire et j'ai soudainement fait face à ce problème.

Enfin, après 10 minutes de deuil et la lecture de cette question/réponses, je me suis rappelé que le mot de passe était différent et que tout fonctionnait parfaitement avec le mot de passe correct.

0
RAM237