Dorin Rusu
Dorin Rusu

Reputation: 1085

OpenSSL encryption/decryption

I'm currently trying to make a simple program that encrypts a binary file (.zip) saves it in another format (.cry) and then decrypts the .cry file back to it's original state.

I'm getting no errors but when i try to open the decrypted .zip file i get an error from the archiving program.

Note: the original .zip file just contains a small .txt file with 3 words written.

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/rand.h>


int main(){
const EVP_CIPHER* pCipher = EVP_aes_128_ecb();
EVP_CIPHER_CTX* pCtx = new EVP_CIPHER_CTX;
//int nBl = EVP_CIPHER_CTX_block_size( pCtx );
FILE *fin;
FILE *fout;
FILE *fdecr;
long fin_size,fout_size,fdecr_size;
unsigned char *fin_buf;
unsigned char *fout_buf;
unsigned char *fdecr_buf;

size_t rezultat;


fin = fopen("arhiva.zip", "rb");
fout = fopen("arhiva.zip.cry","wb");
fdecr= fopen("decript.zip","wb");
if (fin==NULL)
    {fputs ("File error",stderr); exit (1);}
if (fout==NULL)
    {fputs ("File error",stderr); exit (1);}
if (fdecr==NULL)
    {fputs ("File error",stderr); exit (1);}


fseek (fin , 0 , SEEK_END);
fin_size = ftell (fin);
fout_size=fin_size;
fdecr_size=fin_size;
rewind (fin);
fin_buf = (unsigned char*) malloc (sizeof(unsigned char)*fin_size);

fdecr_buf= (unsigned char*) malloc (sizeof(unsigned char)*fin_size);
if (fin_buf == NULL) {fputs ("Memory error",stderr); exit (2);}
//if (fout_buf == NULL) {fputs ("Memory error",stderr); exit (2);}
if (fdecr_buf == NULL) {fputs ("Memory error",stderr); exit (2);}

//copiere fisier in buffer
rezultat = fread (fin_buf,1,fin_size,fin);
if (rezultat != fin_size) {fputs ("Reading error",stderr); exit (3);}



      //pregatire criptare
OpenSSL_add_all_ciphers();

EVP_CIPHER_CTX_init( pCtx );

unsigned char pKey[192];
unsigned char pIV[192];
RAND_bytes(pKey,24);
RAND_bytes(pIV,24);

EVP_EncryptInit_ex( pCtx, pCipher, NULL, pKey, pIV);
EVP_DecryptInit_ex( pCtx, pCipher, NULL, pKey, pIV);

      //cript

int nOutLen = 0;
int nTmpOutLen = 0;

fout_buf = (unsigned char*) malloc (sizeof(unsigned char)*fout_size);
memset( fout_buf, 0, fout_size);

EVP_EncryptUpdate( pCtx,fout_buf,&nTmpOutLen,fin_buf,fin_size );
nOutLen += nTmpOutLen;
EVP_EncryptFinal( pCtx,fout_buf + nTmpOutLen,&nTmpOutLen );
fwrite(fout_buf, 1, fout_size, fout);

//decript
nOutLen = 0;
nTmpOutLen = 0;
memset( fdecr_buf, 0, fdecr_size);

EVP_DecryptUpdate(pCtx,fdecr_buf,&nTmpOutLen,fout_buf,fout_size );
nOutLen += nTmpOutLen;
EVP_DecryptFinal( pCtx,fdecr_buf + nTmpOutLen,&nTmpOutLen );
fwrite(fdecr_buf, 1, fdecr_size, fdecr);


fclose(fin);
fclose(fout);
fclose(fdecr);
EVP_CIPHER_CTX_cleanup(pCtx);


return 0;

}

Upvotes: 1

Views: 1987

Answers (3)

Daniel Roethlisberger
Daniel Roethlisberger

Reputation: 7058

There are a number of problems:

  • The code assumes that the encrypted file will be the same size as the original file. This is generally not the case, especially not with block ciphers such as AES-128 in ECB mode which you are using. In fact, you are overflowing fout_buf in the call to EVP_EncryptFinal().
  • You need to correctly calculate nOutLen across the EVP operations (including *Final) and handle that many bytes of encrypted or decrypted output. For instance, you only write fout_size bytes of encrypted data to the .cry file, which is less than what OpenSSL wrote to the buffer, which in turn leads to a corrupted last block after decryption and thus to the archiver errors.
  • You use the same context pCtx interleaved for both encryption and decryption. You should use separate context structures for encryption and for decryption.
  • You reserve 192 bytes for both pKey and pIV, proceed to fill 24 bytes each with random data, but only 16 bytes of the key gets used by OpenSSL in the end (AES-128), and none of the IV (ECB mode uses no IV).

Upvotes: 2

Maarten Bodewes
Maarten Bodewes

Reputation: 93968

nOutLen is increased with nTmpOutLen for the update part, but not for the finalization part.

Upvotes: 1

Nickolay Olshevsky
Nickolay Olshevsky

Reputation: 14160

Looks like you don't write the whole encryption/decryption output to the file. Write there nOutLen, not fdecr_size. You are using ECB mode, so your encrypted data will be padded to 16-byte boundary. Also I would recommend to use CBC mode.

Upvotes: 3

Related Questions