`

用CryptoAPI进行数据加密

    博客分类:
  • VC
阅读更多

用CryptoAPI进行数据加密

南京理工大学计算机系 
胡静 李蔚清
 
 

---- 因为过于复杂的加密算法实现起来非常困难,所以在过去,许多应用程序只能使用非常简单的加密技术,这样做的结果就是加密的数据很容易就可以被人破译。而使用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的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
---- 2.数据加密原理

---- 数据加密的流程如下图:

---- 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文档。

分享到:
评论

相关推荐

    用 Microsoft CryptoAPI对数据进行加解密

    为了使用CryptoAPI进行数据加密,首先需要创建一个密钥容器并获取相应的CSP句柄。这个过程涉及到指定CSP的名称和类型,进而创建一个唯一的密钥容器来存储加密所需的密钥。例如,在创建一个用于RSA加密的密钥容器时,...

    C语言下CryptoAPI加密系统

    下面将详细介绍如何在C语言中使用CryptoAPI进行加密操作。 首先,使用CryptoAPI需要包含相关的头文件,主要是`windows.h`,因为它包含了CryptoAPI的所有声明。然后,我们需要初始化加密服务提供者(CSP),这是使用...

    Microsoft CryptoAPI加密技术 源代码.zip

    开发者可以调用CryptoAPI提供的函数,如CryptAcquireContext、CryptGenKey、CryptEncrypt等,来获取加密上下文、生成密钥并进行数据加密。 2. **数字签名.cpp**: 数字签名是公钥密码学中的一个重要概念,用于验证...

    基于CryptoAPI 的数据加解密文件.rar

    *CryptoAPI数据加解密,它的流程为: *(加密模块)1.创建会话密钥 2.加密数据 3.安全保存或交换会话密钥 *(解密模块)1.获取会话密钥 2.解密数据 *它的加密是基于对称加密算法的(对称算法加密解密速度快),对...

    在VC++中用CryptoAPI保证安全数据通信

    - **数据加密与解密**:使用CryptoAPI可以对数据进行加密和解密操作,保护数据在传输过程中的安全性。 - **密钥管理**:CryptoAPI还提供了密钥生成、存储和管理等功能。 #### 实现步骤 要在VC++中使用CryptoAPI,...

    CryptoAPI培训教程

    1. ** CryptAcquireContext**:用于获取加密上下文,这是使用CryptoAPI进行任何加密操作的前提。 2. ** CryptCreateHash**:创建一个新的哈希对象,可以使用指定的哈希算法。 3. ** CryptHashData**:将数据添加到...

    Delphi使用CryptoAPI生成证书及PHP(openssl)端签名验签

    - **CryptoApiDemo.zip**:可能是一个包含Delphi项目的压缩包,用于演示如何使用CryptoAPI生成证书和进行验签。 在Delphi端,开发者会调用CryptoAPI函数来生成自签名证书,如`CryptAcquireContext`、`CryptGenKey`...

    CSP开发基础大全(CryptoAPI)

    * CryptoAPI是Win32平台下的数据加密和安全编码接口,提供了基本的ASN.1编码、解码、散列、数据加密和解密、数字证书管理等功能。 * CryptoAPI函数集包含了对称和非对称两类算法的支持。 四、信息隐藏 * 信息隐藏...

    CryptoAPI实例源码

    在"写读这个下下吧.txt"中,可能包含了使用CryptoAPI进行文件读写时加密解密的示例代码。开发者可以通过这个例子学习如何在读取或写入文件前先对数据进行加密,确保数据在传输或存储过程中的安全性。 "CSPtest"和...

    文件的本地加密存储基础CryptoAPI基础

    在CryptoAPI中,可以使用 CryptGenRandom 函数生成一个随机密钥,然后用这个密钥对文件进行加密。加密过程通常是读取文件内容,分块进行加密,最后将加密后的数据写回文件。 接下来,我们关注CryptoAPI中的一个重要...

    windows的cryptoapi接口

    4. **加密/解密**: 使用生成的密钥对数据进行加密或解密。对称加密通常用于大量数据,而非对称加密则用于小量数据或密钥交换。 5. **签名/验证**: 使用私钥进行数字签名,使用公钥验证签名,确保数据的完整性和来源...

    CryptoAPI例子代码

    这个例子代码是一个使用CryptoAPI进行加密和解密的VC6.0工程,它能帮助开发者理解如何在Windows环境中集成加密功能。 在深入讨论CryptoAPI之前,我们先来了解一下加密的基本概念。加密是一种将原始数据(明文)转化...

    信息安全实验:利用Windows CryptoAPI开发加解密工具软件

    通过这个实验,学习者不仅可以掌握CryptoAPI的使用,还能深入了解信息安全的基本原理和实际应用,提升在对称加密、公钥加密及数字签名等方面的技术能力。同时,良好的用户界面设计也是软件成功的关键,它能让用户更...

    MicroSoft CSP CryptoAPI教程

    CryptoAPI提供了基于会话密钥的对称加密方法和基于公钥/私钥的非对称加密方法两种。对称加密使用相同的密钥进行加密和解密,例如AES(高级加密标准)。非对称加密涉及一对密钥,公钥用于加密,私钥用于解密,它们成...

    用CryptoAPI生成密钥的方法

    CryptoAPI(加密应用程序接口)是由微软开发的一套应用程序接口,专门用于数据或文件的加密、解密、数字签名等安全相关操作。这一接口通过调用CSP(Cryptographic Service Provider,加密服务提供者)提供的加密算法...

    CryptoAPI ukey获取证书以及签名流程

    本文整理了如何使用CryptoAPI 操作ukey进行数字签名。附上流程和部分代码,讲解cryptoapi实际应用以及应用中关键问题的解决方法,在这里,仅介绍数字签名(加密流程类似,但是,操作略有不同,所需要的函数也不同),...

    信息安全实验:利用Windows CryptoAPI开发加解密工具软件2

    3. **对称加密**:CryptoAPI提供了各种对称加密算法,如AES(高级加密标准)、DES(数据加密标准)和3DES(三重DES),用于高效地加密大量数据。 4. **非对称加密**:除了对称加密,CryptoAPI还支持RSA、DSA等非...

    crypto_cryptoapi.rar_CRYPTO_Crypto++_cryptoAPI

    本文将深入探讨标题为“crypto_cryptoapi.rar_CRYPTO_Crypto++_cryptoAPI”的主题,该主题涉及到一个用C++编写的加密库,用于封装微软的CryptoAPI(Cryptographic Application Programming Interface)。这个压缩包...

Global site tag (gtag.js) - Google Analytics