当前位置:天才代写 > tutorial > C语言/C++ 教程 > 用CryptoAPI举办数据加密

用CryptoAPI举办数据加密

2017-11-05 08:00 星期日 所属: C语言/C++ 教程 浏览:1091

副标题#e#

因为过于巨大的加密算法实现起来很是坚苦,所以在已往,很多应用措施只能利用很是简朴的加密技能,这样做的功效就是加密的数据很容易就可以被人破译。而利用Microsoft提供的加密应用措施接口(即Cryptography API),或称CryptoAPI,就可以利便地在应用措施中插手强大的加密成果,而不必思量根基的算法。本文将对CryptoAPI及其利用的数据加密道理作一简朴的先容,然后给出了用CryptoAPI编写加密措施的大抵步调,最后以一个文件的加密、解密措施为例演示了CryptoAPI的部门成果。

1. CryptoAPI简介

CryptoAPI是一组函数,为了完成数学计较,必需具有暗码处事提供者模块(CSP)。Microsoft通过绑缚RSA Base Provider在操纵系统级提供一个CSP,利用RSA公司的公钥加密算法,更多的CSP可以按照需要增加到应用中。事实上,CSP有大概与非凡硬件设备(如智能卡)一起来举办数据加密。CryptoAPI接口答允简朴的函数挪用来加密数据,互换公钥,散列一个动静来成立摘要以及生成数字签名。它还提供高级的打点操纵,如从一组大概的CSP中利用一个CSP。另外,CryptoAPI还为很多高级安详性处事提供了基本,包罗用于电子商务的SET,用于加密客户机/处事器动静的PCT,用于在各个平台之间往返通报机要数据和密钥的PFX,代码签名等等。CryptoAPI的体系布局如下图:

用CryptoAPI举行数据加密

今朝支持CryptoAPI的Windows系统有:Windows 95 OSR2、Windows NT SP3及后续版本、Windows 98、Windows 2000等。CryptoAPI的设置信息存储在注册表中,包罗如下密钥:

HKEY_LOCAL_MACHINE\SOFTWARE\
Microsoft \ Cryptography \Defaults
HKEY_CURRENT_USER\ Software \ Microsoft
\ Cryptography \Providers


#p#副标题#e#

2.数据加密道理

数据加密的流程如下图:

用CryptoAPI举行数据加密

CryptoAPI利用两种密钥:会话密钥与民众/私人密钥对。会话密钥利用沟通的加密息争密密钥,这种算法较快,但必需担保密钥的安详通报。民众/私人密钥对利用一个民众密钥和一个私人密钥,私人密钥只有专人才气利用,民众密钥可以遍及流传。假如密钥对中的一个用于加密,另一个必然用于解密。民众/私人密钥对算法很慢,一般只用于加密小批数据,譬喻用于加密会话密钥。

CryptoAPI支持两种根基的编码要领:流式编码和块编码。流式编码在明码文本的每一位上建设编码位,速度较快,但安详性较低。块编码在一个完整的块上(一般为64位)上事情,需要利用填充的要领对要编码的数据举办舍入,以构成多个完整的块。这种算法速度较慢,但更安详。

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 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 > [ < password > ]\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
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");
……//封锁文件、释放内存
  }
②文件解密
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 NT4.0、Visual C++6.0情况中编译通过。

除直接用于加密数据外,CryptoAPI还遍及用于发生并确认数字签名,这里就纷歧一举例说明白,有乐趣的读者可以参考MSDN文档。

 

    关键字:

天才代写-代写联系方式