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

你可能感兴趣的:(Algorithm,加密,windows,解密,vc++,2010)