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

CSP国密算法研究之西电捷通HUFU Cipher Service Provider 作为 Microsoft Windows 的组成部分,CryptoAPI是提供应用程序编程接口(API)的规范,由它提供的一组函数接口允许应用程序在对用户的敏感私钥数据提供保护时,以灵活的方式对数据进行加密或数字签名,而实际的加密操作是由称为密码服务提供者(CSP,Cryptographic Service Provider)的独立模块执行的。 阅读详情
作者:MIXTER
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环境中编译通过。

参考文献:
《CryptoAPI原理与应用》
 
用CryptoAPI进行数据加密 http://expert.youkuaiyun.com/Expert/topic/1034/1034228.xml?temp=.8807794 用CryptoAPI进行数据加密 南京理工大学计算机系 胡静 李蔚清   由于过于复杂的加密算法实现起来非常困难,所以在过去,许多应用程序只能使用非常简单的加密技术,这样做的结果就是加密的数据很容易被人破译。而使用Microsoft提供的加密应用程序接口(即Cryp 阅读详情

相关推荐

Delphi下一代密码学:Windows CryptoAPI实战指南

本文还有配套的精品资源,点击获取 简介:Windows CryptoAPI是微软提供的安全服务组件,支持加密、解密、数字签名和哈希等操作。该压缩包包含了Delphi环境中使用CryptoAPI的库和示例代码,帮助开发者实现高级密码学功能。Delphi通过PInvoke技术调用Windows API,具体操作包括获取CSP句柄、生成密钥、数据加密和解密等。内容还可能包括源码库...

weixin_33750664的博客 1960

Using CryptoAPI in win32 program

如题,我想大家都知道cryptoAPI是微软操作系统提供给程序员加密数据的接口,很简单也很强大。不过在使用中还是有需要注意的几点:  1、注意两种密钥对的区别,签名用密钥和交换用密钥对的不同年。签名密钥对只有用私钥可以加密数据,而交换密钥对只有用公钥可以加密。不如此用,CryptEncrypt函数报错。  2、不要以为公钥可以在CryptDecrypt函数中可以用来解密数据,这是微软不允许的!

Bobo-Smile-Always 503

AES加密/解密,C,java,delphi互解

AES 加密/解密,C,java,delphi(5-XE)可通用,互解.对于跨平台和语言的来说,是稀有资源

Web Crypto API 实战:浏览器端 MD5/AES/RSA/国密SM2/SM3/SM4 加密解密

本文介绍了前端加密的常用场景和实现方法,包括使用Web Crypto API和sm-crypto库。主要内容涵盖:1)前端加密的5大典型场景(密码哈希、数据加密传输、RSA密钥对生成、国密合规、JWT调试);2)Web Crypto API的优势与限制;3)具体代码实现:SHA哈希、HMAC签名、AES加解密、RSA密钥对生成与加解密等。文章特别指出Web Crypto API不支持MD5和国密算法,需配合第三方库使用,并提供了完整的代码示例,帮助开发者在浏览器端实现安全加密功能。

学以致用 知行合一 1356

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

Delphi使用CryptoAPI生成自签名证书,PHP端使用该证书进行签名,Delphi作为客户端使用公钥进行验签。

delphi 加密解密函数

DELPHI下的加密解密..函数 . hcnet@msn.com

Delphi一超级函数代码库SRTL (转)

网上看到的,有很多pas的压缩文件,博客中不知放哪里下载。看看作为资源上传到优快云的下载频道行不行,如果能通过就写上下载链接。 Win32.pas API函数的简单调用,如建立进程,建立文件映射,建立、读取管道(可以捕捉DOS程序输出)等。 StrFuncs.pas 字符串处理单元,完全兼容宽字节处理(即使用wideString),特有的中文字符串处理函数(如简繁转换等等),经过多次优

好记性不如烂笔头 2216

数据加密及解密經典算法

此方法是Delphi編寫的一個經典的針對字符串進行加解密的算法,編程其實也是触类旁通,希望對想在數據加密或密碼加密上學習的朋友有所幫助。

vc++网络安全编程范例(21)用CryptoAPI进行数据加密

由于过于复杂的加密算法实现起来非常困难,所以在过去,许多应用程序只能使用非常简单的加密技术,这样做的结果就是加密的数据很容易被人破译。而使用Microsoft提供的加密应用程序接口(即Cryptography API),或称CryptoAPI,可以方便地在应用程序中加入强大的加密功能,而不必考虑基本的算法。本文将对CryptoAPI及其使用的数据加密原理作一简单的介绍,然后给出了用CryptoAP...

tubaluer 139

delphi调用libSmCrypto实现sm2、sm3、sm4加密解密_delphi_sm2-sm3-sm4_加密解密

支持win和linux平台,32位64位通用

第二十三章 Nest集成日志框架Winston

Winston是一个非常流行的Node.js日志框架,而Nest.js是一个基于Node.js的后端框架。修改 winston.module.ts 内容如下 添加 forRoot 方法,接收 winston 的 createLogger 方法的参数,返回动态模块的 providers、exports。这里用到了 printf 的 format 函数,它可以自定义打印的日志格式 且使用了chalk 加上了颜色,并且打印了 dayjs 格式化的时间。可以看到控制台打印了自定义的 logger 的自定义。

枫ゞ的博客 1070

使用CryptoAPI对文件进行加密解密

 作为 Microsoft Windows 的一部分提供的应用程序编程接口 (API)。CryptoAPI 提供了一组函数,这些函数允许应用程序在对用户的敏感私钥数据提供保护时以灵活的方式对数据进行加密或数字签名。实际的加密操作是由称为加密服务提供程序 (CSP) 的独立模块执行。  因为过于复杂的加密算法实现起来非常困难,所以在过去,许多应用程序只能使用非常简单的加密技术,这样做的结果就是加

Ronal_Lee的专栏 7925

3GPP协议解读_物理层系列(一)_物理层协议怎么看?

5G NR相关协议一般都在38系列,点进去以后可以看到,38.2xx系列为物理层相关协议,为了掌握物理层相关知识,应该怎么看协议呢?我建议从38.201读起,对38.2xx系列协议有一个整体的把握。

JCMLSY的博客 1330

CryptoAPI

简介  因为过于复杂的加密算法实现起来非常困难,所以在过去,许多应用程序只能使用非常简单的加密技术,这样做的结果就是加密的数据很容易就可以被人破译。而使用Microsoft提供的加密应用程序接口(即Cryptography API),或称CryptoAPI,就可以方便地在应用程序中加入强大的加密功能,而不必考虑基本的算法。本文将对CryptoAPI及其使用的数据加密原理作一简单的介绍,然后给出了用CryptoAPI编写加密程序的大致步骤,最后以一个文件的加密、解密程序为例演示了CryptoAPI的部分功能。

重剑无锋的专栏 476

C语言实现惯导更新算法(机械编排)

四元数可用于描述刚体转动或姿态变换,与方向余弦阵相比,表达简洁。四元数是一个包含四个元素的列向量,列向量的第一个元素表示刚体围绕旋转轴转过的角度大小,其余3个元素代表了旋转轴的方向。

十八与她的博客 1730

ruoyi-nbcio基于ruoyi的flowable前端支持自定义表单组件的自动获取方法

ruoyi-nbcio基于ruoyi的flowable前端支持自定义表单组件的自动获取方法

宁波阿成的博客 608
上一篇: Base64编码解码类
下一篇: linux裁减
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值