2013-01-03 91 views
1

目前,我想要做一個簡單的程序,加密的二進制文件(.zip文件),將其保存在另一種格式(.cry),然後解密文件.cry回到它的原始狀態。OpenSSL的加密/解密

我得到沒有錯誤,但是當我嘗試打開解密的.zip文件我從歸檔程序錯誤。

注:原來的.zip文件只包含與寫3個字的小.txt文件。

#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; 

}

+1

從一開始,這使得它更容易調試代碼創建獨立的功能。包括日誌語句,以便你可以看到你在做什麼。在請求stackoverflow之前,先調試你的代碼 –

回答

1

nOutLennTmpOutLen增加了更新的一部分,但不是最終確定的部分。

3

貌似你不寫全加密/解密輸出到文件中。在那裏寫nOutLen,而不是fdecr_size。 您正在使用ECB模式,因此您的加密數據將填充到16字節邊界。 另外我會建議使用CBC模式。

2

有許多問題:

  • 的代碼假定加密文件將是大小與原始文件相同。這通常不是這種情況,尤其是在您正在使用的ECB模式下不使用AES-128等分組密碼。事實上,在撥打EVP_EncryptFinal()時,您正在溢出fout_buf
  • 您需要正確地計算跨EVP操作(包括*FinalnOutLen和處理加密或解密輸出的很多字節。例如,您只將fout_size字節的加密數據寫入.cry文件,該文件小於OpenSSL寫入緩衝區的文件數量,這反過來導致解密後的最後一個塊損壞,從而導致歸檔錯誤。
  • 您使用交錯加密和解密相同的上下文pCtx。您應該使用單獨的上下文結構進行加密和解密。
  • 您爲pKeypIV保留192個字節,繼續填充24個字節,每個填充隨機數據,但最終只有16個字節的密鑰被OpenSSL使用(AES-128),並且沒有IV(ECB模式不使用IV)。