Шифрование и расшифровка строки с помощью c++, Openssl и aes

Я пытаюсь зашифровать и расшифровать строку с помощью C++ openssl и aes cbc.

самое странное в этом, на одном ПК он работает, а на другом-нет. Там у меня есть только 3/4 исходной строки, поэтому окончание неверно.

другая странная вещь, когда я добавляю dll под названием " libeay32.dll " в каталог exe-файла на втором ПК, он работает, но не на первом ПК.

в резюме, первый ПК работает только без dll, второй ПК работает только с DLL.

мой вопрос в том, может ли этот код быть улучшен, и почему эта dll необходима на одном компьютере, но не на другом.

вот что я уже написал:

ключ и Iv определяются:

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

функции шифрования:

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);

}

расшифровка функции:

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);

}

выход первого ПК:

вход:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

зашифрованном виде:

С^соо◄┘"â▼~¼é╣$╨л╡`ас♠·ñZ½h╠∟≥ä°╪╥=АП╙IφoCYN°☺§)↨XwY+☼▀╤м▓÷√NÉk┼≡

расшифровать:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

выход второго ПК:

вход:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

зашифрованном виде:

S^Wo?+"?~¼É¦$ðLÁ'aC?* ñZ½h/?= ä°ÏÊ=ÓpËIÝoCYN°?§)?XwY+ð ÐM / ÷1NÉk +

расшифровать:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?WÎ " H+2222¦¦¦¦¦¦w$ö?ó:

1 ответов


эти два сломаны точно....

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

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

вам понадобится что-то вроде:

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

в противном случае строка, производимая MD5, усекается при первом 0x00 string встречает конструктор.


это беда:

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

в лучшем случае MD5 возвращает строку из 16 байт. Вы не можете вытащить 32 байта из 16-байтовой строки в EncKey.

и вы в беде, Если либо EncKey или EncIV имеет встроенный null. Если у любого из них есть один, то эта строка даже не 16 байт.


и, как отметил Джим в комментарии ниже, это также проблема:

return string ((char *) dec_out);

он должен быть похож на:

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

использование AES_cbc_encrypt выглядит неправильно. Вы должны придерживаться EVP_* интерфейс. Пример см. В разделе EVP симметричное шифрование и дешифрование на вики OpenSSL.

лучше использовать аутентифицированный режим шифрования, такой как GCM, поэтому вы также получаете гарантии подлинности/целостности. Пример см. В разделе EVP Аутентифицированное шифрование и дешифрование на вики OpenSSL.


наконец, используйте больший хэш, как SHA256 или SHA512. MD5 больше не требуется ни для чего, кроме обратной совместимости.