Process a single AES-128-ECB block using C/C++ and openssl -
i want en- , decode single 16 bytes block of data using aes-128-ecb cipher. first did via openssl command line utility using ascii 16 characters string "a_key_simple_key" key , ascii 16 characters string "1234567890uvwxyz" message. command line utility printed hexadecimal string "142f 7d9e ad8c 0682 30e0 f165 a52f f789" ciphered message , decoded 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've written short c++ program should same. doesn't work. there 2 issues:
- the output of encoding part 32 bytes long instead of 16 bytes (the first half of these 32 bytes ciphered text expected see)
- the decoding part failing in finalization step following openssl message:
error:06065064:digital envelope routines:evp_decryptfinal_ex:bad decrypt
i suspect both issues somehow connected padding, don't understand wrong , how fix it. here full output of 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) @ ssl-aes-128-ecb.c++:56 and here c++ program (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 @ %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 }
ok, seems figured out what's wrong:
evp_cipher_ctx_set_padding() call must done after evp_decryptinit_ex() call
so solution exchange lines 50/51 , 35/36.
Comments
Post a Comment