OpenSSL AES 256 CBC via EVP api in C

匿名 (未验证) 提交于 2019-12-03 01:54:01

问题:

What I am trying to do: Write a program in C that opens a file of arbitrary size and reads its contents. Once The contents are read it will encrypt them in AES 256 CBC and save the ciphertext to a file called ciphertext. Once this is saved it will close both files. Then will open the cipher text from the file that was just saved and decrypt the cipher text and save it to a file called decrypted.

My Problem: It seems to never decrypt my cipher text. I get garbage, I have no idea what I am doing wrong. Please help.

#include  #include  #include  #include  #include   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 misspellings. EDIT: Seems Like I made a mistake with the key and IV, both of which are 128 bit and I am trying to use the 256 bit CBC. This was my problem, seems to work once I changed it to

EVP_aes_128_cbc() 

回答1:

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

#include  #include  #include  #include  #include   #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  /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; } 


回答2:

This code works, if anyone has some suggestions as to how it would be cleaner or more efficient please drop a comment.

#include  #include  #include  #include  #include   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:  /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; } 

Also According to this post the EVP api will handle an arbitrary sized input

AES Encryption- large files



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!