winzenghua 发表于 2013-2-7 03:40:16

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]
查看完整版本: VC++2010基于windows Sdk for windows7 开发CrytoAPI应用--加密解密文件