使用WinCrypt进行简单的对称加密实例
2008年12月16日星期二
http://blog.csdn.net/lixiaomin_235/article/details/3532397
微软在wincrypt.h中定义了大量的加解密算法的API,方便了软件加解密的实现,可以使我们不必关注密码学的算法,就可以实现高效率的软件加密。下面通过一个类,对API实现简单的封装。详细代码如下:
头文件:MyCryptOpt.h
#pragma once
#include "windows.h"
#include "wincrypt.h"
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#define KEYLENGTH 0x00800000
#define ENCRYPT_ALGORITHM CALG_RC4
#define ENCRYPT_BLOCK_SIZE 8
class CMyCryptOpt
{
public:
CMyCryptOpt(void);
~CMyCryptOpt(void);
BOOL InitCrypt();
void DestroyCrypt();
BOOL MyEncryptFile(LPSTR lpSourceFile, LPSTR lpDestFile, LPSTR lpPassword);
BOOL MyDecryptFile(LPSTR lpSourceFile, LPSTR lpDestFile, LPSTR lpPassword);
protected:
BOOL CryptProcess(LPSTR lpSourceFile, LPSTR lpDestFile, LPSTR lpPassword);
private:
FILE *m_hSource;
FILE *m_hDestination;
HCRYPTPROV m_hCryptProv;
HCRYPTKEY m_hKey;
HCRYPTHASH m_hHash;
PBYTE m_pbBuffer;
DWORD m_dwBlockLen;
DWORD m_dwBufferLen;
DWORD m_dwCount;
};
源文件:MyCryptOpt.cpp
#include "StdAfx.h"
#include "MyCryptOpt.h"
CMyCryptOpt::CMyCryptOpt(void)
{
}
CMyCryptOpt::~CMyCryptOpt(void)
{
}
BOOL CMyCryptOpt::InitCrypt()
{
// 获得一个CSP句柄
if (!CryptAcquireContext(&m_hCryptProv,NULL,NULL,PROV_RSA_FULL,0))
{
if (!CryptAcquireContext(
&m_hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
OutputDebugString("CryptAcquireContext() error!");
return FALSE;
}
}
// 创建一个会话密钥
if (!CryptCreateHash(
m_hCryptProv,
CALG_MD5,
0,
0,
&m_hHash))
{
OutputDebugString("CryptCreateHash() error!");
return FALSE;
}
return TRUE;
}
void CMyCryptOpt::DestroyCrypt()
{
// close files
if (m_hSource)
fclose(m_hSource);
if (m_hDestination)
fclose(m_hDestination);
// free memory
if (m_pbBuffer)
free(m_pbBuffer);
// destroy session key
if (m_hKey)
CryptDestroyKey(m_hKey);
// destroy hash object
CryptDestroyHash(m_hHash);
m_hHash = NULL;
// Release provider handle
if (m_hCryptProv)
CryptReleaseContext(m_hCryptProv,0);
}
BOOL CMyCryptOpt::MyEncryptFile(LPSTR lpSourceFile, LPSTR lpDestFile, LPSTR lpPassword)
{
// process for encrypt
if (!CryptProcess(lpSourceFile,lpDestFile,lpPassword))
return FALSE;
// 加密源文件,并将加密后数据写入目标文件
do
{
// read source file
m_dwCount = fread(m_pbBuffer,1,m_dwBlockLen,m_hSource);
if (ferror(m_hSource))
{
OutputDebugString("读写源文件错误!");
return FALSE;
}
// encrypt data
if (!CryptEncrypt(
m_hKey,
0,
feof(m_hSource),
0,
m_pbBuffer,
&m_dwCount,
m_dwBufferLen))
{
OutputDebugString("CryptEncrypt() failed!");
return FALSE;
}
// write data to file
fwrite(m_pbBuffer,1,m_dwCount,m_hDestination);
if (ferror(m_hDestination))
{
OutputDebugString("write file error!");
return FALSE;
}
}
while (!feof(m_hSource));
return TRUE;
}
BOOL CMyCryptOpt::MyDecryptFile(LPSTR lpSourceFile, LPSTR lpDestFile, LPSTR lpPassword)
{
// process for decrypt
if (!CryptProcess(lpSourceFile,lpDestFile,lpPassword))
return FALSE;
// 解密源文件,并将解密后数据写入目标文件
do
{
// read source file
m_dwCount = fread(m_pbBuffer,1,m_dwBlockLen,m_hSource);
if (ferror(m_hSource))
{
OutputDebugString("读写源文件错误!");
return FALSE;
}
// decrypt data
if (!CryptDecrypt(
m_hKey,
0,
feof(m_hSource),
0,
m_pbBuffer,
&m_dwCount))
{
OutputDebugString("CryptEncrypt() failed!");
return FALSE;
}
// write data to file
fwrite(m_pbBuffer,1,m_dwCount,m_hDestination);
if (ferror(m_hDestination))
{
OutputDebugString("write file error!");
return FALSE;
}
}
while (!feof(m_hSource));
return TRUE;
}
BOOL CMyCryptOpt::CryptProcess(LPSTR lpSourceFile, LPSTR lpDestFile, LPSTR lpPassword)
{
// 打开要加密的源文件
m_hSource = fopen(lpSourceFile,"rb");
if (!m_hSource)
{
OutputDebugString("open source file failed!");
return FALSE;
}
// 打开加密后产生的目标文件
m_hDestination = fopen(lpDestFile,"wb");
if (!m_hDestination)
{
OutputDebugString("open destination file failed!");
return FALSE;
}
// 用输入的密码产生一个散列
if (!CryptHashData(
m_hHash,
(BYTE*)lpPassword,
strlen(lpPassword),
0))
{
OutputDebugString("CryptHashData() failed!");
return FALSE;
}
// 通过散列生成会话密钥
if (!CryptDeriveKey(
m_hCryptProv,
ENCRYPT_ALGORITHM,
m_hHash,
KEYLENGTH,
&m_hKey))
{
OutputDebugString("CryptDeriveKey() failed!");
return FALSE;
}
// 因为加密算法是按ENCRYPT_BLOCK_SIZE 大小的块加密的,所以被加密的
// 数据长度必须是ENCRYPT_BLOCK_SIZE 的整数倍。下面计算一次加密的
// 数据长度。
m_dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
// Determine the block size. If a block cipher is used,
// it must have room for an extra block.
if (ENCRYPT_BLOCK_SIZE > 1)
{
m_dwBufferLen = m_dwBlockLen + ENCRYPT_BLOCK_SIZE;
}
else
{
m_dwBufferLen = m_dwBlockLen;
}
// 为缓冲区分配内存
m_pbBuffer = (BYTE*)malloc(m_dwBufferLen);
if (!m_pbBuffer)
{
OutputDebugString("分配内存错误!");
return FALSE;
}
return TRUE;
}