您的位置:首页 > 编程语言 > C语言/C++

VC++2010基于windows Sdk for windows7 开发CrytoAPI应用--加密解密文件

2010-03-01 00:49 459 查看
windows Sdk for windows7 开发CrytoAPI是微软推出的安全应用调用函数,用很小的代码就可以实现复杂的安全信息加密。下面演示文件加密解密,详情请见代码。

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "eboy_wincrypt.h"
//#include <wincrypt.h>

#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#define KEYLENGTH  0x00800000
#define ENCRYPT_ALGORITHM CALG_RC2
#define ENCRYPT_BLOCK_SIZE 8

void HandleError(char *s);
BOOL CryEncryptFile(
PCHAR szSource,
PCHAR szDestination,
PCHAR szPassword);
BOOL CryDecryptFile(
PCHAR szSource,
PCHAR szDestination,
PCHAR szPassword);
//加密文件例子
void jiami()
{
PCHAR szSource;
PCHAR szDestination;
PCHAR szPassword;
char  response;

if(!(szSource=(char *)malloc(100)))
HandleError("malloc 失败.");
if(!(szDestination=(char *)malloc(100)))
HandleError("malloc 失败.");
if(!(szPassword=(char *)malloc(100)))
HandleError("malloc 失败.");

printf("文件加密. /n/n");
printf("请输入待加密的文件: ");
scanf("%s",szSource);
printf("请输入保存密文的文件: ");
scanf("%s",szDestination);
printf("使用口令加密文件吗? ( y/n ) ");
getchar();
scanf("%c",&response);
if(response == 'y')
{
printf("请输入口令:");
scanf("%s",szPassword);
}
else
{
printf("不使用口令,则使用随机数作为密钥。 /n");
free(szPassword);
szPassword = NULL;
}

//--------------------------------------------------------------------
// 调用EncryptFile函数完成加密。

if(CryEncryptFile(szSource, szDestination, szPassword))
{
printf("加密文件%s 成功. /n", szSource);
printf("密文文件为 %s./n",szDestination);
}
else
{
HandleError("加密文件失败!");
}

}
//解密文件例子
void jiemi()
{
PCHAR szSource;
PCHAR szDestination;
PCHAR szPassword;
char  response;

if(!(szSource=(char *)malloc(100)))
HandleError("malloc 失败.");
if(!(szDestination=(char *)malloc(100)))
HandleError("malloc 失败.");
if(!(szPassword=(char *)malloc(100)))
HandleError("malloc 失败.");

printf("文件解密. /n/n");
printf("输入待解密的文件名: ");
scanf("%s",szSource);
printf("输入明文保存文件名: ");
scanf("%s",szDestination);
printf("是否使用口令加密的文件? ( y/n ) ");
getchar();
scanf("%c",&response);
if(response == 'y')
{
printf("输入口令:");
scanf("%s",szPassword);
}
else
{
printf("没有使用口令加密,加密密钥以密文的形式保存在文件中。/n");
free(szPassword);
szPassword = NULL;
}
if(!CryDecryptFile(szSource, szDestination, szPassword))
{
printf("/n解密文件失败. /n");
}
else
{
printf("/n解密文件%s 成功 /n", szSource);
printf("解密后的文件保存为 %s ./n",szDestination);
}

}

/************************************************************************
函数功能:加密文件
参数:
szSource:[IN],待加密的明文文件路径
szDestination:[IN] 加密后的密文文件路径
szPassword:[IN] 口令
************************************************************************/
static BOOL CryEncryptFile(
PCHAR szSource,
PCHAR szDestination,
PCHAR szPassword)
{
//变量声明
FILE *hSource;		//待加密的明文文件句柄
FILE *hDestination; //密文文件句柄
HCRYPTPROV hCryptProv; //CSP句柄
HCRYPTKEY hKey;			//密钥句柄
HCRYPTKEY hXchgKey;		//交换密钥句柄
HCRYPTHASH hHash;		//摘要句柄
PBYTE pbKeyBlob;
DWORD dwKeyBlobLen;
PBYTE pbBuffer;
DWORD dwBlockLen;
DWORD dwBufferLen;
DWORD dwCount;

//--------------------------------------------------------------------
// 打开原文件

if(hSource = fopen(szSource,"rb"))
{
printf("打开明文文件 %s,成功. /n", szSource);
}
else
{
HandleError("打开明文文件出错");
}
//--------------------------------------------------------------------
// 打开密文文件.

if(hDestination = fopen(szDestination,"wb"))
{
printf("打开密文文件 %s,成功. /n", szDestination);
}
else
{
HandleError("打开密文文件出错");
}
//打开 MS_ENHANCED_PROV CSP
if(CryptAcquireContext(
&hCryptProv,
NULL,
MS_ENHANCED_PROV,
PROV_RSA_FULL,
0))
{
printf("打开CSP成功 /n");
}
else
{
HandleError("调用 CryptAcquireContext 出错!");
}
//--------------------------------------------------------------------
//   创建会话密钥

if(!szPassword ) //密码为空,那么使用随机数作为会话密钥来加密文件
{
//---------------------------------------------------------------
// 产生一个随机的密钥.

if(CryptGenKey(
hCryptProv,
ENCRYPT_ALGORITHM,
KEYLENGTH | CRYPT_EXPORTABLE,
&hKey))
{
printf("创建会话密钥成功. /n");
}
else
{
HandleError("调用 CryptGenKey 出错!");
}
//---------------------------------------------------------------
// 获得加密者的交换密钥(加密密钥)即容器对应的公钥

if(CryptGetUserKey(
hCryptProv,
AT_KEYEXCHANGE,
&hXchgKey))
{
printf("获得用户公钥成功./n");
}
else
{
HandleError("调用 CryptGetUserKey 出错,可能用户公钥不存在!");
}
//---------------------------------------------------------------
// 导出会话密钥hKey,使用交换密钥hXchgKey加密。第一次调用只得到BLOB长度。

if(CryptExportKey(
hKey,
hXchgKey,
SIMPLEBLOB,
0,
NULL,
&dwKeyBlobLen))
{
printf("导出的密钥长度为%d字节. /n",dwKeyBlobLen);
}
else
{
HandleError("调用 CryptExportKey 出错!");
}
//分配内存
if(pbKeyBlob =(BYTE *)malloc(dwKeyBlobLen))
{
;
}
else
{
HandleError("内存不够了. /n");
}
//---------------------------------------------------------------
// 导出会话密钥hKey,使用交换密钥hXchgKey加密
if(CryptExportKey(
hKey,
hXchgKey,
SIMPLEBLOB,
0,
pbKeyBlob,
&dwKeyBlobLen))
{
printf("导出密钥成功 /n");
}
else
{
HandleError("调用 CryptExportKey 出错!");
}
//---------------------------------------------------------------
// 释放交换密钥句柄
CryptDestroyKey(hXchgKey);
hXchgKey = 0;

//---------------------------------------------------------------
// 把密文会话密钥的长度写入目标文件

fwrite(&dwKeyBlobLen, sizeof(DWORD), 1, hDestination);
if(ferror(hDestination))
{
HandleError("写文件头失败");
}
else
{
;
}
//--------------------------------------------------------------
// 把密文会话密钥写入目标文件

fwrite(pbKeyBlob, 1, dwKeyBlobLen, hDestination);
if(ferror(hDestination))
{
HandleError("写文件头失败");
}
else
{
printf("密文的会话密钥已经写入到文件。/n");
}
}
else //输入了口令,那么使用此口令派生出会话密钥来加密文件
{
//创建摘要句柄
if(CryptCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&hHash))
{
printf("创建哈希句柄成功. /n");
}
else
{
HandleError("调用 CryptCreateHash 出错!");
}
//--------------------------------------------------------------------
// 对口令进行摘要运算
if(CryptHashData(
hHash,
(BYTE *)szPassword,
strlen(szPassword),
0))
{
printf("口令已经被哈希. /n");
}
else
{
HandleError("调用 CryptHashData 出错!");
}
//--------------------------------------------------------------------
// 从哈希对象中派生出会话密钥
if(CryptDeriveKey(
hCryptProv,
ENCRYPT_ALGORITHM,
hHash,
KEYLENGTH,
&hKey))
{
printf("从哈希对象中派生出会话密钥成功。 /n");
}
else
{
HandleError("调用 CryptDeriveKey 出错!");
}
//--------------------------------------------------------------------
//销毁哈希对象

CryptDestroyHash(hHash);
hHash = 0;
}

//--------------------------------------------------------------------
//现在加密文件的会话密钥已经准备好了。

dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;

if(ENCRYPT_BLOCK_SIZE > 1)
dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
else
dwBufferLen = dwBlockLen;

if(pbBuffer = (BYTE *)malloc(dwBufferLen))
{
;
}
else
{
HandleError("内存不够了. /n");
}
//--------------------------------------------------------------------
// 不断循环加密原文件,把密文写入的密文文件

do
{

//--------------------------------------------------------------------
// 读取原文dwBlockLen字节
dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
if(ferror(hSource))
{
HandleError("读取原文错误。/n");
}

//--------------------------------------------------------------------
// 加密数据
if(!CryptEncrypt(
hKey,
0,
feof(hSource),
0,
pbBuffer,
&dwCount,
dwBufferLen))
{
HandleError("调用 CryptEncrypt 出错. /n");
}

//--------------------------------------------------------------------
// 把密文写入的密文文件

fwrite(pbBuffer, 1, dwCount, hDestination);
if(ferror(hDestination))
{
HandleError("写文件失败");
}

}
while(!feof(hSource));
//--------------------------------------------------------------------
//关闭文件句柄
if(hSource)
fclose(hSource);
if(hDestination)
fclose(hDestination);

//--------------------------------------------------------------------
// 释放内存

if(pbBuffer)
free(pbBuffer);

//--------------------------------------------------------------------
// 销毁会话密钥

if(hKey)
CryptDestroyKey(hKey);

//--------------------------------------------------------------------
// 释放交换密钥

if(hXchgKey)
CryptDestroyKey(hXchgKey);

//--------------------------------------------------------------------
// 销毁哈希对象

if(hHash)
CryptDestroyHash(hHash);

//--------------------------------------------------------------------
// 释放CSP句柄

if(hCryptProv)
CryptReleaseContext(hCryptProv, 0);
return(TRUE);
} // End of Encryptfile

/************************************************************************
函数功能:解密文件
参数:
szSource:[IN],待解密的密文文件路径
szDestination:[IN] 加密后的明文文件路径
szPassword:[IN] 口令
************************************************************************/
static BOOL CryDecryptFile(
PCHAR szSource,
PCHAR szDestination,
PCHAR szPassword)
{
//--------------------------------------------------------------------
//   声明变量

FILE *hSource;			//解密的密文文件句柄
FILE *hDestination;		//明文文件句柄

HCRYPTPROV hCryptProv; //CSP句柄
HCRYPTKEY hKey;			//密钥句柄
HCRYPTHASH hHash;		//摘要句柄
PBYTE pbKeyBlob = NULL;
DWORD dwKeyBlobLen;
PBYTE pbBuffer;
DWORD dwBlockLen;
DWORD dwBufferLen;
DWORD dwCount;
BOOL status = FALSE;

//--------------------------------------------------------------------
// 打开密文文件
if(!(hSource = fopen(szSource,"rb")))
{
HandleError("打开密文文件失败 !");
}
//--------------------------------------------------------------------
// 打开目标文件即解密后的明文文件

if(!(hDestination = fopen(szDestination,"wb")))
{
HandleError("打开明文文件失败 !");
}
//--------------------------------------------------------------------
// 获得CSP句柄
if(!CryptAcquireContext(
&hCryptProv,
NULL,
MS_ENHANCED_PROV,
PROV_RSA_FULL,
0))
{
HandleError("调用 CryptAcquireContext 函数出错 !");
}
//--------------------------------------------------------------------
//  检查szPassword是否为空

if(!szPassword) //szPassword为空
{
//--------------------------------------------------------------------
// 使用保存在文件中的加密密钥解密

//从密文文件中读取密钥
fread(&dwKeyBlobLen, sizeof(DWORD), 1, hSource);
if(ferror(hSource) || feof(hSource))
{
HandleError("读文件头失败!");
}
if(!(pbKeyBlob = (BYTE *)malloc(dwKeyBlobLen)))
{
HandleError("申请内存失败!.");
}
fread(pbKeyBlob, 1, dwKeyBlobLen, hSource);
if(ferror(hSource) || feof(hSource))
{
HandleError("读文件头失败!");
}
//--------------------------------------------------------------------
// 导入密钥到CSP,使用私钥解密会话密钥,产生hKey。
if(!CryptImportKey(
hCryptProv,
pbKeyBlob,
dwKeyBlobLen,
0,
0,
&hKey))
{
HandleError("调用 CryptImportKey 函数出错 !");
}
}
else //口令非空,口令派生出的会话密钥解密文件
{
//--------------------------------------------------------------------
// 创建哈希对象
if(!CryptCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&hHash))
{
HandleError("调用 CryptCreateHash 函数出错 !");
}
//--------------------------------------------------------------------
// 哈希口令

if(!CryptHashData(
hHash,
(BYTE *)szPassword,
strlen(szPassword),
0))
{
HandleError("调用 CryptHashData 函数出错 !");
}
//--------------------------------------------------------------------
// 从哈希对象中派生出会话密钥

if(!CryptDeriveKey(
hCryptProv,
ENCRYPT_ALGORITHM,
hHash,
KEYLENGTH,
&hKey))
{
HandleError("调用 CryptDeriveKey 函数出错 !");
}
//--------------------------------------------------------------------
// 销毁哈希对象

CryptDestroyHash(hHash);
hHash = 0;
}
//--------------------------------------------------------------------
//现在已经获得了解密数据的会话密钥。

dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
dwBufferLen = dwBlockLen;

if(!(pbBuffer = (BYTE *)malloc(dwBufferLen)))
{
HandleError("Out of memory!/n");
}
//--------------------------------------------------------------------
// 解密密文,并把明文写到明文文件中。

do {
//--------------------------------------------------------------------
// 循环读取密文

dwCount = fread(
pbBuffer,
1,
dwBlockLen,
hSource);
if(ferror(hSource))
{
HandleError("读取密文失败!");
}
//--------------------------------------------------------------------
// 数据解密
if(!CryptDecrypt(
hKey,
0,
feof(hSource),
0,
pbBuffer,
&dwCount))
{
HandleError("CryptDecrypt解密失败!");
}
//--------------------------------------------------------------------
// 写明文数据到文件

fwrite(
pbBuffer,
1,
dwCount,
hDestination);
if(ferror(hDestination))
{
HandleError("写文件失败!");
}
}
while(!feof(hSource));
status = TRUE;

//--------------------------------------------------------------------
// 关闭文件
if(hSource)
fclose(hSource);
if(hDestination)
fclose(hDestination);

//--------------------------------------------------------------------
// 释放内存

if(pbKeyBlob)
free(pbKeyBlob);

if(pbBuffer)
free(pbBuffer);

//--------------------------------------------------------------------
// 销毁会话密钥

if(hKey)
CryptDestroyKey(hKey);

//--------------------------------------------------------------------
// 销毁哈希对象
if(hHash)
CryptDestroyHash(hHash);

//--------------------------------------------------------------------
// 释放CSP句柄

if(hCryptProv)
CryptReleaseContext(hCryptProv, 0);

return status;
} // End of Decryptfile
//出错处理函数
void HandleError(char *s)
{
printf("本程序在运行时有错误发生./n");
printf("%s/n",s);
printf("错误码: %x/n.",GetLastError());
printf("程序退出./n");
exit(1);
}
int main(int argc, char* argv[])
{

jiami();
jiemi();
return 0;
}


本文作者专著《Visual C++2010开发权威指南》即将推出,敬请关注,Visual C++2010最近技术,Windows7开发最新技术!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐