[Development] AES encryption and descryption through OpenSSL API only === ###### tags: `development`, `C`, `tool`, `linux`, `AES`, `CBC`, `OpenSSL`, `openssl`, `openssl API` [Toc] # Introduction >OpenSSL is a robust, commercial-grade, and full-featured toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols. It is also a general-purpose cryptography library. For more information about the team and community around the project, or to start making your own contributions, start with the community page. To get the latest news, download the source, and so on, please see the sidebar or the buttons at the top of every page. > >OpenSSL is licensed under an Apache-style license, which basically means that you are free to get and use it for commercial and non-commercial purposes subject to some simple license conditions. Our goal is to utilize this library to launch AES encryption and descryption for our data. Here, we are going to utilize AES CBC 128 bit algorithm. It's a little bit more complex than EBC one. To encrypt data, we have to give one key and one initial vector (IV) and obviously the data as shown in below figure. ![](https://i.imgur.com/2WPPGL3.png) ![](https://i.imgur.com/7YA4FzA.png) # Prerequisite Needless to say, we have to download OpenSSL library first. Currently, the newest version is 1.0.2r as show below. But, we utilize 1.0.1c as an example. | Date | description | |:------ |:----------- | |2019-Feb-26 14:34:59 | openssl-1.0.2r.tar.gz| |2019-Feb-26 14:34:59 | openssl-1.1.1b.tar.gz| https://www.openssl.org/source/ # Demo ## API and Header We are going to utilize AES CBC 128 bit algorithm. As a result, we will call the API ***AEScbcencrypt***. Before that, we have to include a header file as shown below. ```C= #include "aes/aes.h" extern void AEScbcencrypt(const unsigned char in, unsigned char out, sizet len, const AESKEY key, unsigned char ivec, const int enc); ``` ## Implementation ### Source code And now, we are going to show the way to encrypt and decrypt our data. --- Input: 1. Plain texts or Cipher texts 2. Key 3. IV Output: 1. Plain texts or Cipher texts ``` C= #include "aes/aes.h" extern void AEScbcencrypt(const unsigned char in, unsigned char out, sizet len, const AESKEY key, unsigned char ivec, const int enc); #define AES_BLOCK_SIZE 16 #define AES_DBG 1 unsigned char key[AES_BLOCK_SIZE] = "thisismykey"; // AES_BLOCK_SIZE = 16 unsigned char iv[AES_BLOCK_SIZE] = {0}; unsigned char txt[32] = "thisismyplaintext"; AES_KEY enckey; AES_KEY deckey; typedef struct enigma { unsigned char key[AES_BLOCK_SIZE]; unsigned char iv[AES_BLOCK_SIZE]; AES_KEY enckey; AES_KEY deckey; unsigned char *plaintxt; unsigned char *cyphertxt; } Enigma, *PEnigma; Enigma data = { .key = "aaaassssjjjjkkkk", .iv = {0}, .plaintxt = NULL, .cyphertxt = NULL }; extern void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t len, const AES_KEY *key, unsigned char *ivec, const int enc); void showcyphertxt(unsigned char *cypher, unsigned int len) { int i; for (i=0; i< len; ++i) printf("%x%x", (cypher[i] >> 4) & 0xf, cypher[i] & 0xf); printf("\n"); } void myEncrypt(unsigned char *key, unsigned char* plaintxt, unsigned int cypher_len ,AES_KEY enckey, unsigned char* result) { unsigned char iv[AES_BLOCK_SIZE]; unsigned int plain_len = strlen((const char*)plaintxt); unsigned char *aes_input = (unsigned char*) calloc( cypher_len, sizeof(unsigned char)); strncpy((char*)aes_input, (char*)plaintxt, (size_t) plain_len); unsigned char *aes_output = (unsigned char*) calloc( cypher_len, sizeof(unsigned char)); if (AES_set_encrypt_key(key, 128, &enckey) < 0) { #if AES_DBG printf("[AESDBG] Unable to set encryption key in AES\n"); #endif return; } memset(iv, 0, AES_BLOCK_SIZE); AES_cbc_encrypt(aes_input, aes_output, cypher_len, &enckey, iv, AES_ENCRYPT); #if AES_DBG printf("[AESDBG][Info] Translate plain_len %d to cypher with len %d\n", plain_len, cypher_len); #endif //showcyphertxt(aes_output, cypher_len); memcpy(result, aes_output, sizeof(unsigned char)*cypher_len); free(aes_output); free(aes_input); } void myDecrypt(unsigned char *key, unsigned char* cyphertxt, unsigned int cypher_len ,AES_KEY deckey, unsigned char* result) { unsigned char iv[AES_BLOCK_SIZE]; unsigned char *aes_input = (unsigned char*) calloc( cypher_len, sizeof(unsigned char)); memcpy(aes_input, cyphertxt, sizeof(unsigned char)*cypher_len); unsigned char *aes_output = (unsigned char*) calloc( cypher_len, sizeof(unsigned char)); if (AES_set_decrypt_key(key, 128, &deckey) < 0) { #if AES_DBG printf("[AESDBG] Unable to set decryption key in AES\n"); #endif return; } memset(iv, 0, AES_BLOCK_SIZE); //showcyphertxt(aes_input, cypher_len); AES_cbc_encrypt(aes_input, aes_output, cypher_len, &deckey, iv, AES_DECRYPT); #if AES_DBG printf("[AESDBG][Info] Translate to plain with strlen %d cypherlen %d\n", strlen((char*)aes_output), cypher_len); #endif //printf("plaintxt = %s\n", aes_output); memcpy(result, aes_output, sizeof(unsigned char)*cypher_len);//debug free(aes_output); free(aes_input); } int main(void) { unsigned int cypher_len, plain_len; unsigned char *cyphertxt, *plaintxt; plain_len = strlen((char*)txt); cypher_len = (plain_len % AES_BLOCK_SIZE == 0)? plain_len : ((plain_len / AES_BLOCK_SIZE + 1) * AES_BLOCK_SIZE); cyphertxt = (unsigned char*) calloc(cypher_len, sizeof(unsigned char)); plaintxt = (unsigned char*) calloc(cypher_len, sizeof(unsigned char)); myEncrypt(key, txt, cypher_len, enckey, cyphertxt); printf("Encryption with key: %s\nciphertxt =\n", key); showcyphertxt(cyphertxt, cypher_len); myDecrypt(key, cyphertxt, cypher_len, deckey, plaintxt); printf("Decryption with key: %s\nplaintxt = %s\n", key, plaintxt); return 0; } ``` ### Makefile ``` =shell CC = gcc CFLAG = -Wall -g LIB = -L/home/tomas/openssl-1.0.1c -lcrypto INC = -I/home/tomas/openssl-1.0.1c/crypto RM = rm -f default: all all: TEST TEST: testaes.c $(CC) $(CFLAG) $(LIB) $(INC) -o test testaes.c clean veryclean: $(RM) TEST ``` ### Build Log ``` =shell [tomas@ aes_example]$ make gcc -Wall -g -L/home/tomas/openssl-1.0.1c -lcrypto -I/home/tomas/openssl-1.0.1c/crypto -o test testaes2.c /usr/bin/ld: skipping incompatible /home/tomas/openssl-1.0.1c/libcrypto.so when searching for -lcrypto /usr/bin/ld: skipping incompatible /home/tomas/openssl-1.0.1c/libcrypto.a when searching for -lcrypto ``` ### Runtime Log ``` =shell [tomas@ aes_example]$ ./test [AESDBG][Info] Translate plain_len 17 to cypher with len 32 Encryption with key: thisismykey ciphertxt = 787352dbd5593a4d089d4bf9289b66db9acf7008e4a43bb037a368844bf9ebc8 [AESDBG][Info] Translate to plain with strlen 17 cypherlen 32 Decryption with key: thisismykey plaintxt = thisismyplaintext ```