完整word版基于CryptoAPI的文件加解密系统的设计与实现Word格式文档下载.docx
《完整word版基于CryptoAPI的文件加解密系统的设计与实现Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《完整word版基于CryptoAPI的文件加解密系统的设计与实现Word格式文档下载.docx(37页珍藏版)》请在冰点文库上搜索。
两种方法:
通过哈希值构造通过随机数构造。
3、数据加密与解密:
实现对数据进行加密解密操作。
4、相关资源释放:
释放申请的相关资源.
(下图为数据加解密的流程)
(参考《网络安全程序设计教程》李红娇 著)
(2)CryptoAPI应用程序的编译环境
⑴包含的头文件
#include<
windows。
h>
#include〈wincrypt.h>
⑵包含的静态链接库
链接CryptoAPI函数必须有静态库Crypto32.lib的支持,部分CryptoAPI函数可能还需要静态库advapi32。
lib及CryptUI。
lib的支持。
⑶若在VC++6。
0和VS2012上编译程序,则需加上以下语句
#ifndef_WIN32_WINNT
#define_WIN32_WINNT0x0400
#endif
(3)实验步骤
1)
在VS2012下实现基于CryptoAPI的文件加密。
a、创建会话密钥
为保证数据加密效率,CryptoAPI规定数据加密操作必须基于对称密码进行。
于是,加密方进行加密操作首先必须创建会话密钥,一般可以通过调用函数CryptoGenKey或CryptDeriveKey创建,在创建会话密钥时指定加密算法。
b、加密数据
在创建会话密钥后,则可以调用CryptEncrypt函数进行加密操作。
加密操作需要注意的是每次加密数据块的长度必须根据具体的算法和算法类型确定,一般来说,加密数据块长度为算法规定的基准加密块长度的整数倍.对于分组密码,需为密文数据块预留一个基准块长度的空间。
c、安全保存或交换会话密钥
数据加密完成后,当在今后的某个时间或其他用户需要解密数据时,必须保存会话密钥以备后用,或者是传输会话密钥给特定用户以使其能正确进行解密操作.
2)
在VS2012下实现基于CryptoAPI的文件解密。
a、获取会话密钥
根据保存或传输会话密钥方式不同,进行相应的操作正确获取会话密钥
b、解密数据
利用获取的会话密钥调用函数CryptDecrypt解密数据,它和函数CryptEncrypt互为逆操作.同样的,解密操作需要注意的是每次解密数据块的长度必须根据具体的算法和算法类型确定,一般来说,解密数据块长度为算法基准加密块长度的整数倍。
要求:
算法的详细实现过程。
a)
获得csp句柄
b)
构造密钥
c)
数据加密
d)
数据解密
e)
释放相关资源
算法实现的流程图
三、实验结果
原文件
加密后
解密后
PS:
我们在加密的时候,没有采用通过随机数创建密钥,然后只能通过输入密码创建加密密钥。
截图:
未加密
四、设计总结
由于多方尝试并编写Openssl对文件的加解密方法,均以失败告终,所以我们小组决定采用新的加密算法,即WindowsCryptoAPI,由微软公司提出的一种安全加密应用服务框架。
本次试验的主要内容是基于CryptoAPI的文件加解密系统的设计与实现,在仔细看懂代码的基础上,真正明白了CryptoAPI的结构体系。
在加密操作时,首先要创建会话密钥,在创建会话密钥时指定加密算法,注意的是,创建会话密钥时,它制定具体的加密算法应该注意具体的CSP是否支持此算法。
我们在做加密的时候,没有加入通过随机数创建会话密钥,只能进行输入密码创建加密密钥。
然后是进行数据的加密操作,当完成以后要进行安全保存或者交换会话密钥。
解密时要获取会话密钥,然后进行数据解密。
CryptoAPI除直接用于加密数据外,还为许多高级安全性服务提供了基础,包括用于电子商务的SET,用于加密客户机/服务器消息的PCT,用于在各个平台之间来回传递机密数据和密钥的PFX,代码签名等等.通过此次编写程序,我对基于CryptoAPI的文件加解密系统有了更深层次的了解,对之前做过的基于CryptoAPI实现文件完整性校验的实验理解的更加透彻.
在编写程序的过程中,遇到了很多棘手的问题,但是这些问题,我通过了找老师,上网查询问题出错的原因等方法努力的寻求答案,到现在为止,程序已经顺利完成,运行无阻。
自己根据要求,从零开始做一份实验真的不容易,需要对整体结构局势进行把握,在做之前要做好多重准备工作,例如运行环境(软、硬件环境)、输入的形式和输入值的范围、输出的形式描述、功能描述。
细节决定成败,对于我而言,这次的作业让我清楚认识到,注重细节的重要性,有时候一个字母的大小写,几个变量的数据类型的统一性,考虑后选择的更为合适的数据类型,重复执行的问题等等,这些都让我不断进步.
五、源代码
加密:
#ifndef_WIN32_WINNT
#define_WIN32_WINNT0x0400
#endif
#include<
stdio.h〉
#include〈string。
#include〈iostream〉
#include〈conio.h>
#include〈windows。
h〉
#include<
wincrypt.h>
#defineMY_ENCODING_TYPE(PKCS_7_ASN_ENCODING|X509_ASN_ENCODING)
#defineKEYLENGTH0x00800000
#defineENCRYPT_ALGORITHMCALG_RC4
#defineENCRYPT_BLOCK_SIZE8
classEnc{
public:
HCRYPTPROVGetCryptProv();
BOOLEncryptFile(
PCHARszSource,
PCHARszDestination,
PCHARszPassword);
HCRYPTKEYGenKeyByPassword(HCRYPTPROVhCryptProv,PCHARszPassword);
};
#include<
iostream〉
#include"
Enc。
h"
usingnamespacestd;
//功能:
加密原文szSource文件,加密后的数据存储在szDestination文件中
//参数:
//szSource:
原文文件名
//szDestination:
加密后数据存储文件
//szPassword:
用户输入的密码
BOOLEnc:
:
EncryptFile(
PCHARszSource,
PCHARszDestination,
PCHARszPassword)
{
//变量申明与初始化。
FILE*hSource;
FILE*hDestination;
HCRYPTPROVhCryptProv;
HCRYPTKEYhKey;
PBYTEpbBuffer;
DWORDdwBlockLen;
DWORDdwBufferLen;
DWORDdwCount;
//打开原文文件。
if(hSource=fopen(szSource,"
rb”))
{
cout<
<
”原文文件”〈〈szSource〈〈”已经打开。
\n”;
}
else
{
cout〈<
"
打开原文文件出错!
”〈〈endl;
}
//打开目标文件。
if(hDestination=fopen(szDestination,"
wb"
))
{
cout〈〈"
目标文件”<
szDestination〈<
”已经打开。
\n"
〈<
endl;
}
cout〈<
”打开目标文件出错!
endl;
//获取加密服务者句柄
hCryptProv=GetCryptProv();
//创建会话密钥。
if(!
szPassword||strcmp(szPassword,"
”)==0)
//hKey=GenKeyByRandom(hCryptProv,hDestination);
当输入密码为空时,则创建随机的加密密钥,并导出创建的密钥保存到文件中.
cout〈〈”你输入的密钥为空!
请正确输入!
”<
〈endl;
}
else
{
//当输入密码不为空时,则通过输入密码创建加密密钥
hKey=GenKeyByPassword(hCryptProv,szPassword);
//因为加密算法按ENCRYPT_BLOCK_SIZE大小块加密,所以被加密的
//数据长度必须是ENCRYPT_BLOCK_SIZE的整数倍。
下面计算一次加密的
//数据长度。
dwBlockLen=1000-1000%ENCRYPT_BLOCK_SIZE;
//确定加密后密文数据块大小。
若是分组密码模式,则必须有容纳额外块的空间
if(ENCRYPT_BLOCK_SIZE>
1)
dwBufferLen=dwBlockLen+ENCRYPT_BLOCK_SIZE;
dwBufferLen=dwBlockLen;
//分配内存空间.
if(pbBuffer=(BYTE*)malloc(dwBufferLen))
cout<
”已经为缓冲区分配了内存.\n"
;
”所需内存不够。
;
//循环加密原文件
do
//每次从原文件中读取dwBlockLen字节数据.
dwCount=fread(pbBuffer,1,dwBlockLen,hSource);
if(ferror(hSource))
{
cout〈<
”读取明文文件出错!
\n”;
}
//—-----———---—-———-—-—-—-—---—--—-——----——-——-—---——---————-—---————
//加密数据。
if(!
CryptEncrypt(
hKey,//密钥
0,//如果数据同时进行散列和加密,这里传入一个散列对象
feof(hSource),//如果是最后一个被加密的块,输入TRUE。
如果不是输入FALSE.
//这里通过判断是否到文件尾来决定是否为最后一块。
0,//保留
pbBuffer,//输入被加密数据,输出加密后的数据
&
dwCount,//输入被加密数据实际长度,输出加密后数据长度
dwBufferLen))//pbBuffer的大小.
{
加密数据时出错。
}
//——————--——-————--—--—--—-—-—-—--———————-——---—-——-—--—---——----—---
//把加密后数据写到密文文件中
fwrite(pbBuffer,1,dwCount,hDestination);
if(ferror(hDestination))
cout<
〈"
写入密文时出错。
}while(!
feof(hSource));
//---——-—-----—-—--—---———--—------————--——--—--—-—---——-——-——-----——
//关闭文件
if(hSource)
if(fclose(hSource))
cout〈〈”关闭原文文件出错!
if(hDestination)
if(fclose(hDestination))
cout〈〈"
关闭目标文件出错!
”;
//—-—-—-—--—---—----—-—————————-——-—-———-———-——-———-——---——-——-—-----
//释放内存空间.
if(pbBuffer)
free(pbBuffer);
//-——-—-—-—-—-——---—---———-——----—-—-—-——-—--—————-—-—--—-—-———-——-——
//销毁会话密钥
if(hKey)
(CryptDestroyKey(hKey)))
销毁会话密钥时出错”<
//----—-——--——-—--—-——-——---——--—-—--——-—-—-—------————---——-——-——-——
//释放CSP句柄
if(hCryptProv)
if(!
(CryptReleaseContext(hCryptProv,0)))
”释放CSP句柄时出错”<
return(TRUE);
}//endEncryptfile
//获取加密提供者句柄
HCRYPTPROVEnc:
:
GetCryptProv()
{
HCRYPTPROVhCryptProv;
//加密服务提供者句柄
//获取加密提供者句柄
if(CryptAcquireContext(
&hCryptProv,//加密服务提供者句柄
NULL,//密钥容器名,这里使用登陆用户名
MS_ENHANCED_PROV,//加密服务提供者
PROV_RSA_FULL,//加密服务提供者类型,可以提供加密和签名等功能
0))//标志
加密服务提供者句柄获取成功!
\n”;
//重新建立一个新的密钥集
CryptAcquireContext(&
hCryptProv,NULL,MS_ENHANCED_PROV,PROV_RSA_FULL,CRYPT_NEWKEYSET))
{
重新建立一个新的密钥集出错!
”;
returnhCryptProv;
}
//GenKeyByRandom:
通过输入密码创建会话密钥
//参数:
hCryptProvCSP句柄
//szPassword输入密码
HCRYPTKEYEnc:
GenKeyByPassword(HCRYPTPROVhCryptProv,PCHARszPassword)
{
HCRYPTHASHhHash;
//--——-——------——-———-———————--—--—————-———---——---—---—---——-—--—-——
//创建哈希句柄.
if(CryptCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&
hHash))
一个哈希句柄已经被创建.\n"
}
else
”ErrorduringCryptCreateHash!
\n"
}
//--—--—-—-—————--—-——-—--———-——--—-—---—-——————--—--———-——--—--——-—-
//计算输入密码的哈希值。
if(CryptHashData(
hHash,
(BYTE*)szPassword,
strlen(szPassword),
0))
”密码已经被添加到了哈希表中.\n”;
计算输入密码的哈希值时出错.\n”;
//——-———-—-——-—-———--———-—-—---—-—————--—-—-—-——--———-—-—----——-——-—-
//通过哈希值创建会话密钥。
if(CryptDeriveKey(
ENCRYPT_ALGORITHM,
KEYLENGTH,
hKey))
”通过密码的哈希值获得了加密密钥。
\n”;
cout〈〈”ErrorduringCryptDeriveKey!
//-—————-———-——-—-------------——-—--—---——-—---—-——--—-------—-—---—-
//销毁哈希句柄。
if(hHash)
(CryptDestroyHash(hHash)))
”ErrorduringCryptDestroyHash"
〈〈endl;
hHash=0;
//返回创建的会话密钥
returnhKey;
解密:
#include〈string。
conio。
#include〈windows.h>
wincrypt。
#defineMY_ENCODING_TYPE(PKCS_7_ASN_ENCODING|X509_ASN_ENCODING)
#defineKEYLENGTH0x00800000
#defineENCRYPT_ALGORITHMCALG_RC4
classDec{//加密文件的方法
public:
HCRYPTPROVGetCryptProv();
//方法的原型
BOOLDecryptFile(
PCHARszSource,
CHAR*szPassword);
HCRYPTKEYGenKeyByPassword(HCRYPTPROVhCryptProv,PCHARszPassword);
//通过输入口令创建会话密钥,我们的密码
HCRYPTKEYGenKeyFromFile(HCRYPTPROVhCryptProv,FILE*hSource);
#ifndef_WIN32_WINNT
stdio。
string。
#include〈conio。
#include〈windows.h〉
#include〈wincrypt。
#include〈iostream>
#defineENCRYPT_BLOCK_SIZE8
#include〈iostream〉
#include”Dec。
h”
/*
功能:
解密密文