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

 

 

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开发最新技术!


原文链接: http://blog.csdn.net/yincheng01/article/details/5334589

你可能感兴趣的:(VC++2010基于windows Sdk for windows7 开发CrytoAPI应用--加密解密文件)