Reputation: 1085
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
Reputation: 7058
There are a number of problems:
fout_buf
in the call to EVP_EncryptFinal()
.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.pCtx
interleaved for both encryption and decryption. You should use separate context structures for encryption and for decryption.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
Reputation: 93968
nOutLen
is increased with nTmpOutLen
for the update part, but not for the finalization part.
Upvotes: 1
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