1.微软的Crypto API
Windows CryptoAPI是Microsoft 公司提出的安全加密应用服务框架,也是PKI推荐使用的加密 API。它提供了在Win32 环境下使用认证、编码、加密和签名等安全服务时的标准加密接口,用于增强应用程序的安全性与可控性。应用开发者可以在不了解复杂的加密机制和加密算法的情况下,简便、快速地开发出标准、通用和易于扩展的安全加密应用程序。CryptoAPI 提供的功能主要有:密钥管理、数据加密和解密、数字签名和验证、证书管理、可信根证书管理、数据编码和解码、数字证书编码和解码、PKCS#7 标准格式编码和解码等。利用CryptoAPI,开发者可以给基于Windows的应用程序添加安全服务,包括: ASN.1编码及解码、数据加密/解密、身份论证、数字证书管理,同时支持PKI、对称密码技术等。应用程序开发者直接使用这些安全功能而无须了解其底层实现。
1.1 使用方式
1.1.1 加密密钥
- 在CryptoAPI中,支持两种类型密钥:会话密钥、公/私密钥对。
- 会话密钥也称为对称密钥,用于对称加密算法,例如RC2、RC4、DES等。在CryptoAPI中,一般使用CryptGenKey 或 CryptDeriveKey函数产生会话密钥。为了保证密钥的安全性,这些密钥都保存在CSP内部。当然,用户也可以通过CryptExportKey函数把密钥以加密密钥块形式导出到具体应用空间内,以备以后使用或传输给其他用户。
- 公/私密钥对(包括公钥、私钥)用于非对称加密算法,例如RSA等。非对称加密算法主要用于加解密会话密钥和数字签名。在CryptoAPI中,一般来说,大多数 CSP产生的密钥容器包含两对密钥对,一对用于加密会话密钥,称为交换密钥对,一对用于产生数字签名,称为签名密钥对;但也有些CSP没有存储密钥对,或者存储不止两对密钥对。
- 在CryptoAPI中,所有的密钥都存储在CSP,CSP负责产生、销毁密钥,并使用它们完成各种密码操作。也可以利用CryptoAPI函数从CSP中导出密钥。
1.1.2 数据编码/解码
- 通过通信媒介(例如电话线路)传输数据,必须先把数据序列化,即把数据转化为0、1串。在序列化操作中,接到数据的计算机必须能够把数据转化为其原始格式。序列化完成的操作规则称为通信协议,它由软件和数据传输硬件共同完成,其协议一般包含多层。
- 计算机1应用程序层先传输原文数据到编码/解码层,编码/解码层编码原文数据为计算机字节流,然后发送到硬件层,硬件层把字节流数据转化为0、1串流传输到计算机2。计算机2接到数据后,反向操作,转化0、1串流为计算机字节流,发送到编码/解码层,编码/解码层解码计算机字节流为原文数据。
- 描述抽象对象的一个普遍方式为:ASN.1(抽象语法标记1),ASN.1在CCITT推荐文件X.208中定义,描述对象转换为0、1串的ASN.1规则称为DER(精确编码规则),在CCITT推荐文档X.509 8.7节定义。CryptoAPI采用的就是这种编码方式,表示数据发送方发送时先把数据抽象为ASN.1对象,然后使用DER编码规则把ASN.1对象转化为可传输的0、1串;接收方接到数据后,利用DER解码规则把0、1串转化为ASN.1对象,然后再把ASN.1对象转化为具体应用支持的数据对象。
1.1.3 数据加/解密
- 加密较大的数据,CryptoAPI中约定用对称加密算法,这种算法中,在加密和解密过程中都使用同一个对称密钥或会话密钥。CryptoAPI中,通过其封装好的加解密函数来实现数据加解密操作,不同CSP提供不同的加解密算法,但常用的算法,一般CSP都提供。
1.1.4 哈希与数字签名
- 哈希与数字签名一般用于确定数据的完整性和身份鉴别。CryptoAPI中,通过其封装好的哈希与数字签名函数来实现相关操作。微软提供的CSP产生的数字签名遵循RSA标准(PKCS#6),其他CSP可能遵循其他标准。
1.1.5 证书编码/解码功能
- 用于加密或解密数据的功能。还包括对哈希数据的支持。有关更多信息,请参见数据加密和解密功能和数据加密和解密。
1.1.6 证书存储功能
- 用于管理数字证书收集的功能。有关更多信息,请参见数字证书和证书存储功能。
1.1.7摘要算法
CryptAcquireContext
摘要运算的第一步要调用CryptAcquireContext方法。实际上,下面介绍的每一个密码运算基本都要先通过调用此方法,设置相应的密码运算参数,并返回相应的CSP句柄,用于后面的运算。
phProv是返回的CSP句柄;pszContainer是要使用的密钥是在容器;摘要运算不涉及密钥,所以这里设置为NULL;pszProvider为使用到的CSP的名称,如果设置为NULL,则CryptAcquireContext会调用系统缺省CSP;dwProvType为所使用的CSP的类型,一般这里设置为PROV_RSA_FULL(0x1);dwFlags为标志值,如果是涉及到私钥的运算,如签名或解密,应设置为0,但如果是摘要、加密或验证等不涉及私钥的运算,强烈不建议这里设置成0,而应设置成CRYPT_VERIFYCONTEXT(0xF0000000),就是告诉Windows接下来的密码运算是不会访问私钥的。
CryptCreateHash
调用此方法生成一个摘要运算的对象。hProv为上一步返回的CSP句柄;Algid为摘要算法,比如可以是CALG_SHA1;hKey和dwFlags都设置成0;phHash为返回的摘要运算对象。返回值同上。
CryptHashData
调用CryptHashData方法进行摘要运算。phHash为上一步返回的摘要运算对象;pbData为原文;dwDataLen为原文长度;dwFlags为0。方法返回值同上。
CryptGetHashParam
调用CryptGetHashParam可以返回摘要的各种相关数据信息,这里先返回摘要的数据长度。
dwParam设置为HP_HASHSIZE(0x0004);pbData为返回长度值;pdwDataLen为长度值所占字节数;dwFlags为0。调用成功后,再调用一次CryptGetHashParam方法返回摘要值。这次dwParam设置为HP_HASHVAL(0x0002);按照上一次调用返回的长度值为pbData分配空间,它返回的摘要值。
1.1.8 对称加密
对称加密中常用的方式是根据用户输入的口令加解密文档,即基于口令派生出加解密密钥
CryptAcquireContext
返回CSP句柄,参数设置与摘要运算时一致。
CryptCreateHash
生成摘要运算对象。
CryptHashData
生成摘要。pbData为调用加密功能的上位程序输入的加密口令。
BOOL CryptDeriveKey
派生密钥。
BOOL CryptSetKeyParam
设置密钥参数。
BOOL CryptEncrypt
调用CryptEncrypt进行加密。
1.1.9 对称解密
对称解密与加密相对应,调用顺序和参数设置基本一致。
pbData输入密文,调用后输出明文;pdwDataLen输入为密文长度,调用后输出明文长度。返回值与CryptEncrypt一致。
2.RAS公司的PKCS#11标准
2.1研究学习
PKCS#11是公钥加密标准Public-Key Cryptography Standards中的一份子,由RSA实验室发布。
PKCS#11标准定义了与密码令牌的独立于平台的API,API本身命名为Cryptoki,这个API已经发展成为一个通用的加密令牌的抽象层。
PKCS#11主要是应用于智能卡和HSM。
PKCS#11为使用加密Token的应用程序提供统一的编程接口,独立于设备,屏蔽加密设备的复杂性,应用程序可以方便地更换设备。
PKCS密码中间件位于上层应用和底层安全设备之间,应用基于 PKCS#11 标准接口开发各类应用程序。主要包括2个库
- 主API库:提供给应用的PKCS11接口。
- tokenDLL库:由主 API 库调用,完成从上向下到指定设备的套接。
- 安全密码设备:安全服务资源和实施的载体,完成具体安全功能支撑。
PKCS #11模型中重要的概念之一是slot,也称为槽。一个slot为一个密码设备对象。某个打开的slot会话称之为session。Session之间存在不同的验证权限,而同一个slot的不同的session之间存在操作的互相影响性,同时在某些状况下,权限会发生同步。另外一个重要的概念是对象,PKCS #11中支持几种重要的对象,如公钥、私钥、对称密钥,数据对象等。
PKCS#11创建和支持下列对象:
PKCS#11的对象可根据其生命期长短的不同分成两大类:一类是持久存储的类对象,这类对象被保存在USB Key的安全存储区域当中,直到应用程序主动删除这些对象;另一类是会话对象,这类对象只存在于运行时建立的特定会话(Session对象)当中,一旦会话结束,这类对象也跟着被删除。
PKCS#11的对象除了生命期长短有分别之外,在访问权限上也有限制。所有的对象都可根据访问权限的不同分成两大类:一类是公开对象,这类对象是任何用户都可以访问的;另一类是私有对象,这一类对象只有身份被验证的用户才有权访问。决定对象的访问限制类型的模板属性是CKA_PRIVATE。
2.2使用方式
2.2.1架构
2.2.2会话状态
2.2.3对象
2.3 API函数
PKCS#11创建和支持下列对象:
PKCS#11的对象可根据其生命期长短的不同分成两大类:
持久存储的类对象,这类对象被保存在USB Key的安全存储区域当中,直到应用程序主动删除这些对象;
会话对象,这类对象只存在于运行时建立的特定会话(Session对象)当中,一旦会话结束,这类对象也跟着被删除。
决定对象生命期的模板属性是CKA_TOKEN,这是个布尔值,所有的对象都有这一属性。当该值为TRUE时,该对象将被保存到Key内的存储空间,否则,该对象保存在会话空间中,当会话结束后,该对象即销毁。
P11标准颁发了70余条指令。其中部分指令简介如下表:
3.GMT 0016-2012 智能密码钥匙密码应用接口规范
3.1研究学习
接口规范
GMT 0016-2012是国家规定的智能密码钥匙密码应用接口规范,规定了基于PKI密码体制的智能密码钥匙密码应用接口,描述了密码应用接口的函数、数据类型、参数的定义和设备的安全要求。适用于智能密码钥匙产品的研制、使用和检测。
规范性引用文件
下列文件对于本标准的应用是必不可少的。凡是注日期的引用文件。仅所注日期的版本适用于本文件;凡是不注日期的引用文件,其最新版本(包括所有的修改单)适用于本文件;GM/T 0006密码应用标识规范;GM/T AAAA SM2密码算法使用规范
3.2使用方法
层次关系
应用结构
3.3API函数
设备管理系列函数
访问控制系列函数
应用管理系列函数
文件管理系列函数
容器管理系列函数
密码服务系列函数
4.GMT 0018-2012密码设备应用接口规范
4.1研究学习
GMT 0018-2012 文件[http://www.gmbz.org.cn/main/viewfile/20180110020642562680.html]
接口标准
GMT 0018-2012标准规定了公钥密码基础设施应用技术体系下服务类密码设备的应用接口标准。适用于服务类密码设备的研制、使用,以及基于该类密码设备的应用开发,也可用于指导该类密码设备的检测。
规范性引用文件
下列文件对于本文件的应用是必不可少的。凡是注日期的引用文件,仅注日期的版本适用于本文件;凡是不注日期的引用文件,其最新版本(包括所有的修改单)适用于本文件;GM/T 0006密码应用标识规范;GM/T AAAA SM2密码算法使用规范。
其中还包括了对部分术语的规定:
4.2使用方式
在公钥密码基础设施应用技术体系框架中,密码设备服务层由密码机,密码卡,智能密码终端等设备组成,通过本标准规定的密码设备应用接口向通用密码服务层提供基础密码服务。如下图所示。
基础密码服务包括密钥生成、单一的密码运算、文件管理等的服务。
本标准采用C语言描述接口函数。如无特别说明,函数中参数的长度单位均为字节数。
4.3API函数
设备管理类函数
A.打开设备:SDF_OpenDevice
B.关闭设备:SDF_CloseDevice
C.创建会话:SDF_OpenSession
D.关闭会话:SDF_CloseSession
E.获取设备信息:SDF_GetDeviceInfo
F.产生随机数:SDF_GenerateRandom
G.获取私钥使用权限:SDF_GetPrivateKeyAccessRight
H.释放私钥使用权限:SDF_ReleasePrivateKeyAccessRight
密钥管理类函数
- 导出 RSA 签名公钥∶SDF_ExportSignPublicKey_RSA
- 导出 RSA 加密公钥∶SDF_ExportEncPublicKey_RSA
- 产生 RSA非对称密钥对并输出∶SDF_GenerateKeyPair_RSA
- 生成会话密钥并用内部 RSA公钥加密输出∶SDF_GenerateKeyWithIPK_RSA
- 生成会话密钥并用外部 RSA公钥加密输出∶SDF_GenerateKeyWithEPK_RSA
- 导入会话密钥并用内部 RSA私钥解密∶SDF_ImportKeyWithISK_RSA
- 基于 RSA 算法的数字信封转换∶SDF_ExchangeDigitEnvelopeBaseOnRSA
- 导出 ECC签名公钥∶SDF_ExportSignPublicKey_ECC
- 导出 ECC 加密公钥∶SDF_ExportEncPublicKey_ECC
- 产生 ECC非对称密钥对并输出∶SDF_GenerateKeyPair_ECC
- 生成会话密钥并用内部 ECC公钥加密输出∶SDF_GenerateKeyWithIPK_ECC
- 生成会话密钥并用外部 ECC公钥加密输出:SDF_GenerateKeyWithEPK ECC
- 导入会话密钥并用内部 ECC私钥解密∶SDF_ImportKeyWithISK_ECC
- 生成密钥协商参数并输出;SDF_GenerateAgreementDataWithECC
- 计算会话密钥∶SDF_GenerateKeyWiuhECC
- 产生协商数据并计算会话密钥∶SDF_GenerateAgreementDataAndKeyWithECC
- 基于 ECC算法的数字信封转换∶SDF_ExchangeDigitEnvelopeBaseOnECC
- 生成会话密钥并用密钥加密密钥加密输出∶SDF_GenerateKeyWithKEK
- 导入会话密钥并用密钥加密密钥解密∶SDF_ImportKeyWithKEK
- 销毁会话密钥∶SDF_DestroyKey
5.以龙脉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
要在当前目录下先创建 20211302.txt
2.龙脉密码钥匙驱动实例工具等\mToken-GM3000\csp\samples\CryptAPI\VC\EnumCerts\EnumCerts.sln
(三)PKCS#11
1.龙脉密码钥匙驱动实例工具等\mToken-GM3000\pkcs11\windows\samples\PKCStest\PKCStest.sln
(1)DES
(2)DES3
(3)RC2