2014-06-27 15 views
6

Sto provando a criptare e decrittografare una stringa con C++ openssl e aes cbc.Cifra e decrittografa la stringa con C++, Openssl e aes

La cosa strana di questo è, su un pc funziona, e sull'altro pc no. Lì ho solo 3/4 della stringa originale, quindi il finale è sbagliato.

L'altra cosa strana è che quando aggiungo una DLL chiamata "libeay32.dll" alla directory del file exe sul secondo pc, funziona, ma non sul primo pc.

In sintesi, il primo pc funziona solo senza dll, il secondo pc funziona solo con dll.

La mia domanda è, questo codice può essere migliorato e perché questa DLL è necessaria su un computer ma non sull'altro.

Ecco quello che ho già scritto:

KEY e IV sono definisce: funzione

#define KEY "abc" 
#define Iv "abc" 

crittografia: funzione

string aes_encrypt(string _InStr) 
{ 
    string EncKey, 
      EncIV; 

    AES_KEY enc_key; 

    unsigned char * aes_key = (unsigned char *) malloc (sizeof(unsigned char) * (32)), 
        * iv_enc = (unsigned char *) malloc (sizeof(unsigned char) * AES_BLOCK_SIZE), 
        * aes_input = (unsigned char *) malloc (sizeof(unsigned char) * _InStr.size()), 
        * enc_out = (unsigned char *) malloc (sizeof(unsigned char) * ((_InStr.size() + AES_BLOCK_SIZE)/AES_BLOCK_SIZE) * AES_BLOCK_SIZE); 



    memcpy ((char *) aes_input, _InStr.c_str(), _InStr.size()); 

    memset (aes_key, 0, 32); 

    EncKey = KEY; 
    EncIV = Iv; 

    for (int i = 0; i < 50; i++) 
     EncKey = md5 (EncKey.c_str()); 


    for (int i = 0; i < 305; i++) 
     EncIV = md5 (EncIV.c_str()); 

    EncIV.erase (16); 

    memcpy (aes_key, EncKey.c_str(), 32); 
    memcpy (iv_enc, EncIV.c_str (), 16); 


    AES_set_encrypt_key (aes_key, 128, &enc_key); 
    AES_cbc_encrypt  (aes_input, enc_out, _InStr.size(), &enc_key, iv_enc, AES_ENCRYPT); 


    free (aes_key); 
    free (aes_input); 
    free (iv_enc); 

    aes_key  = NULL; 
    aes_input = NULL; 
    iv_enc  = NULL; 

    return string ((char *) enc_out); 

} 

decrittografia:

string aes_decrypt (string _InStr) 
{ 
    string EncKey, 
      EncIV; 

    AES_KEY dec_key; 

    unsigned char * aes_key = (unsigned char *) malloc (sizeof(unsigned char) * (32)), 
        * iv_dec = (unsigned char *) malloc (sizeof(unsigned char) * AES_BLOCK_SIZE), 
        * enc_out = (unsigned char *) malloc (sizeof(unsigned char) * _InStr.size()), 
        * dec_out = (unsigned char *) malloc (sizeof(unsigned char) * _InStr.size()); 


    memcpy (enc_out, _InStr.c_str(), _InStr.size()); 

    memset (aes_key, 0, 32); 

    EncKey = KEY; 
    EncIV = Iv; 

    for (int i = 0; i < 50; i++) 
     EncKey = md5 (EncKey.c_str()); 

    for (int i = 0; i < 305; i++) 
     EncIV = md5 (EncIV.c_str()); 

    EncIV.erase (16); 

    memcpy (aes_key, EncKey.c_str(), 32); 
    memcpy (iv_dec, EncIV.c_str (), 16); 

    AES_set_decrypt_key(aes_key, 128, &dec_key); 
    AES_cbc_encrypt(enc_out, dec_out, _InStr.size(), &dec_key, iv_dec, AES_DECRYPT); 

    free (aes_key); 
    free (iv_dec); 
    free (enc_out); 

    aes_key  = NULL; 
    iv_dec  = NULL; 
    enc_out  = NULL; 

    return string ((char *) dec_out); 

} 

uscita di primo pc:

ingresso:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

criptata:

S^Wo◄┘ "â ▼ ~ ¼ \ é╣ $ ╨L╡`aC ♠ · ñZ½h╠∟≥ä ° ╪╥ = αp╙IφoCYN ° ☺§) ↨XwY + ☼▀╤M▓ ÷ √NÉk┼≡ < ÷ ák◄Ä┬ ∙ z ¼üt @ ¥ ≈╟ ∙ ¶√Ñù ° 7å²²²²½½½½½½½½ε ■ ε ■

decriptati:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

uscita del secondo pc :

Ingresso:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Encrypted:????

S^Wo + "A ~ ¼ \ é| $ ðLÁ`aC · ñZ½h| = ä ° Ie = ÓpËIÝoCYN °? §)? XwY + ¤¯ÐM| ÷ ¹NÉk + < ák? Ä- ÷ ðz + BñFb YÙ]?s

decriptati:?

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Wi »H + ²²²²||||||w $ O O:?

+0

Se un exe richiede una dll, prima cercherà nella cartella corrente e se non la trova poi cercherà in varie cartelle di sistema fino a quando non la troverà (o bombarderà se non lo fa). Potrebbe essere che il secondo pc abbia una copia di una versione vecchia/buggy di questa dll da qualche parte in una cartella di sistema in modo da prenderne nota? Una volta che hai messo quello giusto nella cartella del tuo exe, allora funzionerebbe correttamente. Ad ogni modo, solo una supposizione, ma vale la pena cercare questa DLL sull'intero drive C per assicurarsi che non ci sia una copia più vecchia in agguato da qualche parte. – djikay

+0

Onestamente, con la possibile eccezione del * input iniziale * a 'aes_encrypt()', e * output finale * di 'aes_decrypt',' std :: string' non dovrebbe essere * ovunque * in questo. E se ti ritrovi c-ctyle-casting in C++, le probabilità sono che stai facendo qualcosa di sbagliato. Entrambe le funzioni perdono memoria, btw. – WhozCraig

+0

Dovresti * non * usare 'AES_encrypt' e amici.Dovresti usare le funzioni 'EVP_ *'. Le funzioni 'EVP_ *' usano l'hardware, come AES-NI (se disponibile). Vedi [Codifica simmetrica EVP e decrittografia] (https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption) sul wiki OpenSSL. In effetti, probabilmente dovresti utilizzare 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

risposta

3

questi due sono rotto di sicuro .. ..

for (int i = 0; i < 50; i++) 
    EncKey = md5 (EncKey.c_str()); 

for (int i = 0; i < 305; i++) 
    EncIV = md5 (EncIV.c_str()); 

Si avrebbe bisogno di qualcosa di simile a:

EncKey = string(md5 (EncKey.c_str()), 16); 

In caso contrario, la stringa prodotta da MD5 viene troncato al primo 0x00 i string incontri costruttore.


Questi sono problemi:

memcpy (aes_key, EncKey.c_str(), 32); 
memcpy (iv_enc, EncIV.c_str (), 16); 

Al massimo MD5 produce una stringa di 16 byte. Non è possibile estrarre 32 byte dalla stringa da 16 byte in EncKey.

E si è in difficoltà se EncKey o EncIV ha un valore null incorporato. Se ne ha uno, allora quella stringa non è nemmeno 16 byte.


E come Jim ha sottolineato nel commento qui sotto, questo è anche problemi:

return string ((char *) dec_out); 

Ha bisogno di essere simile a:

string aes_encrypt(string _InStr) 
{ 
    ... 
    return string ((char *) dec_out, <some size>); 
} 

e l'uso di AES_cbc_encrypt sembra sbagliato. È necessario attenersi all'interfaccia EVP_*. Per un esempio, vedere EVP Symmetric Encryption and Decryption nella wiki di OpenSSL.

Meglio, utilizzare una modalità di crittografia autenticata come GCM in modo da ottenere anche garanzie di autenticità/integrità. Per un esempio, vedere EVP Authenticated Encryption and Decryption nella wiki di OpenSSL.


Quindi, utilizzare un hash più grande come SHA256 o SHA512. MD5 non è più richiesto per qualcosa di diverso dalla retrocompatibilità.

+1

Anche questo è un problema: return string ((char *) enc_out); - enc_out non ha terminazione null e, potrebbe accidentalmente essere terminato da null byte nulli. –