OpenSSL AES 256 CBC via EVP api in C

What I'm trying to do: Write a C program that opens a file of arbitrary size and reads its contents. After the content has been read, it will encrypt them in AES 256 CBC and save the encrypted text to a file called encrypted text. Once this is saved, it will close both files. Then, the encrypted text from the file that was just saved will open and decrypt the encrypted text and save it in a decrypted file.

My problem: It seems like it never decrypts my ciphertext. I get garbage, I have no idea what I'm doing wrong. Please, help.

#include <string.h> #include <stdio.h> #include <stdlib.h> #include <openssl/evp.h> #include <openssl/aes.h> void encrypt(FILE *ifp, FILE *ofp) { //Get file size fseek(ifp, 0L, SEEK_END); int fsize = ftell(ifp); //set back to normal fseek(ifp, 0L, SEEK_SET); int outLen1 = 0; int outLen2 = 0; unsigned char *indata = malloc(fsize); unsigned char *outdata = malloc(fsize*2); unsigned char ckey[] = "thiskeyisverybad"; unsigned char ivec[] = "dontusethisinput"; //Read File fread(indata,sizeof(char),fsize, ifp);//Read Entire File //Set up encryption EVP_CIPHER_CTX ctx; EVP_EncryptInit(&ctx,EVP_aes_256_cbc(),ckey,ivec); EVP_EncryptUpdate(&ctx,outdata,&outLen1,indata,fsize); EVP_EncryptFinal(&ctx,outdata,&outLen2); fwrite(outdata,sizeof(char),fsize,ofp); } void decrypt(FILE *ifp, FILE *ofp) { //Get file size fseek(ifp, 0L, SEEK_END); int fsize = ftell(ifp); //set back to normal fseek(ifp, 0L, SEEK_SET); int outLen1 = 0; int outLen2 = 0; unsigned char *indata = malloc(fsize); unsigned char *outdata = malloc(fsize*2); unsigned char ckey[] = "thiskeyisverybad"; unsigned char ivec[] = "dontusethisinput"; //Read File fread(indata,sizeof(char),fsize, ifp);//Read Entire File //setup decryption EVP_CIPHER_CTX ctx; EVP_DecryptInit(&ctx,EVP_aes_256_cbc(),ckey,ivec); EVP_DecryptUpdate(&ctx,outdata,&outLen1,indata,fsize); EVP_DecryptFinal(&ctx,outdata,&outLen2); fwrite(outdata,sizeof(char),fsize,ofp); } int main(int argc, char *argv[]) { FILE *fIN, *fOUT; fIN = fopen("plain.txt", "rb");//File to be encrypted; plain text fOUT = fopen("cyphertext.txt", "wb");//File to be written; cipher text encrypt(fIN, fOUT); fclose(fIN); fclose(fOUT); //Decrypt file now fIN = fopen("cyphertext.txt", "rb");//File to be written; cipher text fOUT = fopen("decrypted.txt", "wb");//File to be written; cipher text decrypt(fIN,fOUT); fclose(fIN); fclose(fOUT); return 0; } 

Note: there may be some errors. EDIT: It seems I made a mistake with the key and IV, both of which are 128 bits, and I'm trying to use 256 bit CBC. That was my problem, it seems to work as soon as I changed it to

 EVP_aes_128_cbc() 
+6
source share
2 answers

Here is my version of your code. Naturally, I like it, but I offer it as an alternative. Note the complete lack of error checking: the real code will have it.

 #include <string.h> #include <stdio.h> #include <stdlib.h> #include <openssl/evp.h> #include <openssl/aes.h> #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif /** * Encrypt or decrypt, depending on flag 'should_encrypt' */ void en_de_crypt(int should_encrypt, FILE *ifp, FILE *ofp, unsigned char *ckey, unsigned char *ivec) { const unsigned BUFSIZE=4096; unsigned char *read_buf = malloc(BUFSIZE); unsigned char *cipher_buf; unsigned blocksize; int out_len; EVP_CIPHER_CTX ctx; EVP_CipherInit(&ctx, EVP_aes_256_cbc(), ckey, ivec, should_encrypt); blocksize = EVP_CIPHER_CTX_block_size(&ctx); cipher_buf = malloc(BUFSIZE + blocksize); while (1) { // Read in data in blocks until EOF. Update the ciphering with each read. int numRead = fread(read_buf, sizeof(unsigned char), BUFSIZE, ifp); EVP_CipherUpdate(&ctx, cipher_buf, &out_len, read_buf, numRead); fwrite(cipher_buf, sizeof(unsigned char), out_len, ofp); if (numRead < BUFSIZE) { // EOF break; } } // Now cipher the final block and write it out. EVP_CipherFinal(&ctx, cipher_buf, &out_len); fwrite(cipher_buf, sizeof(unsigned char), out_len, ofp); // Free memory free(cipher_buf); free(read_buf); } int main(int argc, char *argv[]) { unsigned char ckey[] = "thiskeyisverybad"; unsigned char ivec[] = "dontusethisinput"; FILE *fIN, *fOUT; if (argc != 2) { printf("Usage: <executable> /path/to/file/exe"); return -1; } // First encrypt the file fIN = fopen("plain.txt", "rb"); //File to be encrypted; plain text fOUT = fopen("cyphertext.txt", "wb"); //File to be written; cipher text en_de_crypt(TRUE, fIN, fOUT, ckey, ivec); fclose(fIN); fclose(fOUT); //Decrypt file now fIN = fopen("cyphertext.txt", "rb"); //File to be read; cipher text fOUT = fopen("decrypted.txt", "wb"); //File to be written; cipher text en_de_crypt(FALSE, fIN, fOUT, ckey, ivec); fclose(fIN); fclose(fOUT); return 0; } 
+6
source

This code works if someone has any suggestions as to how it will be cleaner or more efficient, write a comment.

 #include <string.h> #include <stdio.h> #include <stdlib.h> #include <openssl/evp.h> #include <openssl/aes.h> void encrypt(FILE *ifp, FILE *ofp) { //Get file size fseek(ifp, 0L, SEEK_END); int fsize = ftell(ifp); //set back to normal fseek(ifp, 0L, SEEK_SET); int outLen1 = 0; int outLen2 = 0; unsigned char *indata = malloc(fsize); unsigned char *outdata = malloc(fsize*2); unsigned char ckey[] = "thiskeyisverybad"; unsigned char ivec[] = "dontusethisinput"; //Read File fread(indata,sizeof(char),fsize, ifp);//Read Entire File //Set up encryption EVP_CIPHER_CTX ctx; EVP_EncryptInit(&ctx,EVP_aes_128_cbc(),ckey,ivec); EVP_EncryptUpdate(&ctx,outdata,&outLen1,indata,fsize); EVP_EncryptFinal(&ctx,outdata + outLen1,&outLen2); fwrite(outdata,sizeof(char),outLen1 + outLen2,ofp); } void decrypt(FILE *ifp, FILE *ofp) { //Get file size fseek(ifp, 0L, SEEK_END); int fsize = ftell(ifp); //set back to normal fseek(ifp, 0L, SEEK_SET); int outLen1 = 0; int outLen2 = 0; unsigned char *indata = malloc(fsize); unsigned char *outdata = malloc(fsize); unsigned char ckey[] = "thiskeyisverybad"; unsigned char ivec[] = "dontusethisinput"; //Read File fread(indata,sizeof(char),fsize, ifp);//Read Entire File //setup decryption EVP_CIPHER_CTX ctx; EVP_DecryptInit(&ctx,EVP_aes_128_cbc(),ckey,ivec); EVP_DecryptUpdate(&ctx,outdata,&outLen1,indata,fsize); EVP_DecryptFinal(&ctx,outdata + outLen1,&outLen2); fwrite(outdata,sizeof(char),outLen1 + outLen2,ofp); } int main(int argc, char *argv[]) { if(argc != 2){ printf("Usage: <executable> /path/to/file/exe"); return -1; } FILE *fIN, *fOUT; fIN = fopen("plain.txt", "rb");//File to be encrypted; plain text fOUT = fopen("cyphertext.txt", "wb");//File to be written; cipher text encrypt(fIN, fOUT); fclose(fIN); fclose(fOUT); //Decrypt file now fIN = fopen("cyphertext.txt", "rb");//File to be written; cipher text fOUT = fopen("decrypted.txt", "wb");//File to be written; cipher text decrypt(fIN,fOUT); fclose(fIN); fclose(fOUT); return 0; } 

In addition, according to this post, EVP api will handle arbitrary input size

AES Encryption-large files

+3
source

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


All Articles