简单实现强大的加密功能——CryptoAPI

CryptoAPI是Microsoft提供的加密应用程序接口,他其实是一组函数,他为许多高级安全性服务提供了基础,包括用于电子商务的SET,用于加密客户机/服务器消息的PCT,用于在各个平台之间来回传递机密数据和密钥的PFX,代码签名等等。 
支持这种功能的主要有2000/XP(98和ME下不详) 

其配置信息(密钥)主要在 
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft 
\ Cryptography \Defaults 
HKEY_CURRENT_USER\ Software \ Microsoft 
\ Cryptography \Providers 
中, 


下面以两个文件加密与解密的C程序片断为例,演示一下CryptoAPI的强大功能。这两个程序均为Win32控制台应用,程序省略了出错处理,实际运行时请加入。 

----1. 文件加密 

#include 
#include 
#include 
#include 

//确定使用RC2块编码或是RC4流式编码,这就是CryptoAPI支持的两种基本编码方式 

#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 

void CAPIDecryptFile(PCHAR szSource, 
PCHAR szDestination, PCHAR szPassWord); 

void _cdecl main(int argc, char *argv[]) 

PCHAR szSource  = NULL; 
PCHAR szDestination = NULL; 
PCHAR szPassword  = NULL; 

// 验证参数个数 
if(argc != 3 && argc != 4) { 
printf(“USAGE: decrypt < source file > 
< dest file > [ ]\n"); 
exit(1); 


//读取参数. 
szSource  = argv[1]; 
szDestination = argv[2]; 
if(argc == 4) { 
szPassword = argv[3]; 

CAPIDecryptFile(szSource, szDestination, szPassword); 


/*szSource为要加密的文件名称, 
szDestination为加密过的文件名称, 
szPassword为加密口令*/ 
void 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"));// 打开源文件 
hDestination = fopen(szDestination,“wb") ;//.打开目标文件 
// 连接缺省的CSP,密码服务提供者模块(CSP),这是通过WIN系统中捆绑的RSA Base Provider实现的。 
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=malloc(dwKeyBlobLen)) == NULL) ; 
// 将会话密钥输出至隐码 
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, szPassword, strlen(szPassword), 0); 
//散列口令 
// 从散列表中派生密钥 
CryptDeriveKey(hProv, ENCRYPT_ALGORITHM, hHash, 0, &hKey); 
// 删除散列表 
CryptDestroyHash(hHash); 
hHash = 0; 


//计算一次加密的数据字节数, 
必须为ENCRYPT_BLOCK_SIZE的整数倍 
dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE; 
//如果使用块编码,则需要额外空间 
if(ENCRYPT_BLOCK_SIZE > 1) { 
dwBufferLen=dwBlockLen + ENCRYPT_BLOCK_SIZE; 
} else { 
dwBufferLen = dwBlockLen; 

//分配缓冲区 
pbBuffer = 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)); 
printf("OK\n"); 
......//关闭文件、释放内存 

----2 文件解密 

void CAPIDecryptFile(PCHAR szSource, 
PCHAR szDestination, PCHAR szPassword) 


   ......//变量声明、文件操作同文件加密程序 

CryptAcquireContext(&hProv, NULL, NULL, 
PROV_RSA_FULL, 0); 
if(szPassword == NULL) { 
// 口令为空,使用存储在加密文件中的会话密钥解密 
// 读隐码的长度并分配内存 
fread(&dwKeyBlobLen,sizeof(DWORD),1,hSource); 
pbKeyBlob=malloc(dwKeyBlobLen))== NULL); 
// 从源文件中读隐码. 
fread(pbKeyBlob, 1, dwKeyBlobLen, hSource); 
// 将隐码输入CSP 
CryptImportKey(hProv, pbKeyBlob, 
dwKeyBlobLen, 0, 0, &hKey); 
} else { 
// 口令不为空, 使用从口令派生出的密钥解密文件 
CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash); 
CryptHashData(hHash, 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 = 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)); 
printf(“OK\n"); 
......//关闭文件、释放内存 

----以上代码在windows 2000、Visual C++6.0环境中编译通过。

你可能感兴趣的:(C/C++)