0 查找各种标准的原始文档,研究学习(至少包含Crypto API,PKCS#11,GMT 0016-2012,GMT 0018-2012)
Crypto API
https://learn.microsoft.com/zh-cn/windows/win32/seccrypto/cryptoapi-system-architecture#base-cryptographic-functions
微软的CryptoAPI是Win32平台下为应用程序开发者提供的数据加密和安全的编码接口。CryptoAPI函数集包含了基本的ASN.1的编码、解码,散列,数据加密和解密,数字证书管理等重要的密码学应用功能。数据的加密、解密支持对称和非对称两类算法。
PKCS#11
https://www.jianshu.com/p/b5a80fe0e901
加密令牌接口标准PKCS#11由RSA Security制定,定义了加密令牌的本机编程接口,例如硬件加密加速器和智能卡。使用JCA和JCE API的现有应用程序可以使用PKCS#11提供程序访问本机PKCS#11令牌。pkcs#11只提供了接口的定义, 不包括接口的实现。
GMT 0016-2012
https://www.doc88.com/p-6911351376514.html
规定了基于PKI密码体制的智能密码钥匙密码应用接口,描述了密码应用接口的函数、数据类型、参数的定义和设备的安全要求。
GMT 0018-2012
https://v1.cecdn.yun300.cn/150001_2107145025/GMT0018-2012密码设备应用接口规范(1).pdf
规定了公钥密码基础设施应用技术体系下服务类密码设备的应用接口标准。
1 总结这些API在编程中的使用方式
- Crypto API
- 引入头文件和链接库:
在编程时,需要引入wincrypt.h
头文件,并链接到Advapi32.lib
库。
- 初始化和释放Crypto API:
在使用Crypto API之前,需要初始化和释放Crypto API。可以使用CryptAcquireContext
函数初始化Crypto API,并使用CryptReleaseContext
函数释放资源。
- 选择算法和密钥:
在进行加密或解密操作之前,需要选择合适的算法和密钥。可以使用CryptCreateHash
函数创建哈希对象,并使用CryptGenKey
函数生成密钥。
- 加密和解密操作:
一旦选择了算法和密钥,可以使用相应的函数进行加密和解密操作。常用的加密函数是CryptEncrypt
,而解密函数是CryptDecrypt
。
- 释放资源:
在使用完Crypto API后,需要释放相应的资源。可以使用CryptDestroyHash
函数释放哈希对象,使用CryptDestroyKey
函数释放密钥。
- PKCS#11
- 引入头文件和链接库:
在编程时,需要引入适当的PKCS#11头文件,通常是pkcs11.h
。还需要链接到与所使用的PKCS#11库相对应的链接库。
- 初始化和释放PKCS#11库:
在使用PKCS#11库之前,需要初始化和释放库。可以使用C_Initialize
函数初始化PKCS#11库,并使用C_Finalize
函数释放资源。
- 查询和初始化令牌:
在使用PKCS#11库时,需要查询和初始化要使用的令牌(如智能卡)。可以使用C_GetSlotList
函数查询可用的令牌插槽,然后使用C_OpenSession
函数打开会话。
- 登录和登出令牌:
在进行操作之前,通常需要登录到令牌。可以使用C_Login
函数进行登录,并使用相应的用户PIN码验证身份。完成操作后,可以使用C_Logout
函数登出令牌。
- 生成密钥和对象:
PKCS#11允许生成密钥和其他对象。可以使用C_GenerateKey
函数生成密钥,使用C_CreateObject
函数创建其他类型的对象。
- 加密和解密操作:
一旦获取了密钥和对象,可以使用相应的函数进行加密和解密操作。通常使用C_Encrypt
函数进行加密,C_Decrypt
函数进行解密。
- 释放资源:
在使用完PKCS#11库后,需要释放相应的资源。可以使用C_CloseSession
函数关闭会话,使用C_Finalize
函数释放PKCS#11库资源。
- GMT 0016-2012
- GMT 0018-2012
2 列出这些API包含的函数,进行分类,并总结它们的异同
- Crypto API
- 基本加密函数
用于连接到 CSP 的上下文函数。 这些函数使应用程序能够按名称选择特定的 CSP,或选择可以提供所需功能类别的特定 CSP。
用于生成和存储加密密钥的密钥生成函数。 包括对更改 链接模式、 初始化向量和其他加密功能的完全支持。
用于交换或传输密钥的密钥交换函数。 - 证书编码/解码函数
用于加密或解密数据的函数。 还支持对数据进行哈希处理 。 - 证书存储函数
用于管理数字证书集合的函数。 - 简化的消息函数
用于加密和解密消息与数据的函数。
用于对消息和数据进行签名的函数。
用于验证所接收消息和相关数据上签名的真实性的函数。 - 低级别消息函数
用于执行简化消息函数执行的所有任务的函数。 与简化的消息函数相比,低级别消息函数提供更大的灵活性,但需要更多的函数调用。
https://learn.microsoft.com/zh-cn/windows/win32/seccrypto/cryptography-functions
- PKCS#11
通用接口
槽和令牌管理
会话管理
对象管理
加密函数
解密函数
消息摘要
签名和MAC
验证签名和MAC
密钥管理
随机数生成
-
GMT 0016-2012
-
GMT 0018-2012
3 以龙脉GM3000Key为例,写出调用不同接口的代码(Crypto API,PKCS#11,SKF接口),把运行截图加入博客
(一)SKF接口
龙脉密码钥匙驱动实例工具等\mToken-GM3000\skf\samples\windows\EncryptData\EncryptData.sln
(二)Crypto API
1.龙脉密码钥匙驱动实例工具等\mToken-GM3000\csp\samples\CryptAPI\VC\EncryptDecryptFile\EncryptFile.sln
(三)PKCS#11
1.龙脉密码钥匙驱动实例工具等\mToken-GM3000\pkcs11\windows\samples\PKCStest\PKCStest.sln
(1)DES
(2)DES3
(3)RC2
(4)RC4
(5)RSA
(6)AES
2.龙脉密码钥匙驱动实例工具等\mToken-GM3000\pkcs11\windows\samples\GetUSBInfos\getusbinfos.sln
Ⅰ.Crypto API#
Copy
解释
点击查看代码
HCRYPTPROV hCryptProv;
HCRYPTHASH hCryptHash;
HCRYPTKEY hCryptKey;
CPAcquireContext(
hCryptProv, NULL,
MS_DEF_PROV,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT
)//为应用程序创建一个上下文
CPCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&hCryptHash
) //为应用程序创建一个上下文
static char szHash[]=”PISAHASHDATA”; //原始字符串
DWORD dwLen=strlen(szHash);
CPHashData(hCryptHash, (BYTE*)szHash, dwLen, 0);//散列输入的数据
CPDeriveKey(hCryptProv, CALG_RC2, hCryptHash, 0, &hCryptKey);//从一个数据散列中生成一个会话密钥,它保证生成的密钥互不相同
static char szEntry[]= “PISA2002”;
DWORD dwLenIn = strlen(szEntry);
DWORD dwLenOut=dwLenIn;
CPEncrypt(hCryptKey, 0, TRUE, 0, (BYTE*)szEntry, &dwLenOut, dwLenIn);//用来加密明文
CPDecrypt(hCryptKey, 0, TRUE, 0,(BYTE*)szEntry,&dwLenOut);//用来解密先前被加密的数据
CPDestroyKey(hCryptKey);//释放一个密钥句柄,释放后,句柄将无效,密钥将无法再被访问
CPDestroyHash(hCryptHash);//删除一个散列对象句柄
CPReleaseContext(hCryptProv, NULL);//释放CPAcquireContext.创建的上下文
Ⅱ.PKCS#11
点击查看代码
CK_SESSION_HANDLE hSession;
CK_MECHANISM digestMechanism;
CK_ULONG ulStateLen;
CK_BYTE data1[] = {0x01, 0x03, 0x05, 0x07};
CK_BYTE data2[] = {0x02, 0x04, 0x08};
CK_BYTE data3[] = {0x10, 0x0F, 0x0E, 0x0D, 0x0C};
CK_BYTE pDigest[20];
CK_ULONG ulDigestLen;
CK_RV rv;
/* Initialize hash operation */
rv = C_DigestInit(hSession, &digestMechanism);//初始化消息杂凑计算操作,指定计算消息杂凑的算法
assert(rv == CKR_OK);
/* Start hashing */
rv = C_DigestUpdate(hSession, data1, sizeof(data1));//对多个分组的消息进行杂凑计算
assert(rv == CKR_OK);//返回成功或者失败
/* Find out how big the state might be */
rv = C_GetOperationState(hSession, NULL_PTR, &ulStateLen);//获取设备是否存在的状态
assert(rv == CKR_OK);//返回成功或者失败
/* Allocate some memory and then get the state */
pState = (CK_BYTE_PTR) malloc(ulStateLen);
rv = C_GetOperationState(hSession, pState, &ulStateLen);//获取设备是否存在的状态
/* Continue hashing */
rv = C_DigestUpdate(hSession, data2, sizeof(data2));//对多个分组的消息进行杂凑计算
assert(rv == CKR_OK);//返回成功或者失败
/* Restore state. No key handles needed */
rv = C_SetOperationState(hSession, pState, ulStateLen, 0, 0);
assert(rv == CKR_OK);//返回成功或者失败
/* Continue hashing from where we saved state */
rv = C_DigestUpdate(hSession, data3, sizeof(data3));//对多个分组的消息进行杂凑计算
assert(rv == CKR_OK);//返回成功或者失败
/* Conclude hashing operation */
ulDigestLen = sizeof(pDigest);
rv = C_DigestFinal(hSession, pDigest, &ulDigestLen);
if (rv == CKR_OK) {
/* pDigest[] now contains the hash of 0x01030507100F0E0D0C */
}//返回成功或者失败
点击查看代码
CK_FLAGS flags = 0;
CK_Dev_ID DevID;
CK_Dev_INFO DevInfo;
/* Block and wait for a slot event */
rv = SKF_WaitForSlotEvent(flags, &slotID, NULL_PTR);//等待设备的插拔事件
assert(rv == CKR_OK);//返回成功或者失败
/* See what’s up with that slot */
rv = SKF_GetDevInfo(slotID, &slotInfo);//获取设备的一些特征信息
assert(rv == CKR_OK);//返回成功或者失败