函数功能:根据输入的口令对文件解密,并输出明文到指定的文件。
函数定义:
BOOL Decrypt_File(CString strCipherFilePath, CString strPlainFilePath, CString strPass)
参数说明:
q strCipherFilePath:[IN] 待解加密的文件路径
q strPlainFilePath:[IN] 解密后的明文文件保存路径
q strPass:[IN] 解密口令
返回值:操作成功返回TRUE,否则返回FALSE。
处理过程如下:
(1)定义一些必要的变量,包括保存密钥的数组、保存初始化向量的数组、EVP加密上下文环境、保存密文的缓冲区、保存原文的缓冲区、加密算法、输入文件句柄、输出文件句柄等。
unsigned char key[EVP_MAX_KEY_LENGTH]; //保存密钥的数组
unsigned char iv[EVP_MAX_KEY_LENGTH]; //保存初始化向量的数组
EVP_CIPHER_CTX ctx; //EVP加密上下文环境
unsigned char out[1024+EVP_MAX_KEY_LENGTH]; //保存解密后明文的缓冲区数组
int outl;
unsigned char in[1024]; //保存密文数据的数组
int inl;
const EVP_CIPHER * cipher; //加密算法
int rv;
FILE *fpIn; //输入文件句柄
FILE *fpOut; //输出文件句柄
char enchead[128]={0}; //保存密文文件头的数组
int nAlg_ID=0; //加密算法
(2)打开待解密的密文文件和保存明文的文件。
//打开待解密的密文文件
fpIn = fopen(strCipherFilePath.GetBuffer(0),"rb");
if(fpIn==NULL)
{
return FALSE;
}
//打开保存明文的文件
fpOut = fopen(strPlainFilePath.GetBuffer(0),"wb");
if(fpOut==NULL)
{
fclose(fpIn);
return FALSE;
}
(3)读取密文文件头,获取加密算法。
//读取密文文件头,获取加密算法
fread(enchead,1,128,fpIn);
sscanf(enchead,"ALGID:%d/n",&nAlg_ID);
(4)根据算法ID获得EVP_CIPHER算法。
//根据算法ID获得EVP_CIPHER算法
cipher = EVP_get_cipherbynid(nAlg_ID);
(5)根据口令、密码算法生成key和iv。
EVP_BytesToKey(cipher,EVP_md5(),NULL,(const unsigned char *)strPass.GetBuffer(0),strPass.GetLength(),1,key,iv);
(6)初始化ctx ,设置密码算法、key和iv。
//初始化ctx
EVP_CIPHER_CTX_init(&ctx);
//设置解密的算法、key和iv
rv = EVP_DecryptInit_ex(&ctx,cipher,NULL,key,iv);
(7)循环读取原文,解密后后保存到明文文件。
for(;;)
{
inl = fread(in,1,1024,fpIn);
if(inl <= 0)
break;
rv = EVP_DecryptUpdate(&ctx,out,&outl,in,inl);//解密
if(rv != 1)
{
fclose(fpIn);
fclose(fpOut);
EVP_CIPHER_CTX_cleanup(&ctx);
return FALSE;
}
fwrite(out,1,outl,fpOut);//保存明文到文件
}
//解密结束
rv = EVP_DecryptFinal_ex(&ctx,out,&outl);
if(rv != 1)
{
fclose(fpIn);
fclose(fpOut);
EVP_CIPHER_CTX_cleanup(&ctx);
return FALSE;
}
fwrite(out,1,outl,fpOut);//保存明文到文件
fclose(fpIn);
fclose(fpOut);
(6)清除EVP加密上下文环境。
EVP_CIPHER_CTX_cleanup(&ctx);//清除EVP加密上下文环境
处理过程如图所示:
密文文件的格式为密文文件头+密文。文件头为128字节,其格式为“ALGID:”字符串+ nAlg_ID