9.3 功能实现
来源:互联网 发布:单片机程序烧录 编辑:程序博客网 时间:2024/05/16 09:32
本例的开发环境为Windows操作系统,VC6。基本步骤如下:
(1) 打开VC6,单击【File】|【New】命令,弹出【New】对话框。
(2)在【Projects】选项卡中,选择【MFC AppWizard(exe)】选项,创建一个MFC应用程序。在【Projectname】文本框中,输入项目名称“文件保险箱”,如图9.12所示。
(3)单击“OK”,在创建MFC应用程序向导对话框选择应用程序类型,这里选择“Dilag based”如图所示。然后单击“Finish”完成。
(4)在IDD_MY_DIALOG对话框窗体添加组合框(Combo Box)控件。
(5) 按 “Ctrl+W” 键或单击【View】|【ClassWizard】命令,启动“MFC ClassWizard”,对话框,选择【Member Variables】选项。如图所示。
(6)选中“IDC_COMBO1”控件,单击“Add Variable…”按钮。添加控件变量m_ALGLIST,如图所示。
(7)添加4个编辑框,ID分别为IDC_EDIT1、IDC_EDIT2、IDC_EDIT3、IDC_EDIT4用户保存加密时的原文和密文文件路径以及解密时的密文和原文文件路径。
(8)添加6个命令按钮。ID分别为IDC_BUTTON1、IDC_BUTTON2、IDC_BUTTON3、IDC_BUTTON4、IDC_BUTTON5、IDC_BUTTON6。功能分别是选择待加密的原文路径、选择密文路径、加密、选择待解密的密文路径、选择保存明文文件的路径、解密。
(9)添加其他控件。全部控件和布局如图所示。
(10)添加自定义的密码算法ID和算法名称结构体。在“文件保险箱Dlg.h”文件中添加如下代码。
// CMyDlg dialog
typedef struct _alglist//算法列表结构体
{
char strAlgName[128];//算法名称
int nAlgID;//算法ID
}ALG_LIST,*ALG_LIST_PTR;
(11)定义全局变量g_Alg_List,保存支持的全部加密算法。在“文件保险箱Dlg.cpp”文件中添加如下代码:
ALG_LIST g_Alg_List[]=
{
{"ECB模式的DES算法",NID_des_ecb},
{"CBC模式的DES算法",NID_des_cbc},
{"CBC模式3DES算法",NID_des_ede3_cbc},
{"ECB模式3DES算法",NID_des_ede3_ecb},
{"CBC模式的IDEA算法",NID_idea_cbc},
{"ECB模式的IDEA算法",NID_idea_ecb},
{"128位的ECB模式的AES算法",NID_aes_128_ecb},
{"128位的CBC模式的AES算法",NID_aes_128_cbc},
{"192位的ECB模式的AES算法",NID_aes_192_ecb},
{"192位的CBC模式的AES算法",NID_aes_192_cbc},
{"256位的ECB模式的AES算法",NID_aes_256_ecb},
{"256位的CBC模式的AES算法",NID_aes_256_cbc},
{NULL,0}
};
(12)添加初始化代码,添加支持的算法到组合框以及初始化OpenSSL环境。在CMyDlg类OnInitDialog方法中添加如下代码:
// TODO: Add extra initialization here
m_ALGLIST.Clear();
for(int i=0;;i++)
{
if(g_Alg_List[i].nAlgID ==0)
{
break;
}
m_ALGLIST.InsertString(i,g_Alg_List[i].strAlgName);
}
m_ALGLIST.SetCurSel(i-1);
OpenSSL_add_all_algorithms();
return TRUE; // return TRUE unless you set the focus to a control
(13)在VC工程WorkSpace区,选择【ClassView】选项,在CMyDlg类中添加函数Encrypt_File和Decrypt_File,如图所示。
(14)在“文件保险箱Dlg.cpp”文件中添加完整的Encrypt_File和Decrypt_File函数代码如下。
/**********************************************************************
函数名称:Encrypt_File
函数功能:加密文件
处理过程:
1.根据选择的密码算法以及口令,生成key和iv。
2.把文件头写入密文文件
3.循环读取原文文件数据加密后保存到密文文件路径中。
参数说明:
strPstrPlainFilePath:[IN] CString,待加密的原文文件路径
strCipherFilePath:[IN] CString,加密后的密文文件保存路径
nAlg_ID:[IN] int 密码算法ID
strPass:[IN] CString 口令
返回值:成功返回TRUE,否则返回FALSE
备注说明:密文文件由文件头和密文数据组成,文件头里记录和加密算法信息。
************************************************************************/
BOOL CMyDlg::Encrypt_File(CString strPlainFilePath, CString strCipherFilePath, int nAlg_ID, CString strPass)
{
unsigned char key[EVP_MAX_KEY_LENGTH]; //保存密钥的数组
unsigned char iv[EVP_MAX_KEY_LENGTH]; ////保存初始化向量的数组
EVP_CIPHER_CTX ctx; //EVP加密上下文环境
unsigned char out[1024]; //保存密文的缓冲区
int outl;
unsigned char in[1024]; //保存原文的缓冲区
int inl;
const EVP_CIPHER * cipher; //加密算法
int rv;
FILE *fpIn; //输入文件句柄
FILE *fpOut; //输出文件句柄
char enchead[128]={0}; //保存密文文件头的数组
//根据算法ID获得EVP_CIPHER算法
cipher = EVP_get_cipherbynid(nAlg_ID);
if(cipher==NULL)
{
return FALSE;
}
//打开待加密的原文文件
fpIn = fopen(strPlainFilePath.GetBuffer(0),"rb");
if(fpIn==NULL)
{
return FALSE;
}
//打开保存密文的文件
fpOut = fopen(strCipherFilePath.GetBuffer(0),"wb");
if(fpOut==NULL)
{
fclose(fpIn);
return FALSE;
}
strPlainFilePath.ReleaseBuffer();
strCipherFilePath.ReleaseBuffer();
//文件头,保存算法信息
sprintf(enchead,"ALGID:%d/n",nAlg_ID);
fwrite(enchead,1,128,fpOut);
//根据口令、密码算法生成key和iv
EVP_BytesToKey(cipher,EVP_md5(),NULL,(const unsigned char *)strPass.GetBuffer(0),strPass.GetLength(),1,key,iv);
//初始化ctx
EVP_CIPHER_CTX_init(&ctx);
//设置密码算法、key和iv
rv = EVP_EncryptInit_ex(&ctx,cipher,NULL,key,iv);
if(rv != 1)
{
EVP_CIPHER_CTX_cleanup(&ctx);
return FALSE;
}
//以1K为单位,循环读取原文,加密后后保存到密文文件。
for(;;)
{
inl = fread(in,1,1024,fpIn);
if(inl <= 0)//读取原文结束
break;
rv = EVP_EncryptUpdate(&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_EncryptFinal_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);
EVP_CIPHER_CTX_cleanup(&ctx);//清除EVP加密上下文环境
return TRUE;
}
/**********************************************************************
函数名称:Decrypt_File
函数功能:对加密文件解密
处理过程:
1.读取文件头获得加密算法。
2.根据算法和口令生成key和iv
3.循环读取原文文件数据解密,并保存在原文文件。
参数说明:
strCipherFilePath:[IN] CString,密文文件路径
strPstrPlainFilePath:[IN] CString,解密后的原文文件保存路径。
strPass:[IN] CString 口令
返回值:成功返回TRUE,否则返回FALSE
************************************************************************/
BOOL CMyDlg::Decrypt_File(CString strCipherFilePath, CString strPlainFilePath, CString strPass)
{
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; //加密算法
//打开待解密的密文文件
fpIn = fopen(strCipherFilePath.GetBuffer(0),"rb");
if(fpIn==NULL)
{
return FALSE;
}
//打开保存明文的文件
fpOut = fopen(strPlainFilePath.GetBuffer(0),"wb");
if(fpOut==NULL)
{
fclose(fpIn);
return FALSE;
}
strPlainFilePath.ReleaseBuffer();
strCipherFilePath.ReleaseBuffer();
//读取密文文件头,获取加密算法
fread(enchead,1,128,fpIn);
sscanf(enchead,"ALGID:%d/n",&nAlg_ID);
if(nAlg_ID==0)
{
return FALSE;
}
//根据算法ID获得EVP_CIPHER算法
cipher = EVP_get_cipherbynid(nAlg_ID);
if(cipher==NULL)
{
return FALSE;
}
//根据口令、密码算法生成key和iv
EVP_BytesToKey(cipher,EVP_md5(),NULL,(const unsigned char *)strPass.GetBuffer(0),strPass.GetLength(),1,key,iv);
//初始化ctx
EVP_CIPHER_CTX_init(&ctx);
//设置解密的算法、key和iv
rv = EVP_DecryptInit_ex(&ctx,cipher,NULL,key,iv);
if(rv != 1)
{
EVP_CIPHER_CTX_cleanup(&ctx);
return FALSE;
}
//以1K为单位,循环读取原文,解密后后保存到明文文件。
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);
EVP_CIPHER_CTX_cleanup(&ctx);//清除EVP加密上下文环境
return TRUE;
}
详细的VC工程请参考本书附光盘“code/第二篇-OpenSSL开发/文件保险箱”目录- 9.3 功能实现
- 实现功能
- 翻页功能的实现
- 拖放功能的实现
- 实现分页打印功能:
- VC实现打印功能
- sql实现搜索功能
- bolg 功能 实现 畅想
- DataGrid实现tooltip功能
- DataGrid实现tooltip功能
- DataGrid部分功能实现
- 撤消功能的实现
- DataGrid实现tooltip功能
- 拖放功能的实现
- 如何实现拖曳功能
- frameset实现隐现功能
- session功能实现原理
- 抽屉功能的实现
- BSTR String之间的转化问题
- Windows Mobile 开发、体验软件准备
- C/C++位操作简介
- Java 程序中启动及关闭命令行程序
- 谁有jbpm-starters-kit-3.1.2.zip啊?救救我吧!~55555~~~
- 9.3 功能实现
- 简单的北京奥运会倒计时 java 程序
- 目前市场上主流PDM软件是什么?
- Windchill
- [转帖] 博士猫与本科鸡 (很值得一读)
- JAXP
- Concept-第12章翻译
- jQuery 选择器的使用
- datapager分页问题 (点击两次)