Process one AES-128-ECB block with C / C ++ and openssl

I want en- and decode one 16-byte data block using AES-128-ECB . First, I did this using the openssl command-line utility, using an ASCII string of 16 characters "a_key_simple_key" as the key and an ASCII string of 16 characters "1234567890uvwxyz" as a message. The command-line utility printed the hexadecimal string "142f 7d9e ad8c 0682 30e0 f165 a52f f789" as an encrypted message, and then successfully decoded it back to the original message, see below:

$ echo -n "1234567890uvwxyz" | openssl aes-128-ecb -K $(echo -n "a_key_simple_key" | xxd -ps) -nopad | xxd 0000000: 142f 7d9e ad8c 0682 30e0 f165 a52f f789 ./}.....0..e./.. $ echo "142f 7d9e ad8c 0682 30e0 f165 a52f f789" | xxd -r -ps | openssl aes-128-ecb -d -K $(echo -n "a_key_simple_key" | xxd -ps) -nopad 1234567890uvwxyz 

Now I have written a short C ++ program that should do the same. This does not work. There are 2 questions:

  • The encoding result is 32 bytes instead of 16 bytes (the first half of these 32 bytes is exactly the encrypted text that I expected to see)
  • Part of the decoding phase does not work at the completion stage with the following openssl message:

error: 06065064: digital envelope procedures: EVP_DecryptFinal_ex: bad decrypt

I suspect that both problems are somehow related to the filling, but I don’t understand what exactly is wrong and how to fix it. Here is the complete output of the program:

 $ g++ -Wall -g ssl-aes-128-ecb.c++ -lcrypto -lssl && ./a.out 2>&1 | less ENCODING: FAIL ENCODING: 1234567890uvwxyz --> ^T/}<9E><AD><8C>^F<82>0<E0><F1>e<A5>/<F7><89>^X<A0>P<U+DACE>R<F8>a^R^A<8A><97>GF* error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt Aborting in u_string decode(u_string, u_string) at ssl-aes-128-ecb.c++:56 

And here is the C ++ program itself (with line numbers):

 01 #include <string> 02 #include <iostream> 03 #include <openssl/evp.h> 04 #include <openssl/err.h> 05 #include <openssl/ssl.h> 06 #define ABORT() (fprintf(stderr, "%s\nAborting in %s at %s:%d\n", ERR_error_string(ERR_get_error(), NULL), __PRETTY_FUNCTION__, __FILE__, __LINE__), abort(), 0) 07 08 typedef std::basic_string<unsigned char> u_string; 09 static u_string encode(u_string key, u_string data); 10 static u_string decode(u_string key, u_string data); 11 12 // echo -n "1234567890uvwxyz" | openssl aes-128-ecb -K $(echo -n "a_key_simple_key" | xxd -ps) -nopad | xxd 13 // echo "142f 7d9e ad8c 0682 30e0 f165 a52f f789" | xxd -r -ps | openssl aes-128-ecb -d -K $(echo -n "a_key_simple_key" | xxd -ps) -nopad 14 15 int main() 16 { 17 SSL_load_error_strings(); 18 19 u_string key = (unsigned char *) "a_key_simple_key"; 20 u_string clear_text = (unsigned char *) "1234567890uvwxyz"; 21 u_string secret_txt = (unsigned char *) "\x14\x2f" "\x7d\x9e" "\xad\x8c" "\x06\x82" "\x30\xe0" "\xf1\x65" "\xa5\x2f" "\xf7\x89"; 22 23 std::cerr << "ENCODING: " << (encode(key, clear_text)==secret_txt ? "ok" : "FAIL") << std::endl; 24 std::cerr << "ENCODING: " << (char*)clear_text.c_str() << " --> " << (char*)encode(key, clear_text).c_str() << std::endl; 25 std::cerr << "DECODING: " << (decode(key, secret_txt)==clear_text ? "ok" : "FAIL") << std::endl; 26 std::cerr << "DECODING: " << (char*)secret_txt.c_str() << " --> " << (char*)decode(key, secret_txt).c_str() << std::endl; 27 28 return 0; 29 } 30 31 static u_string encode(u_string key, u_string data) 32 { 33 EVP_CIPHER_CTX ctx; 34 EVP_CIPHER_CTX_init(&ctx); 35 EVP_CIPHER_CTX_set_padding(&ctx, false); 36 EVP_EncryptInit_ex (&ctx, EVP_aes_128_ecb(), NULL, key.c_str(), NULL); 37 unsigned char buffer[1024], *pointer = buffer; 38 int outlen; 39 EVP_EncryptUpdate (&ctx, pointer, &outlen, data.c_str(), data.length()) or ABORT(); 40 pointer += outlen; 41 EVP_EncryptFinal_ex(&ctx, pointer, &outlen) or ABORT(); 42 pointer += outlen; 43 return u_string(buffer, pointer-buffer); 44 } 45 46 static u_string decode(u_string key, u_string data) 47 { 48 EVP_CIPHER_CTX ctx; 49 EVP_CIPHER_CTX_init(&ctx); 50 EVP_CIPHER_CTX_set_padding(&ctx, false); 51 EVP_DecryptInit_ex (&ctx, EVP_aes_128_ecb(), NULL, key.c_str(), NULL); 52 unsigned char buffer[1024], *pointer = buffer; 53 int outlen; 54 EVP_DecryptUpdate (&ctx, pointer, &outlen, data.c_str(), data.length()) or ABORT(); 55 pointer += outlen; 56 EVP_DecryptFinal_ex(&ctx, pointer, &outlen) or ABORT(); 57 pointer += outlen; 58 return u_string(buffer, pointer-buffer); 59 } 
+6
source share
1 answer

Well, I think I realized what is wrong:

EVP_CIPHER_CTX_set_padding() call should be executed AFTER the EVP_DecryptInit_ex() call

Thus, the solution is to exchange lines 50/51 and 35/36.

+4
source

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


All Articles