2013-01-03 61 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)。