I'm trying to encrypt and decrypt a string with c++ openssl and aes cbc.
The weird thing about this is, on one pc it works, and on the other pc it doesn't. There i have only 3/4 of the original string, so the ending is wrong.
The other weird thing is, when i add a dll called "libeay32.dll" to the directory of the exe file on the second pc, it works, but not on the first pc.
In summary, first pc only works without dll, second pc works only with dll.
My question is, can this code be improved, and why this dll is needed on one computer but not on the other.
Here's what i've already written:
KEY and Iv are defines:
#define KEY "abc"
#define Iv "abc"
Encryption function:
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);
}
Decryption function:
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);
}
Output of first pc:
Input:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Encrypted:
S^Wo◄┘"â▼~¼\é╣$╨L╡`aC♠·ñZ½h╠∟≥ä°╪╥=αp╙IφoCYN°☺§)↨XwY+☼▀╤M▓÷√NÉk┼≡<ák◄Ä┬÷∙z ¼üt@¥≈╟∙¶√Ñù°7å²²²²½½½½½½½½ε■ε■
Decrypted:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Output of second pc:
Input:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Encrypted:
S^Wo?+"â?~¼\é¦$ðLÁ`aC?·ñZ½h¦?=ä°ÏÊ=ÓpËIÝoCYN°?§)?XwY+¤¯ÐM¦÷¹NÉk+<ák?Ä-÷¨zð+BñFb YÙ]?s
Decrypted:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?WλH+²²²²¦¦¦¦¦¦w$ö?ó:
These two are broken for sure....
for (int i = 0; i < 50; i++)
EncKey = md5 (EncKey.c_str ());
for (int i = 0; i < 305; i++)
EncIV = md5 (EncIV.c_str ());
You would need something like:
EncKey = string(md5 (EncKey.c_str ()), 16);
Otherwise, the string produced by MD5 is truncated at the first 0x00 the string
constructor encounters.
These are trouble:
memcpy (aes_key, EncKey.c_str (), 32);
memcpy (iv_enc, EncIV.c_str (), 16);
At best, MD5
produces a string of 16 bytes. You can't pull 32 bytes out of the 16 byte string in EncKey
.
And you are in trouble if either EncKey
or EncIV
has an embedded null. If either has one, then that string is not even 16 bytes.
And as Jim pointed out in the comment below, this is also trouble:
return string ((char *) dec_out);
It needs to be similar to:
string aes_encrypt(string _InStr)
{
...
return string ((char *) dec_out, <some size>);
}
And your use of AES_cbc_encrypt
looks wrong. You should stick with the EVP_*
interface. For an example, see EVP Symmetric Encryption and Decryption on the OpenSSL wiki.
Better, use an authenticated encryption mode like GCM so you get authenticity/integrity assurances, too. For an example, see EVP Authenticated Encryption and Decryption on the OpenSSL wiki.
Finally, use a larger hash like SHA256
or SHA512
. MD5 is no longer desired for anything other than backwards compatibility.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With