2015-12-16 9 views
8

Ho la seguente query. Qualcuno può suggerirmi una soluzione.Come risolvere "EVP_DecryptFInal_ex: decrypt errato" durante la decrittografia del file

Sto lavorando alla crittografia e alla decodifica del file per la prima volta.

ho criptato file tramite prompt dei comandi utilizzando il comando:

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

devo decifrare a livello di codice. Così ho scritto il programma per esso, ma si sta gettando il seguente errore:

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

Il programma qui di seguito prende in ingresso come percorso della directory e la ricerca di file crittografato ".enc" e cercare di decifrare leggere nel buffer.

Codice:

#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; 
} 

Grazie.

+0

La modalità CBC fornisce solo riservatezza e di solito è necessario aggiungere un MAC per utilizzare la modalità CBC in modo sicuro. Probabilmente dovresti usare la crittografia autenticata perché fornisce * sia * riservatezza e autenticità. Vedi [Crittografia e decodifica autenticata EVP] (https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption) sul wiki OpenSSL. – jww

+0

Semplifica il tuo codice. Elimina tutte le letture del file system. Cripta un file e prova a decrittografarlo. Il debug è molto più facile allora. – adlag

+0

Grazie per la risposta. Intendevi quell'uso delle chiamate di sistema dal programma? – Sai

risposta

4

Penso che la chiave e IV utilizzati per la crittografia utilizzando la riga di comando e la decrittografia utilizzando il programma non sono gli stessi.

Si noti che quando si utilizza il "-k" (diverso da "-K"), l'input fornito viene considerato come una password da cui viene derivata la chiave. Generalmente, in questo caso, non è necessaria l'opzione "-iv" poiché sia ​​la chiave che la password saranno derivate dall'input fornito con l'opzione "-k".

Non è chiaro dalla domanda, come si sta garantendo che la chiave e IV sono uguali tra crittografia e decrittografia.

Nel mio suggerimento, utilizzare meglio l'opzione "-K" e "-iv" per specificare esplicitamente la chiave e IV durante la crittografia e utilizzare lo stesso per la decrittografia. Se è necessario utilizzare "-k", utilizzare l'opzione "-p" per stampare la chiave e iv utilizzati per la crittografia e utilizzare lo stesso nel programma di decrittografia.

Maggiori dettagli sono disponibili presso https://www.openssl.org/docs/manmaster/apps/enc.html

+0

Grazie Jay. si! avevi ragione non stava ottenendo la chiave corretta e il valore iv. ha provato un semplice programma con il tuo suggerimento (usando le opzioni -K, -iv e -p) e ha funzionato. Ho un'altra domanda qui. ho generato una chiave privata di utilizzare questo comando ** OpenSSL genrsa -out key.pem 2048 ** ho crittografato un file con questa chiave, come di seguito ** openssl enc -AES-256-CBC rand_bytes -in .c -out rand_bytes.enc -kfile key.pem ** Ora la domanda è, Devo leggere la stessa chiave per decodificare il file usando le API OpenSSL EVP. Potresti suggerirmi come si può ottenere. Grazie. – Sai

+0

@Sai: se questo risponde alla tua domanda specifica, contrassegnala come risposta per questa discussione. L'altra risposta è utile per una ragione diversa, ma contrassegnandola come risposta al problema specifico, chiarisce che questa discussione non è un duplicato di quella collegata all'altra risposta. –

17

Questo messaggio digital envelope routines: EVP_DecryptFInal_ex: bad decrypt può verificarsi anche quando si crittografare e decrittografare con una versioni incompatibili di OpenSSL.

Il problema che stavo facendo era che stavo criptando su Windows che aveva la versione 1.1.0 e quindi decodifica su un sistema Linux generico con 1.0.2g.

Non è un messaggio di errore molto utile!

+15

Vedere qui: https://stackoverflow.com/a/39641378/284111 Il digest predefinito è cambiato tra quelle versioni da md5 a sha256. Si può specificare il digest di default sulla riga di comando come '-md sha256' o' -md md5' rispettivamente –

+1

@AndrewSavinykh Grazie! L'aggiunta di '-md md5' ha risolto il problema per me. – mauvm