|
前一篇简单介绍了下CryptoAPI的东西,这篇就将那点代码放出来给大家看看,以作交流参考目的。- /************************************************************************
- FileName:CryptoDefine.h
- Author :eliteYang
- Mail :elite_yang@163.com
- Desc :加密需要的常量定义
- ************************************************************************/
- #ifndef __CRYPTO_DEFINE_H_
- #define __CRYPTO_DEFINE_H_
- #include <WinCrypt.h>
- #define MY_ENCODING_TYPE ( PKCS_7_ASN_ENCODING | X509_ASN_ENCODING )
- #define KEY_LENGTH 0x00800000
- #define ENCRYPT_ALGORITHM CALG_RC4
- #define ENCRYPT_BLOCK_SIZE 8
- #endif
- /************************************************************************
- FileName:LogDefine.h
- Author :eliteYang
- Mail :elite_yang@163.com
- Desc :提示信息
- ************************************************************************/
- #ifndef __LOG_DEFINE_H__
- #define __LOG_DEFINE_H__
- #define MAX_INFO 1024
- #include <stdio.h>
- void (*g_fnPrintInfoCallBack)( char* format ) = NULL;
- void OutputInfoMessage( char* format )
- {
- if ( g_fnPrintInfoCallBack != NULL )
- {
- char temp[ MAX_INFO ] = { 0 };
- memset( temp, 0, sizeof( temp ) );
- va_list list;
- va_start( list, format );
- vsprintf_s( temp, sizeof( temp ) - 1, format, list );
- va_end( list );
- g_fnPrintInfoCallBack( temp );
- }
- }
- #endif
- /************************************************************************
- FileName:Crypto.h
- Author :eliteYang
- Mail :elite_yang@163.com
- Desc :Crypto加解密算法实现函数
- ************************************************************************/
- #ifndef __CRYPTO_H__
- #define __CRYPTO_H__
- #pragma once
- #define MAX_INFO_LENGTH 1024
- #include "CryptoDefine.h"
- #include <windows.h>
- #include <string>
- #include <stdio.h>
- #include "LogDefine.h"
- extern void MyOutputInfoMessage( char* format );
- void HandleError( char* s )
- {
- char cErrorInfo[ MAX_INFO_LENGTH ];
- memset( cErrorInfo, 0, sizeof( cErrorInfo ) );
- sprintf_s( cErrorInfo, sizeof( cErrorInfo ) - 1, "%s 错误代码:%x 程序终止执行!", s, GetLastError() );
- MyOutputInfoMessage( cErrorInfo );
- exit(1);
- }
- HCRYPTPROV GetCryptProv()
- {
- HCRYPTPROV hCryptProv;
- if ( CryptAcquireContext( &hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0 ) )
- {
- MyOutputInfoMessage( "加密服务提供者(CSP)句柄获取成功" );
- }
- else
- {
- if ( !CryptAcquireContext( &hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET ) )
- {
- HandleError( "重新建立一个新的密钥集出错!" );
- }
- }
- return hCryptProv;
- }
- HCRYPTKEY GetKeyByPassword( HCRYPTPROV hCryptProv,PCHAR szPassword )
- {
- HCRYPTKEY hKey;
- HCRYPTHASH hHash;
- if ( CryptCreateHash( hCryptProv, CALG_MD5, 0, 0, &hHash ) )
- {
- MyOutputInfoMessage( "一个Hash句柄已经被创建" );
- }
- else
- {
- HandleError( "CryptCreateHash 创建Hash句柄失败" );
- }
- if ( CryptHashData( hHash, (BYTE*)szPassword, strlen( szPassword ), 0 ) )
- {
- MyOutputInfoMessage( "密码已经被添加到了Hash表中" );
- }
- else
- {
- HandleError( "CryptHashData 计算密码的Hash值失败" );
- }
- // 通过Hash创建值创建会话密钥
- if ( CryptDeriveKey( hCryptProv, ENCRYPT_ALGORITHM, hHash, KEY_LENGTH, &hKey ) )
- {
- MyOutputInfoMessage( "通过密码的Hash值获得了加密密钥" );
- }
- else
- {
- HandleError( "CryptDeriveKey 通过Hash值创建会话密钥失败" );
- }
- if ( hHash )
- {
- if ( !CryptDestroyHash( hHash ) )
- {
- HandleError( "CryptDestroyHash 销毁Hash句柄失败" );
- }
- else
- {
- MyOutputInfoMessage( "释放Hash句柄成功" );
- hHash = 0;
- }
- }
- return hKey;
- }
- HCRYPTKEY GenKeyByRandom( HCRYPTPROV hCryptProv,FILE* hDestination )
- {
- HCRYPTKEY hKey;
- HCRYPTKEY hXchgKey;
- PBYTE pbKeyBlob;
- DWORD dwKeyBlobLen;
- if( CryptGenKey( hCryptProv, ENCRYPT_ALGORITHM, KEY_LENGTH | CRYPT_EXPORTABLE, &hKey) )
- {
- MyOutputInfoMessage( "一个会话密钥已经被创建" );
- }
- else
- {
- HandleError("CryptGenKey 创建会话密钥失败");
- }
- // 创建交换密钥
- if( CryptGenKey( hCryptProv, AT_KEYEXCHANGE, 0, &hXchgKey ) )
- {
- MyOutputInfoMessage( "交换密钥对已经创建" );
- }
- else
- {
- HandleError("在试图创建交换密钥时出错");
- }
- // 确定密钥数据块长度,并分配空间.
- if( CryptExportKey( hKey, hXchgKey, SIMPLEBLOB, 0, NULL, &dwKeyBlobLen ) )
- {
- char cInfo[ MAX_INFO_LENGTH ];
- memset( cInfo, 0, sizeof( cInfo ) );
- sprintf_s( cInfo, sizeof( cInfo ) - 1, "此密钥块的长度是 %d 字节", dwKeyBlobLen );
- MyOutputInfoMessage( cInfo );
- }
- else
- {
- HandleError( "计算密钥数据块长度出错" );
- }
- if (pbKeyBlob =(BYTE *)malloc( dwKeyBlobLen ) )
- {
- MyOutputInfoMessage( "已经问此密钥块分配了内存" );
- }
- else
- {
- HandleError("所需内存不够");
- }
- // 导出会话密钥到简单密钥数据块中.
- if( CryptExportKey( hKey, hXchgKey, SIMPLEBLOB, 0, pbKeyBlob, &dwKeyBlobLen ) )
- {
- MyOutputInfoMessage( "此会话密钥已经被导出" );
- }
- else
- {
- HandleError("CryptExportKey 导出会话密钥到简单密钥数据块中失败");
- }
- //释放交换密钥句柄.
- if( hXchgKey )
- {
- if(!(CryptDestroyKey(hXchgKey)))
- {
- HandleError("CryptDestroyKey 释放交换密钥句柄失败");
- }
- else
- MyOutputInfoMessage( "释放交换密钥句柄成功" );
- hXchgKey = 0;
- }
- // 写密钥块长度到目标文件.
- fwrite( &dwKeyBlobLen, sizeof(DWORD), 1, hDestination );
- if( ferror( hDestination ) )
- {
- HandleError("写密钥块长度出错");
- }
- else
- {
- MyOutputInfoMessage( "密钥块长度已经被写入" );
- }
- //写密钥块数据到目标文件.
- fwrite( pbKeyBlob, 1, dwKeyBlobLen, hDestination );
- if( ferror( hDestination ) )
- {
- HandleError( "写密钥数据出错" );
- }
- else
- {
- MyOutputInfoMessage( "此密钥块数据已经被写入目标文件" );
- }
- // 释放内存空间.
- free(pbKeyBlob);
- //返回创建的会话密钥
- return hKey;
- }
- BOOL MyEncryptFile( char* szSource, char* szDestination, char* szPassword )
- {
- FILE *hSource;
- FILE *hDestination;
- HCRYPTPROV hCryptProv;
- HCRYPTKEY hKey;
- PBYTE pbBuffer;
- DWORD dwBlockLen;
- DWORD dwBufferLen;
- DWORD dwCount;
- char cInfo[ MAX_INFO_LENGTH ] = { 0 };
- // 打开原文文件.
- hSource = fopen( szSource,"rb" );
- if ( hSource )
- {
- memset( cInfo, 0, sizeof( cInfo ) );
- sprintf_s( cInfo, sizeof( cInfo ) - 1, "原文文件 %s 已经打开", szSource );
- MyOutputInfoMessage( cInfo );
- }
- else
- {
- HandleError("打开原文文件出错!");
- }
- // 打开目标文件.
- hDestination = fopen(szDestination,"w+");
- if( hDestination )
- {
- memset( cInfo, 0, sizeof( cInfo ) );
- sprintf_s( cInfo, sizeof( cInfo ) - 1, "目标文件 %s 已经打开", szDestination );
- MyOutputInfoMessage( cInfo );
- }
- else
- {
- MyOutputInfoMessage( "文件不存在,创建文件" );
- }
- //获取加密服务者句柄
- hCryptProv = GetCryptProv();
- // 创建会话密钥.
- if( !szPassword || strcmp(szPassword,"")==0 )
- {
- // 当输入密码为空时,则创建随机的加密密钥,并导出创建的密钥保存到文件中.
- hKey = GenKeyByRandom( hCryptProv, hDestination);
- }
- else
- {
- hKey = GetKeyByPassword( hCryptProv, szPassword);
- }
- // 因为加密算法按ENCRYPT_BLOCK_SIZE 大小块加密,所以被加密的
- // 数据长度必须是ENCRYPT_BLOCK_SIZE 的整数倍。下面计算一次加密的
- // 数据长度。
- dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
- // 确定加密后密文数据块大小. 若是分组密码模式,则必须有容纳额外块的空间
- if( ENCRYPT_BLOCK_SIZE > 1 )
- dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
- else
- dwBufferLen = dwBlockLen;
- // 分配内存空间.
- if( pbBuffer = (BYTE*)malloc( dwBufferLen ) )
- {
- MyOutputInfoMessage( "已经为缓冲区分配了内存" );
- }
- else
- {
- HandleError( "所需内存不够" );
- }
- // 循环加密 原文件
- while( !feof(hSource) )
- {
- // 每次从原文件中读取dwBlockLen字节数据.
- dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
- if( ferror(hSource) )
- {
- HandleError("读取明文文件出错");
- }
- // 加密数据.
- if( !CryptEncrypt(
- hKey, //密钥
- 0, //如果数据同时进行散列和加密,这里传入一个散列对象
- feof(hSource), //如果是最后一个被加密的块,输入TRUE.如果不是输入FALSE.
- //这里通过判断是否到文件尾来决定是否为最后一块。
- 0, //保留
- pbBuffer, //输入被加密数据,输出加密后的数据
- &dwCount, //输入被加密数据实际长度,输出加密后数据长度
- dwBufferLen)) //pbBuffer的大小。
- {
- HandleError("CryptEncrypt 加密失败");
- }
- // 把加密后数据写到密文文件中
- fwrite(pbBuffer, 1, dwCount, hDestination);
- if( ferror(hDestination) )
- {
- HandleError("写入密文时出错");
- }
- }
- // 关闭文件
- if( hSource )
- {
- if(fclose(hSource))
- {
- HandleError("关闭源文文件出错!");
- }
- }
- if( hDestination )
- {
- if(fclose(hDestination))
- {
- HandleError("关闭目标文件出错!");
- }
- }
- // 释放内存空间.
- if(pbBuffer)
- free(pbBuffer);
- // 销毁会话密钥
- if ( hKey )
- {
- if( !CryptDestroyKey( hKey ) )
- {
- HandleError("CryptDestroyKey 会话密钥失败");
- }
- }
- // 释放CSP句柄
- if ( hCryptProv )
- {
- if( !CryptReleaseContext(hCryptProv, 0) )
- {
- HandleError("CryptReleaseContext 释放CSP句柄失败");
- }
- }
- return(TRUE);
- }
- HCRYPTKEY GenKeyFromFile(HCRYPTPROV hCryptProv,FILE* hSource)
- {
- HCRYPTKEY hKey;
- PBYTE pbKeyBlob;
- DWORD dwKeyBlobLen;
- //从密文文件中获取密钥数据块长度,并分配内存空间.
- 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("读取密文文件中密钥数据块出错!\n");
- }
- //--------------------------------------------------------------------
- // 导入会话密钥到 CSP.
- if(!CryptImportKey(
- hCryptProv,
- pbKeyBlob,
- dwKeyBlobLen,
- 0,
- 0,
- &hKey))
- {
- HandleError("Error during CryptImportKey!");
- }
- if(pbKeyBlob)
- free(pbKeyBlob);
- //返回导出的会话密钥
- return hKey;
- }
- BOOL MyDecryptFile( char* szSource, char* szDestination, char* szPassword)
- {
- //--------------------------------------------------------------------
- // 局部变量申明与初始化.
- FILE *hSource;
- FILE *hDestination;
- HCRYPTPROV hCryptProv;
- HCRYPTKEY hKey;
- PBYTE pbBuffer;
- DWORD dwBlockLen;
- DWORD dwBufferLen;
- DWORD dwCount;
- BOOL status = FALSE;
- //--------------------------------------------------------------------
- // 打开密文文件.
- if(!(hSource = fopen(szSource,"rb")))
- {
- HandleError("打开密文文件出错!");
- }
- //--------------------------------------------------------------------
- // 打开目标文件,用于存储解密后的数据.
- hDestination = fopen( szDestination,"w+" );
- if( !hDestination )
- {
- HandleError("打开明文文件出错!");
- }
- //获取加密服务者句柄
- hCryptProv = GetCryptProv();
- //获取或创建会话密钥
- if(!szPassword|| strcmp(szPassword,"")==0 )
- {
- //--------------------------------------------------------------------
- //从密文文件导入保存的会话密钥
- hKey = GenKeyFromFile( hCryptProv,hSource);
- }
- else
- {
- //--------------------------------------------------------------------
- // 通过输入密码重新创建会话密钥.
- hKey = GetKeyByPassword( hCryptProv, szPassword);
- }
- // 计算一次解密的数据长度,它是ENCRYPT_BLOCK_SIZE 的整数倍
- dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
- dwBufferLen = dwBlockLen;
- //--------------------------------------------------------------------
- // 分配内存空间.
- if(!(pbBuffer = (BYTE *)malloc(dwBufferLen)))
- {
- HandleError("所需内存不够!\n");
- }
- //--------------------------------------------------------------------
- // 解密密文文件,解密后数据保存在目标文件
- do {
- //--------------------------------------------------------------------
- // 每次从密文文件中读取dwBlockLen字节数据.
- dwCount = fread(
- pbBuffer,
- 1,
- dwBlockLen,
- hSource);
- if(ferror(hSource))
- {
- HandleError("读取密文文件出错!");
- }
- //--------------------------------------------------------------------
- // 解密 数据
- if(!CryptDecrypt(
- hKey,
- 0,
- feof(hSource),
- 0,
- pbBuffer,
- &dwCount))
- {
- HandleError("Error during CryptDecrypt!");
- }
- //--------------------------------------------------------------------
- // 把解密后的数据写入目标文件中.
- fwrite(
- pbBuffer,
- 1,
- dwCount,
- hDestination);
- if(ferror(hDestination))
- {
- HandleError("Error writing plaintext!");
- }
- } while(!feof(hSource));
- status = TRUE;
- //--------------------------------------------------------------------
- // 关闭文件
- if(hSource)
- {
- if(fclose(hSource))
- HandleError("关闭原文件出错");
- }
- if(hDestination)
- {
- if(fclose(hDestination))
- HandleError("关闭目标文件出错");
- }
- //--------------------------------------------------------------------
- // 释放内存空间
- if(pbBuffer)
- free(pbBuffer);
- //--------------------------------------------------------------------
- // 销毁会话密钥
- if(hKey)
- {
- if(!(CryptDestroyKey(hKey)))
- HandleError("Error during CryptDestroyKey");
- }
- //--------------------------------------------------------------------
- // 释放CSP句柄
- if(hCryptProv)
- {
- if(!(CryptReleaseContext(hCryptProv, 0)))
- HandleError("Error during CryptReleaseContext");
- }
- return status;
- } // end Decryptfile
- #endif
复制代码 其中MyOutputInfoMessage函数为我自己定义的一个打印Log的函数,在一个ListBox上输出所有的提示信息,不然用MessageBox太恶心了,这点大家可以用别的方式实现,就不贴MFC部分的代码了。
本文固定链接: http://www.cppfans.org/985.html | C++爱好者博客™
|
|