Encrypt and decrypt strings using C ++, Openssl and aes

I am trying to encrypt and decrypt a string using C ++ openssl and aes cbc.

It is strange that on one PC it works, but on another PC it is not. There I only have 3/4 of the original line, so the ending is wrong.

Another strange thing: when I add a DLL called "libeay32.dll" to the exe directory of the file on the second PC, it works, but not on the first PC.

Thus, the first computer only works with dll, the second computer only works with dll.

My question is whether this code can be improved and why this DLL is needed on one computer, but not on another.

Here is what I already wrote:

KEY and Iv define:

#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 the first PC:

Input:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa a

Encrypted:

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

Decrypted:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa a

Second PC output:

Input:

the

Encrypted:

S ^ Wo + ", and ~ ¼ \ é | $ ðLÁ`aC · Z½h | = A ° Ie = ÓpËIÝoCYN ° §) XwY + ¤¯ÐM | ÷ ¹NÉk + <?????? Ak a- ÷ ¨ ZD + BñFb YU]? C

Decrypted:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa WI "H + ²²²² |||||| w $ Ö Ö :?

+6
source share
1 answer

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 will need something like:

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

Otherwise, the line created by MD5 is truncated at the first 0x00 that the string constructor encounters.


This is problem:

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

In the best case, MD5 creates a string of 16 bytes. You cannot pull 32 bytes from a 16-byte string in EncKey .

And you have problems if either EncKey or EncIV has a built-in zero. If it has one, then this line does not even contain 16 bytes.


And as Jim noted in the comment below, this is also a problem:

 return string ((char *) dec_out); 

It should look like:

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

And your use of AES_cbc_encrypt does not look right. You must adhere to the EVP_* interface. For example, see Symmetric Encryption and Decryption of EVP on the OpenSSL Wiki.

It is better to use an authenticated encryption mode such as GCM, so that you also receive guarantees of authenticity and integrity. For an example, see EVP Authenticated Encryption and Decryption on the OpenSSL Wiki.


Finally, use a larger hash such as SHA256 or SHA512 . MD5 is no longer needed for anything other than backward compatibility.

+3
source

Source: https://habr.com/ru/post/971433/


All Articles