Шифрование и расшифровка строки с помощью 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 больше не требуется ни для чего, кроме обратной совместимости.