CryptoAPI函数测试实例代码
#include "stdafx.h"
#include "h\util.h"
namespace UI { namespace Util
{
#ifdef UTIL_CRYPT
#include "Wincrypt.h"
#pragma comment(lib, "Crypt32.lib")
//
// 函数: void MD5_Digest( BYTE* bOrign, int nOriLen, CBuffer *pDigestBuf )
//
// 目的: 对给定的字节流做摘要
//
// 参数:
// bOrign
// [in]: 要做摘要的字节流
// nOriLen
// [in]: szOrign字节流的长度
// pDigestBuf
// [out]: 返回摘要值,33位的长度(包括NULL)
//
// 返回: 成功返回TRUE,失败返回FALSE;
//
// 备注: 支持ASCII和UNICODE
//
BOOL MD5_Digest( BYTE* bOrign, int nOriLen, CBuffer *pDigestBuf )
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hHash = NULL;
BOOL bRet = FALSE;
do
{
bRet = ::CryptAcquireContext( &hCryptProv, 0, NULL, PROV_RSA_FULL, 0 );
if( FALSE == bRet )
break;
bRet = ::CryptCreateHash( hCryptProv, CALG_MD5, 0, 0, &hHash );
if( FALSE == bRet )
break;
// 做摘要
::CryptHashData( hHash, bOrign, nOriLen, 0 );
DWORD dwHashLen = 0;
DWORD dwDataLen = sizeof(DWORD);
CBufferT<BYTE> buf;
// 先获取摘要的长度,再分配内存获取摘要值
if( FALSE == ::CryptGetHashParam( hHash, HP_HASHSIZE, (BYTE*)&dwHashLen, &dwDataLen, 0 ) )
break;
buf.malloc( dwHashLen );
dwDataLen = dwHashLen;
if( FALSE == ::CryptGetHashParam( hHash, HP_HASHVAL, buf, &dwDataLen, 0 ) )
break;
B2HS( (BYTE*)buf, buf.GetBufSize(), *pDigestBuf );
bRet = TRUE;
}
while(false);
if( hHash )
::CryptDestroyHash( hHash );
if( hCryptProv )
::CryptReleaseContext( hCryptProv, 0 );
return bRet;
}
//
// 函数: void MD5_String_Digest( TCHAR* str, CBuffer* pDigestBuf )
//
// 目的: 对给定的字符串做摘要
//
// 参数:
// str
// [in]: 要做摘要的字符串,兼容ASCII和UNICODE,对于UNICODE,
// 是将其转换为ASCII。因为做摘要它只是针对BYTE而言
// pDigestBuf
// [out]: 返回摘要值,33位的长度(包括NULL)
//
// 返回: 成功返回TRUE,失败返回FALSE;
//
// 备注: 内部调用MD5_Digest
//
BOOL MD5_String_Digest( TCHAR* str, CBuffer* pDigestBuf )
{
#ifdef _UNICODE
CBufferT<char> buf;
U2A( str, buf );
return MD5_Digest( (BYTE*)(char*)buf, wcslen(str), pDigestBuf );
#else
return MD5_Digest( (BYTE*)str, strlen( str ), pDigestBuf );
#endif
}
//
// 函数: BOOL MD5_File_Digest( TCHAR* szPath, CBuffer* pDigestBuf )
//
// 目的: 对一个文件做摘要
//
// 参数:
// szPath
// [in]: 要做摘要的文件路径
// pDigestBuf
// [out]: 返回摘要内容
//
// 返回: 成功返回TRUE,失败返回FALSE;
//
BOOL MD5_File_Digest( TCHAR* szPath, CBuffer* pDigestBuf )
{
CBufferT<char> fileBuf;
if( FALSE == GetFileBuffer( szPath, fileBuf ) )
return FALSE;
return MD5_Digest( (BYTE*)(char*) fileBuf, fileBuf.GetBufSize(), pDigestBuf );
}
//
// 函数: void Encrypt( BYTE* bOrign, int nOriLen, TCHAR* szPassword, CBuffer* pEncryptBuf )
//
// 目的: 对字节流使用指定的密码进行加密
//
// 参数:
// bOrign
// [in]: 要加密的字节流
// nOriLen
// [in]: 要加密的字节流的长度
// szPassword
// [in]: 加密所用的密码
// pEncryptBuf
// [out]: 返回加密后的内容
//
// 备注: 该函数尚未完成
//
void Encrypt( BYTE* bOrign, int nOriLen, TCHAR* szPassword, CBuffer* pEncryptBuf )
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hHash = NULL;
HCRYPTKEY hKey = NULL;
BOOL bRet = FALSE;
do
{
bRet = ::CryptAcquireContext( &hCryptProv, 0, NULL, PROV_RSA_FULL, 0 );
if( FALSE == bRet )
break;
bRet = ::CryptCreateHash( hCryptProv, CALG_MD5, 0, 0, &hHash );
if( FALSE == bRet )
break;
// 对密码做一次HASH,用于产生会话密钥
#ifdef _UNICODE
CBufferT<char> pswdBuf;
U2A( szPassword, pswdBuf );
::CryptHashData( hHash, (BYTE*)(char*)pswdBuf, pswdBuf.GetBufSize()-1, 0 );
#else
::CryptHashData( hHash, (BYTE*)szPassword, strlen(szPassword), 0 );
#endif
bRet = ::CryptDeriveKey( hCryptProv, CALG_RC2, hHash, 0x00800000|CRYPT_EXPORTABLE, &hKey );
if( FALSE == bRet )
break;
::CryptDestroyHash( hHash );
hHash = NULL;
const int ENCRYPT_BLOCK_SIZE = 8;
DWORD dwBufferLen = 1000 - 1000%8 + 8; // 每次加密的字节数
DWORD dwEncrypt = 0; // 到目前为止加密了多少数据
do
{
BOOL bFinal = dwEncrypt + dwBufferLen >= (DWORD)nOriLen;
DWORD dwDataLen = bFinal? nOriLen-dwEncrypt : dwBufferLen;
bRet = ::CryptEncrypt( hKey, 0, bFinal, 0, bOrign+dwEncrypt, &dwDataLen, dwDataLen );
if( FALSE == bRet )
{
DWORD dwErr = ::GetLastError();
break;
}
dwEncrypt += dwBufferLen;
if( bFinal )
break;
}
while( true );
}
while( false );
if( hKey )
::CryptDestroyKey( hKey );
if( hHash )
::CryptDestroyHash( hHash );
if( hCryptProv )
::CryptReleaseContext( hCryptProv, 0 );
}
//
// 函数:DWORD WINAPI ImportRootCertAutoClickProc( LPVOID lpParameter )
//
// 目的:在导入一个根证书的时候,由程序来自动点击确定按钮
//
DWORD WINAPI ImportRootCertAutoClickProc( LPVOID lpParameter )
{
int nRetryTimes = 20;
int nSleepTime = 200;
HWND hWnd = NULL;
bool bFinish = false;
TCHAR titleR[64] = _T("根证书存储"); // 卸载根证书的对话框标题
TCHAR titleI_xp[64] = _T("安全警告"); // xp下,导入根证书的对话框标题
TCHAR titleI_win7[64] = _T("安全性警告"); // win7下,导入根证书的对话框标题
for( int i = 0; i < nRetryTimes; i++ )
{
if( bFinish )
break;
Sleep(nSleepTime);
hWnd = FindWindow( _T("#32770"), titleR );
if( !hWnd)
{
HWND hWndXp = FindWindow( _T("#32770"), titleI_xp );
HWND hWndWin7 = FindWindow( _T("#32770"), titleI_win7 );
if( hWndXp != NULL || hWndWin7 != NULL )
{
bFinish = true;
hWnd = ( hWndXp == NULL ? hWndWin7:hWndXp );
}
else
continue;
}
SendMessage(hWnd, WM_COMMAND, MAKELONG(IDYES, BN_CLICKED), (long)GetDlgItem( hWnd, IDYES ));
}
return 0;
}
//
// 函数:DWORD WINAPI RemoveRootCertAutoClickProc( LPVOID lpParameter )
//
// 目的:在删除一个根证书的时候,由程序来自动点击确定按钮
//
DWORD WINAPI RemoveRootCertAutoClickProc( LPVOID lpParameter )
{
int nRetryTimes = 20;
int nSleepTime = 200;
HWND hWnd = NULL;
bool bFinish = false;
TCHAR titleR[64] = _T("根证书存储"); // 卸载根证书的对话框标题
for( int i = 0; i < nRetryTimes; i++ )
{
Sleep(nSleepTime);
hWnd = FindWindow( _T("#32770"), titleR );
if( hWnd)
{
SendMessage(hWnd, WM_COMMAND, MAKELONG(IDYES, BN_CLICKED), (long)GetDlgItem( hWnd, IDY补充:软件开发 , C++ ,