cpp文件
// EncryptFile.cpp: implementation of the CEncryptFile class.
//
//////////////////////////////////////////////////////////////////////#include "stdafx.h"
#include "MyCQ.h"
#include "EncryptFile.h"#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////CEncryptFile::CEncryptFile()
{}CEncryptFile::~CEncryptFile()
{}bool CEncryptFile::CAPIEncryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword)
{
FILE *hSource = NULL;
FILE *hDestination = NULL;
INT eof = 0;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
HCRYPTKEY hXchgKey = 0;
HCRYPTHASH hHash = 0;
PBYTE pbKeyBlob = NULL;
DWORD dwKeyBlobLen;
PBYTE pbBuffer = NULL;
DWORD dwBlockLen;
DWORD dwBufferLen;
DWORD dwCount; hSource= fopen(szSource,"rb");// 打开源文件
if (hSource != NULL)
{
hDestination = fopen(szDestination,"wb") ;//.打开目标文件
if (hDestination != NULL)
{
// 连接缺省的CSP
CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0);
if(szPassword == NULL) 
{
//口令为空,使用随机产生的会话密钥加密
// 产生随机会话密钥。
CryptGenKey(hProv, ENCRYPT_ALGORITHM, CRYPT_EXPORTABLE, &hKey);
// 取得密钥交换对的公共密钥
CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hXchgKey);
// 计算隐码长度并分配缓冲区
CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, NULL, &dwKeyBlobLen);
pbKeyBlob=(unsigned char*)malloc(dwKeyBlobLen) ;
// 将会话密钥输出至隐码
CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, pbKeyBlob, &dwKeyBlobLen);
// 释放密钥交换对的句柄
CryptDestroyKey(hXchgKey);
hXchgKey = 0;
// 将隐码长度写入目标文件
fwrite(&dwKeyBlobLen, sizeof(DWORD), 1, hDestination);
//将隐码长度写入目标文件
fwrite(pbKeyBlob,1,dwKeyBlobLen, hDestination);

else 
{
//口令不为空, 使用从口令派生出的密钥加密文件
CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);// 建立散列表
CryptHashData(hHash, (unsigned char*)szPassword, strlen(szPassword), 0); //散列口令
// 从散列表中派生密钥
CryptDeriveKey(hProv, ENCRYPT_ALGORITHM, hHash, 0, &hKey);
// 删除散列表
CryptDestroyHash(hHash);
hHash = 0;
}
//计算一次加密的数据字节数,必须为ENCRYPT_BLOCK_SIZE的整数倍dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
//如果使用块编码,则需要额外空间
dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
if(ENCRYPT_BLOCK_SIZE > 1) 
{
dwBufferLen=dwBlockLen + ENCRYPT_BLOCK_SIZE;

else 
{
dwBufferLen = dwBlockLen;
}
//分配缓冲区
pbBuffer = (unsigned char*)malloc(dwBufferLen);
//加密源文件并写入目标文件
do 
{
// 从源文件中读出dwBlockLen个字节
dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
eof = feof(hSource);
//加密数据
CryptEncrypt(hKey, 0, eof, 0, pbBuffer, &dwCount, dwBufferLen);
// 将加密过的数据写入目标文件
fwrite(pbBuffer, 1, dwCount, hDestination);

while(!feof(hSource));
fclose(hDestination);
}
fclose(hSource);
}
return true;
}bool CEncryptFile::CAPIDecryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword)
{
FILE *hSource = NULL;
FILE *hDestination = NULL;
INT eof = 0;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
HCRYPTKEY hXchgKey = 0;
HCRYPTHASH hHash = 0;
PBYTE pbKeyBlob = NULL;
DWORD dwKeyBlobLen;
PBYTE pbBuffer = NULL;
DWORD dwBlockLen = 0;
DWORD dwBufferLen;
DWORD dwCount;
hSource= fopen(szSource,"rb");// 打开源文件
if (hSource != NULL)
{
hDestination = fopen(szDestination,"wb") ;//.打开目标文件
if (hDestination != NULL)
{
CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0);
if(szPassword == NULL) 
{
// 口令为空,使用存储在加密文件中的会话密钥解密
// 读隐码的长度并分配内存
fread(&dwKeyBlobLen,sizeof(DWORD),1,hSource);
pbKeyBlob=(unsigned char*)malloc(dwKeyBlobLen);
// 从源文件中读隐码.
fread(pbKeyBlob, 1, dwKeyBlobLen, hSource);
// 将隐码输入CSP
CryptImportKey(hProv, pbKeyBlob, dwKeyBlobLen, 0, 0, &hKey);

else 
{
// 口令不为空, 使用从口令派生出的密钥解密文件
CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
CryptHashData(hHash, (const unsigned char*)szPassword, strlen(szPassword), 0);
CryptDeriveKey(hProv, ENCRYPT_ALGORITHM,hHash, 0, &hKey);
CryptDestroyHash(hHash);
hHash = 0;
}
dwBlockLen=1000-1000%ENCRYPT_BLOCK_SIZE;
if(ENCRYPT_BLOCK_SIZE > 1) 
{
dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;

else 
{
dwBufferLen = dwBlockLen;
}
pbBuffer = (unsigned char*)malloc(dwBufferLen);
//解密源文件并写入目标文件
do 
{
dwCount = fread(pbBuffer, 1, dwBlockLen,hSource);
eof = feof(hSource);
// 解密数据
CryptDecrypt(hKey, 0, eof, 0, pbBuffer, &dwCount);
// 将解密过的数据写入目标文件
fwrite(pbBuffer, 1, dwCount, hDestination);

while(!feof(hSource));
fclose(hDestination);
}
fclose(hSource);
}
return true;
}bool CEncryptFile::InitUser()
{
    HCRYPTPROV  hProv;
    HCRYPTKEY  hKey;
    CHAR  szUserName[100];
    DWORD  dwUserNameLen = 100; // 试图获取缺省的密钥容器,若失败,则创建一个缺省容器
if(!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0))
{
//若获取缺省密钥容器发生错误,就创建一个缺省密钥容器, 使用参数CRYPT_NEWKEYSET
if(!CryptAcquireContext(&hProv,NULL,MS_DEF_PROV, PROV_RSA_FULL,CRYPT_NEWKEYSET))
{
AfxMessageBox("创建缺省密钥容器发生错误!");
return false;
}
// 取得缺省密钥容器名
if(!CryptGetProvParam(hProv, PP_CONTAINER, (unsigned char*)szUserName, &dwUserNameLen, 0))
{
// 出错误时容器名置空
szUserName[0] = 0;
}
// printf("Create key container '%s'\n",szUserName);
}
// 试图获取签名密钥的名柄
if(!CryptGetUserKey(hProv, AT_SIGNATURE, &hKey))
{
if(GetLastError() == NTE_NO_KEY)
{     // 创建数字签名密钥对
//printf("Create signature key pair\n");
if(!CryptGenKey(hProv,AT_SIGNATURE,0,&hKey))
{
AfxMessageBox("创建数字签名密钥对发生错误!");
return false;

else
{
CryptDestroyKey(hKey);
}
}
else
{
return false;
}
} // 试图取得交换密钥的句柄,没有交换密钥时,创建交换密钥
if(!CryptGetUserKey(hProv,AT_KEYEXCHANGE,&hKey))
{
if(GetLastError()==NTE_NO_KEY) 
{//没有交换密钥时,创建交换密钥对
//printf("创建交换密钥\n");
if(!CryptGenKey(hProv,AT_KEYEXCHANGE,0,&hKey))
{
//printf("Error %x during CryptGenKey!\n", GetLastError());
return false;
     } 
else 
{
CryptDestroyKey(hKey);
     }
}
else
{
//printf("Error %x during CryptGetUserKey!\n", GetLastError());
return false;
}
    }
CryptReleaseContext(hProv,0); //释放句柄
//printf("OK\n");
return true;}h文件:
// EncryptFile.h: interface for the CEncryptFile class.
//
//////////////////////////////////////////////////////////////////////#if !defined(AFX_ENCRYPTFILE_H__918D0E01_1474_11D5_9F1B_0000E8900D46__INCLUDED_)
#define AFX_ENCRYPTFILE_H__918D0E01_1474_11D5_9F1B_0000E8900D46__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000#include <Wincrypt.h>#ifdef USE_BLOCK_CIPHER
#define ENCRYPT_ALGORITHM CALG_RC2
#define ENCRYPT_BLOCK_SIZE 8
#else
#define ENCRYPT_ALGORITHM CALG_RC4
#define ENCRYPT_BLOCK_SIZE 1
#endif
class CEncryptFile  
{
public:
bool InitUser();
bool CAPIDecryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword);
bool CAPIEncryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword);
CEncryptFile();
virtual ~CEncryptFile();};#endif // !defined(AFX_ENCRYPTFILE_H__918D0E01_1474_11D5_9F1B_0000E8900D46__INCLUDED_)