
作为一部分 Microsoft Windows 提供得听群尔的应用程序编程接口 (API),CryptoAPI 提供了一组函数。这些功能允许应用程序以灵活的方式加密来自或数字签名数据,同时保护用户的敏感私360百科钥数据。实际加密操作由一个称为加密服务提供商(C者秋吸器兰SP)的单独模块执行。
- 中文名称 CryptoAPI
- 全称 加密应用程序接口
- 提供商 Microsoft
- 功能 加密
- 性质 一组函数
加密算法简介
因为过于复杂的加密算法实现起来非常困难,所以在过去,许多应用程序只能使用非常简单的加密技术,这晶春史印况甲叶乙际样做的结果就是加密的数据很容易就可以被人破译。而使用Microsoft提供的加密应用程序接口(即Cryptography API),或称CryptoAPI,就可以方便地在应用程序中加入强大的加密功能,而不必考虑基本的算法。本文将对CryptoAPI及其使用的数据加密原理作一简单的介绍,然后给出了用CryptoAPI编写加密程序的大来自致步骤,最后以一个文件的加密、解密程序为例演示了CryptoAPI的部分功能。
CryptoAPI是一组函数,为了完成数学计算,必须具有密码服务提供者模块(CSP)。Microsoft通过捆绑RSA Base P360百科rovider在操作系统级提供一个CSP,使用RSA公司的公钥加密算法,更多的CSP可以根据需要增加到应用中。事实上,CSP有可能与特殊硬件设备(如智能卡)一起来进行数据加密。CryptoAPI接口允许简单的函数调用来加密数据,交换公钥,散列一个消息来建立摘要以及生成数字签名。它还提点哥定同始而赶保供高级的管理操作,如从一组可能的CSP中使用一个CSP。此外,Cryp便toAPI还为许多高级安全性服务提供了基础,包括用于电子商务的SET,用于加密客户机/服务器消息何的PCT,用于在各个平台备引施作之间来回传递机密数据和密钥的PFX,代码签名等等。CryptoAPI的体系结构如下图:
目前支持CryptoAPI的Windows系统有:Windo位处照河轴显川画适ws 95 OSR2、Wi念谓ndows NT SP3及后续版本、Windows 98、W春甚校标呢认神敌indows 2000等。CryptoAPI的配置信息存储在注册表中,包括如下密钥:
HKEY_LOCAL_MACHINE\SOFTWAR风愿停功盾此飞误半李句E\
Microsoft Cryptography Defaults
HKEY_C责且风孩烟URRENT_USER Software Mic系发rosoft
Cr良任值编下察即yptography Providers2.数据加密原理
加密流程
数据加密的流程
数据加密的流程如下图:
CryptoAPI使用两种密钥:会话密钥与公共/私人密钥对。会话密钥使用相同的加密和解密密钥,师看祖菜势协企茶危这种算法较快,但必须保证密钥的安全传递。公共/私人密钥对使用一个公共密钥和一个私人密钥,私伯附命件和境罪力剂变人密钥只有专人才能使用,公共密钥可以广泛传播。如果密钥对中的一个用于加密,另一个一定用于解密。公共/私人密钥对算法很慢,一般只用于加密小批数据,例如用于加密会话密钥。
CryptoAPI支持两种基本的编码方法:流式编码和块编码。流式编码在明码文本的每一位上创建编码位,速度较快,但安全性较低。块编码在一个完整的块上(一般为64位)工作,需要使用填充的方法对要编码的数据进行舍入,以组成多个完整的块。这种算法速小尼度较慢,但更安全。
应用
Cryp义养况面toAPI函数使用"加密服务提供者"(CSP)完成数据加密、解密以及密钥的存储管理、所有的CSP都是相互来自独立的模块。理论上,CSP应该独立于特定的应用程序,也就是说360百科所有的应用程序可以使用任何一个换快CSP。但是,实际上有些应用程序只能与特定的CSP协作。CSP与应用程序之间的关系类似于Windows GDI模型。CSP就类似于图形硬件驱动程序。

密钥存储的安全性完全取决于CSP的具体实现和操等设压作系统没有任何关系。这就使得应用程序无需修改就可以运行于多种安全环境之下。
应用程序于机密模块之间的访问控制必须受到严格的控制。只要这样才能保证应用的安全性和移植性。要遵循以下三条原则:
1)、应用程序不能直接访问密钥的内容。因为所有密钥都是在CSP内部产生的,应用程序通过不透明强量自每画短开的句柄进行访问。这就避免了应用程序和其相关联的动态连接库泄密密钥或使用不好的随机数产生密钥的济呀赶验万音点担第等怕可能性。
2)、应用程序不能指定加密操作细节。CSP允许应用程序选择进行加密或者签名操作使用的算法类型,但是实际的操作完全由CSP内部进行控制。
3)、应用程序不处理用户的信任凭证或其它身份鉴别数据。用户的鉴别是由CSP完成的。因此,对于未来可能出现的身份验证方式,例如者军延杨自钱或参特格队人体识别技术,应了庆了轮树们运胡盟胞用程序无需修改其身份验证的模型县则密。
应用举例
3.应用举例
下面以两个文件加密与解密的C程序片断为例,演示一下CryptoAPI的强大功能。这两个程序均为Win32控制台应用水重永,程序省略了出错处理,实际运行时请加入。
①文件加密
#include < windows.h >
#include < stdio.h >
#include < stdlib.h >
#include < wincrypt.h >
//确定使用RC2块编码或是RC4流式编码
#ifdef USE_BLOCK_CIPHER
#define ENCRYPT_ALGORITHMCALG_RC2
#define ENCRYPT_BLOCK_SIZE8
#else
#define ENCRYPT_ALGORITHMCALG_RC4
#define ENCRYPT_BLOCK_SIZE1
导事失静 #endif
void CAPIEncryptFile(PCHAR szSource,
PCHAR szDestination, P货杆乎CHAR szPassword);
void _cdecl main(int argc, char *argv[])
{
PCH有AR szSource= NULL;
PCHAR szDestination = NULL;
PCHAR sz业Password= NULL;
// 验证参数个数
变企世流术曾if(argc != 3 && argc != 4) {
printf("USAGE: decrypt < source file >
< dest file > [ < password > ]
");
exit(1);
}
//读取参数.
szSource = argv[1];
szDestination = argv[讨影令演率绍白些准2];
if(argc == 4) {
szPassword = 又北灯回少本县波娘argv[3];
}
进血践银否CAPIEncryptFile(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
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
");
……//关闭文件、释放内存
}
②文件解密
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
");
……//关闭文件、释放内存
}以上代码在Windows NT4.0、Visual C++6.0环境中编译通过。
其他信息
除直接用于加密数据外,CryptoAPI还广泛用于产生并确认数字签名,这里就不一一举例说明了,有兴趣的读者可以参考MSDN文档。
评论留言