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 KEYLENGTH0x00800000#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; charresponse;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; charresponse;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:,待加密的明文文件路径szDestination: 加密后的密文文件路径szPassword: 口令************************************************************************/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 CSPif(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:,待解密的密文文件路径szDestination: 加密后的明文文件路径szPassword: 口令************************************************************************/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开发最新技术!
页:
[1]