[Development] AES encryption decryption through OpenSSL API and binary respectively - JohnHau/mis GitHub Wiki

https://hackmd.io/@TomasZheng/SkDqKZA6I

tags: development, C, tool, linux, AES, CBC, ECB, OpenSSL, openssl, openssl API, openssl binary, hexdump, od, xxd [Development] AES encryption/decryption through OpenSSL API and binary respectively Overview Environment Openssl binary usage openssl help openssl aes-128-ecb help Encryption by binary and decrpytion by binary Encryption by binary and decrpytion by API Encryption Decryption Tools to dump hex Annex Build openssl shared libaray Reference

Overview In this note, on one hand, I will show how to use the openssl binary to encrypt and decrypt a file. On the other hand, I will demo how to encrypt a file through openssl binary and decrypt it through openssl API in c code.

Environment In this case, I encrypt a file in a x86-based system, and decrypt it in a mips-based system which is a switch here.

x86-based Host for encryption Tomas# uname -a Linux 4.15.0-99-generic #100-Ubuntu SMP Wed Apr 22 20:32:56 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

Tomas# openssl version
OpenSSL 1.1.1 11 Sep 2018 mips-based for decryption Switch# uname -r Linux Switch 3.18.24 #1 Thu Jun 11 10:40:48 CST 2020 mips GNU/Linux

openssl version v 1.1.1.1 2015/04/28

Openssl binary usage openssl help Tomas# openssl help Standard commands asn1parse ca ciphers cms
crl crl2pkcs7 dgst dhparam
dsa dsaparam ec ecparam
enc engine errstr gendsa
genpkey genrsa help list
nseq ocsp passwd pkcs12
pkcs7 pkcs8 pkey pkeyparam
pkeyutl prime rand rehash
req rsa rsautl s_client
s_server s_time sess_id smime
speed spkac srp storeutl
ts verify version x509

Message Digest commands (see the `dgst' command for more details) blake2b512 blake2s256 gost md4
md5 rmd160 sha1 sha224
sha256 sha3-224 sha3-256 sha3-384
sha3-512 sha384 sha512 sha512-224
sha512-256 shake128 shake256 sm3

Cipher commands (see the `enc' command for more details) aes-128-cbc aes-128-ecb aes-192-cbc aes-192-ecb
aes-256-cbc aes-256-ecb aria-128-cbc aria-128-cfb
aria-128-cfb1 aria-128-cfb8 aria-128-ctr aria-128-ecb
aria-128-ofb aria-192-cbc aria-192-cfb aria-192-cfb1
aria-192-cfb8 aria-192-ctr aria-192-ecb aria-192-ofb
aria-256-cbc aria-256-cfb aria-256-cfb1 aria-256-cfb8
aria-256-ctr aria-256-ecb aria-256-ofb base64
bf bf-cbc bf-cfb bf-ecb
bf-ofb camellia-128-cbc camellia-128-ecb camellia-192-cbc
camellia-192-ecb camellia-256-cbc camellia-256-ecb cast
cast-cbc cast5-cbc cast5-cfb cast5-ecb
cast5-ofb des des-cbc des-cfb
des-ecb des-ede des-ede-cbc des-ede-cfb
des-ede-ofb des-ede3 des-ede3-cbc des-ede3-cfb
des-ede3-ofb des-ofb des3 desx
rc2 rc2-40-cbc rc2-64-cbc rc2-cbc
rc2-cfb rc2-ecb rc2-ofb rc4
rc4-40 seed seed-cbc seed-cfb
seed-ecb seed-ofb sm4-cbc sm4-cfb
sm4-ctr sm4-ecb sm4-ofb
openssl aes-128-ecb help Tomas# openssl aes-128-ecb -help
Usage: aes-128-ecb [options] Valid options are: -help Display this summary -ciphers List ciphers -in infile Input file -out outfile Output file -pass val Passphrase source -e Encrypt -d Decrypt -p Print the iv/key -P Print the iv/key and exit -v Verbose output -nopad Disable standard block padding -salt Use salt in the KDF (default) -nosalt Do not use salt in the KDF -debug Print debug info -a Base64 encode/decode, depending on encryption flag -base64 Same as option -a -A Used with -[base64|a] to specify base64 buffer as a single line -bufsize val Buffer size -k val Passphrase -kfile infile Read passphrase from file -K val Raw key, in hex -S val Salt, in hex -iv val IV in hex -md val Use specified digest to create a key from the passphrase -iter +int Specify the iteration count and force use of PBKDF2 -pbkdf2 Use password-based key derivation function 2 -none Don't encrypt -* Any supported cipher -rand val Load the file(s) into the random number generator -writerand outfile Write random data to the specified file -engine val Use engine, possibly a hardware device Encryption by binary and decrpytion by binary In this case, it is intuitive. The command is mostly the same including parameters like -K, -k, -iv, -nosalt, -pbkdf2, -iter and so on. The differences are -d/-e and -in/-out.

I gave an example below.

Tomas# cat org.txt thisismytestforaesencanddecsadfsadf

Tomas# openssl aes-128-ecb -e -k aaaaaaaa -p -nosalt -pbkdf2 -in org.txt -out cypher.txt key=35D447AD8E76F1BFB40F12EAF216ABEB Tomas# cat cypher.txt +-~=)Rb}]pP\6;:%3(߁ X%

Tomas# openssl aes-128-ecb -d -k aaaaaaaa -p -nosalt -pbkdf2 -in cypher.txt -out plain.txt key=35D447AD8E76F1BFB40F12EAF216ABEB Tomas# cat plain.txt thisismytestforaesencanddecsadfsadf

Tomas# openssl aes-128-ecb -d -K 35D447AD8E76F1BFB40F12EAF216ABEB -p -nosalt -pbkdf2 -in cypher.txt -out plain2.txt key=35D447AD8E76F1BFB40F12EAF216ABEB Tomas# cat plain2.txt thisismytestforaesencanddecsadfsadf Encryption by binary and decrpytion by API In this case, I encrypt a file by openssl binary and decrypt it by API imported in my code. The key point here is the key/iv in C code are strings while in parameter are hex. Therefore, we have to convert the key/iv in C code to hex digits as a parameter when launching openssl binary. This can be done through an online tool here or others.

For instance,

in C code, assume key = mybiggg_only_123 iv = thisisxoperation (for CBC) in the parameter of -K key = 6d7962696767675f6f6e6c795f313233 iv = 746869736973786f7065726174696f6e (for CBC) Encryption openssl aes-128-ecb -e -K 6d7962696767675f6f6e6c795f313233 -p -in org.txt -out cypher.txt

openssl aes-128-cbc -e -K 6d7962696767675f6f6e6c795f313233 -iv 746869736973786f7065726174696f6e -p -in org -out cypher2.txt Decryption Here, we just demo simple ECB.

Below gist shows:

File Name Description AES_example.c The source code for demo Makefile For build binary org.txt The original plaint text gen_cypher.sh The command to generate cypher text plain.txt The outcome of aes_example #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <openssl/aes.h> #include <openssl/md5.h>

int decrypt_AES128ECB(unsigned char *key, unsigned char *cypher, unsigned char *plain, int len) { AES_KEY deckey;

if(0 != (len % AES_BLOCK_SIZE)) {
    printf("Cypher length should be a multiple of AES_BLOCK_SIZE\n");
    return -1;
}

if (AES_set_decrypt_key(key, 128, &deckey) < 0) {
    printf("Set decryption key in AES failed\n");
    return -2;
}

while(len) {
    AES_ecb_encrypt(cypher, plain, &deckey, AES_DECRYPT);-
    len -= AES_BLOCK_SIZE;
    cypher += AES_BLOCK_SIZE;
    plain += AES_BLOCK_SIZE;
}

return 0;

}

int main(void) { unsigned char Rfd, Wfd; unsigned long flen; unsigned char buf[1024], plain[1024]; int ret, read_size, write_size;

ret = 0;
Rfd = open("cypher.txt", O_RDONLY);
Wfd = open("plain.txt", O_RDWR);

if((0 > Rfd) || (0 > Wfd)) {
    ret = -1;
    goto err;
}

printf("File opened\n");

flen = lseek (Rfd, 0, SEEK_END);
lseek (Rfd, 0, SEEK_SET);

read_size = read(Rfd, buf, flen);
if(read_size < 0) {
    ret = -2;
    goto err;
}

printf("File read\n");

decrypt_AES128ECB("mybiggg_only_123", buf, plain, flen);

printf("File decrypted\n");

write_size = write(Wfd, plain, flen);
if(write_size < 0) {
    ret = -3;
    goto err;
}

printf("File written\n");

err: close(Rfd); close(Wfd);

printf("Done Error %d\n", ret);
return ret;

} view rawAES_example.c hosted with ❤ by GitHub #!/bin/sh openssl aes-128-ecb -e -K 6d7962696767675f6f6e6c795f313233 -p -in org.txt -out cypher.txt echo "Gen cypher.txt done!" view rawgen_cypher.sh hosted with ❤ by GitHub #!/bin/sh git clone git://git.openssl.org/openssl.git cd openssl git checkout OpenSSL_1_1_1-stable ./config -fPIC -shared make -j8 cp libcrypto.so ../your_destination/ view rawgen_lib.sh hosted with ❤ by GitHub aes_example.o: AES_example.c gcc AES_example.c -lcrypto -o aes_example

#gcc AES_example.c -lcrypto -o aes_example
view rawMakefile hosted with ❤ by GitHub thisismytestforaesencanddecsadfsadf view raworg.txt hosted with ❤ by GitHub thisismytestforaesencanddecsadfsadf

view rawplain.txt hosted with ❤ by GitHub

Tools to dump hex When we implement features like AES encryption/decryption or MD5/SHA checksum in a file, we usually need to deubg it to check whether our encrypting, decrypting or checksum calculating are correct. So, we need some tools to inspect it.

We can utilize tools such as hexdump, od, and xxd to dump hex values in a file or binary.

Below shows some examples of them.

Tomas# hexdump uImage | head -n 2 0000000 0527 5619 d0bb 0c65 005f b69d 1e00 404c 0000010 0080 0000 2780 50a0 cac5 e513 0505 0102

Tomas# od -x uImage | head -n 2 0000000 0527 5619 d0bb 0c65 005f b69d 1e00 404c 0000020 0080 0000 2780 50a0 cac5 e513 0505 0102

Tomas# xxd uImage | head -n 2 00000000: 2705 1956 bbd0 650c 5f00 9db6 001e 4c40 '..V..e._.....L@ 00000010: 8000 0000 8027 a050 c5ca 13e5 0505 0201 .....'.P........

Tomas# hexdump -C uImage | head -n 2 00000000 27 05 19 56 bb d0 65 0c 5f 00 9d b6 00 1e 4c 40 |'..V..e._.....L@| 00000010 80 00 00 00 80 27 a0 50 c5 ca 13 e5 05 05 02 01 |.....'.P........| Annex Build openssl shared libaray Tomas# git clone git://git.openssl.org/openssl.git Tomas# cd openssl Tomas# git checkout OpenSSL_1_1_1-stable Tomas# ./config -fPIC -shared Tomas# make -j8 Tomas# cp libcrypto.so ../your_destination/ Reference https://onlinestringtools.com/convert-string-to-ascii http://aes.online-domain-tools.com/ https://emn178.github.io/online-tools/md5_checksum.html https://my.oschina.net/u/2539854/blog/1559531 https://stackoverflow.com/questions/2537271/compile-openssl-with-the-shared-option http://www.361way.com/hexdump/749.html

⚠️ **GitHub.com Fallback** ⚠️