APP下载

基于CNG API实现国密算法注册及应用*

2022-05-20朱红宏

信息安全与通信保密 2022年4期
关键词:公钥密钥应用程序

夏 凡,文 刚,朱红宏

(中国电子科技集团公司第三十研究所,四川 成都 610041)

关键字:下一代加密技术接口;商密算法;SM2 证书;加密服务提供程序

0 引 言

目前,国内主流企业所采用的密码算法都是国际公开算法。国家密码管理局早在2012年起就颁布了一系列的商密算法实现及应用的规范文件。国内的一些信息安全厂商和一些开源程序,例如,基于开放式安全套接层协议(Open Secure Sockets Layer,OpenSSL)实现的支持国密算法和标准的OpenSSL 分支(GmSSL)和天安版国密OpenSSL(TaSSL)也基于该系列规范实现了国密标准的对称、非对称、散列算法及接口规范。但基于该规范的实现与操作系统的实现有较大差异,目前,国密算法SM2 虽已被纳入国际标准,但在各大操作系统上依然没有内置该算法的实现。在实际使用时仍是由应用程序开发人员使用各厂商提供的算法库来实现对国密算法的使用。一些利用操作系统应用程序接口(Application Programming Interface,API)实现密码算法调用的应用程序将面临重新开发和定制的风险。同时,证书信任是使用安全套接层(Secure Sockets Layer,SSL)的基本要求,各种浏览器、使用SSL 的客户端在面对不信任的证书时都会弹出警告,甚至是直接断开连接,但目前系统中并没有实现SM2 证书的验证,导致无法对某些安全性要求较强的业务进行访问。因此,本文通过研究微软提出的新一代密码应用服务接口,实现国密算法在Windows 系统中的注册及使用。在不修改原应用程序的情况下,使应用程序正确调用新注册的国密算法以实现密码服务功能,实现国密算法在Windows 操作系统中的无缝集成,完成国密证书在Windows 系统中的直接验证及P12 格式的国密证书导入。

1 CNG 简介

下一代加密技术接口(Cryptographic Next Generation API,CNG API)是微软在Windows Vista 及之后的操作系统中实现的取代上一代CryptoAPI 的密码服务接口。相对于上一代的CryptoAPI,它具备的优势如下:(1)更灵活的配置模型,支持更多的密钥存储配置、算法配置、随机数发生器等;(2)完全兼容上一代CryptoAPI 接口;(3)支持内核模式下的算法配置;(4)支持自定义的证书格式;(5)支持SSL/安全传输层(Transport Layer Security,TLS)的协议配置。在Windows Vista 及之后的操作系统中,默认使用的密码服务接口已经替换为CNG API,CryptoAPI 也只是对CNG 的封装调用。

CNG 允许密码服务实现方以“Provider”的形式向系统添加密码服务实现,并向开发者提供软件开发工具包(Software Development Kit,SDK),极大地方便了密码服务提供商向系统注册自己专有算法或者对密码硬件的调用。CNG允许第三方密码服务提供商提供的程序的主要功能如下文所述。

(1)密钥存储实现。第三方提供商以自己的方式实现密钥的管理、产生、销毁、使用等。例如,实现密钥存储可通过结合密码硬件来实现私钥的保存和使用,使私钥既不出硬件,又能通过Windows 标准接口供应用程序使用。密钥存储仅支持在用户模式下注册。

(2)密码算法实现。第三方提供商可通过注册密码算法来实现对称、摘要、非对称加解密、签名验签、随机数发生器、密钥衍生等功能。通过该方式,可以将一些专用的非公开算法方便地新增到系统中并由原生的Windows API使用。密码算法可在用户模式下和内核模式下进行注册,在内核模式下注册后,驱动程序中也可以使用用户自定义的密码算法。

(3)密钥衍生、协商实现。第三方提供商可注册自己的密钥衍生、密钥协商实现类。

(4)SSL 协议实现。第三方提供商可注册自己的协议实现类,实现TLS 协议交互过程中使用私有算法或者数据格式的认证、密钥协商、加密等功能。

2 国密算法在系统中的注册

在系统中注册自定义算法时需要先注册一个Provider,一个Provider 可包含多种算法实现的接口。Provider 及支持的接口关系如图1所示。

由Provider 的结构可以看出它涵盖了密码算法的所有功能,通过接口将算法注册到系统后,即可实现算法接口的相关功能。本文通过将SM2 算法、SM3 算法注册到Windows操作系统中,实现国密证书在Windows 中的识别、签发、验证。此外,还需要实现随机数发生接口,以产生符合国密随机数检测规范的随机数。

2.1 算法OID 的注册

在数字证书中,以对象标识符(Object Identifier,OID)来唯一标识一种算法。密码服务提供商通过Windows 标准接口CryptRegisterOIDInfo 来实现密码算法OID 向操作系统的注册,当注册算法时,在结构CRYPT_OID_INFO 中填写对应的算法所属的组(国密各算法及参数的OID 可在标识规范中查询)。根据实际需要,SM3 所属组为BCRYPT_HASH_INTERFACE,SM2 作为公钥算法时,其所属的组为CRYPT_PUBKEY_ALG_OID_GROUP_ID;SM2 作为签名算法时,其所属的组为CRYPT_SIGN_ALG_OID_GROUP_ID。支持SM2 算法时,还需要根据用途填充OID 扩展参数,用作加密和验签时,则扩展参数为3 个整型:第一个参数为公钥用途,加密(CRYPT_OID_PUBKEY_ENCRYPT_ONLY_FLAG)、验签(CRYPT_OID_PUBKEY_SIGN_ONLY_FLAG)或两者都支持;第二个参数为公钥所属算法的标识;第三个参数为椭圆曲线算法(Elliptic Curve Cryptography,ECC)公钥模长。用作签名时,则扩展参数为整型,值恒为CALG_OID_INFO_PARAMETERS。SM2 算法OID 注册成功后,在Windows 下双击国密SM2 证书,可在证书详细信息里面查看到公钥、公钥参数、签名算法等值显示为SM2、SM3 等注册过的值[1]。注册算法OID 前,系统则只能显示出算法OID对应的可识别文本信息,因算法的实现还需要通过Provider 的注册后,才会被系统调用。在Windows 下未注册OID 和已注册OID 的国密证书显示对比如图2所示。

2.2 算法Provider 的注册

CNG 开发包提供了BCryptRegisterProvider 函数用于向系统中注册Provider,本文讨论的是应用层的算法注册,因此必须在BCryptRegisterProvider函数的PCRYPT_PRVIDER_REG 参数中填充SM2和SM3 算法,指定Provider 所处的动态库文件名称以及Provider 提供的算法类型。

Provider 注册成功后,还需要向配置节点中添加各个算法的配置,CNG 开发包提供BCryptAddContextFunctionProvider 函数用于向Provider 中添加算法实现。

OID、Provider 及配置的算法在CNG 开发包中也提供了相应的实现,若操作系统中不再需要新注册的算法,则调用函数CryptUnregisterOIDInfo 卸载已注册的OID,调用函数BCryptUnregisterProvider卸载已注册的Provider。

2.3 Provider 库的实现

Provider 以动态库的形式提供算法,为保证Windows 操作系统正确使用Provider 所提供的算法,动态库必须实现导出函数来支持注册到Provider 中的算法,导出的函数及含义如表1所示。

表1 Provider 导出函数及含义

根据微软提供的CNG 开发包及其示例,在Provider 中实现了SM3 算法、SM2 算法及其相关函数接口。Windows 应用程序调用的算法实际是由Provider 所提供的算法接口实现的。

2.3.1 SM3 的实现

Provider 中实现杂凑功能的函数接口GetHashInterface 原型如下:

在GetHashInterface 的实现代码中以SM3 的实现函数填充返回的结构体列表ppFunctionTable,其对应的回调函数即可实现SM3 在系统中的注册。完成SM3 算法注册和相应的功能后,可通过如下的示例代码进行验证:

根据验证程序的输入和输出结果,与国密SM3 密码杂凑算法规范对比,两者结果一致[2]。

2.3.2 SM2 的实现

Provider 中实现SM2 的签名/验签、加密/解密以及公私钥的导入和密钥对产生等,需在CNG中分别对相应结构体进行填充。签名以结构体BCRYPT_SIGNATURE_FUNCTION_TABLE 定义各个操作回调,非对称加密以结构体BCRYPT_ASYMMETRIC_ENCRYPTION_FUNCTION_TABLE定义各个操作回调。Provider 中实现SM2 签名验签的接口原型如下:

在以上GetSignatureInterface 的实现代码中,以SM2 的实现函数填充返回的结构体列表ppFunctionTable,其对应的回调函数即可实现SM2算法的签名、验签功能在系统中的注册。然后应用程序采用Windows 系统标准的CNG API 完成对SM2 算法的调用,调用流程与SM3 类似,细节可参考CNG 开发包提供的示例以及帮助文档。

根据密码行业标准GM/T 0009—2012《SM2 密码算法使用规范》,使用SM2 的签名功能需利用签名方的用户身份标识和签名方公钥,通过SM3 运算得到Z 值[2],再将Z 值与待签名消息通过SM3 计算哈希后签名/验签[3]。该使用规范为SM2 特有,公开算法无此应用方式。因此,应用程序除通过扩展BCRYPT_SIGNATURE_FUNCTION_TABLE 中的BCryptExportKeyFn 接口外,还需扩展一个 BCRYPT_SM2Z_BLOB=L"SM2ZBLOB"的数据类型。通过调用BCryptExportKey,并指定数据类型为BCRYPT_SM2Z_BLOB,可计算出公钥的Z 值,应用程序将此Z 值与待签名数据计算哈希后再进行签名/验签。

3 国密算法的实际应用

将国密算法在操作系统中注册完成后,以中国金融认证中心(China Financial Certification Authority,CFCA)提供的SM2 测试证书链为例,验证此国密SM2 证书能否通过验证。

在Windows 系统中,证书都是通过 WinVerify TrustEx 接口函数进行验证的,在该接口里面内置有证书解码、证书完整性、有效性、证书链校验等函数。基于SM2 算法的应用规范[3],在对数据进行签名/验签时,先使用签名公钥与用户标识计算Z 值,然后与源数据合并计算SM3,最后对SM3 的结果进行签名/验签。

通过对Windows 系统中证书验证的过程进行分析[4],对证书完整性和有效性的验证实际就是直接使用CryptDecodeObjectEx 接口对证书解码,然后根据解码后的数据计算哈希值,再将哈希值验签。该操作流程与SM2 的使用规范不符,无法通过SM2 的验签。为符合SM2 使用规范,需要在证书解码后的数据前面添加签发者Z 值。Windows系统提供 CryptInstallOIDFunctionAddress函数用于注册自定义的编解码函数,通过该函数对X509_ASN_ENCODING 编码类型注册自定义编解码。从签名算法使用SM2 的证书获取到签发者的公钥,并计算Z 值,再与系统自动编/解码后的证书数据合并,以使签名/验签的数据符合SM2 使用规范。

分别使用CFCA 提供的测试证书SM2 的根证书、下级证书为例,验证未注册国密算法的Windows 操作系统和已注册国密算法的操作系统,通过直接双击SM2 证书文件得到如图3、图4和图5的结果。

通过图片可直观地看出:在系统中注册国密算法后,操作系统自动实现了对国密算法证书的验证。使用Windows 的标准接口 WinVerifyTrustEx验证证书,同样能得到证书验证通过的结果。

4 结 语

本文通过对Windows 系统下新一代密码接口的功能分析,完成了国密SM2、SM3 算法向系统中注册,同时实现了对国密算法签发的证书验证,为进一步实现国密SSL 协议[5]在Windows 系统中的集成奠定了基础,同时也为其他非公开算法向系统中注册提供了一种实现思路。

猜你喜欢

公钥密钥应用程序
幻中邂逅之金色密钥
幻中邂逅之金色密钥
密码系统中密钥的状态与保护*
删除Win10中自带的应用程序
谷歌禁止加密货币应用程序
神奇的公钥密码
Android密钥库简析
国密SM2密码算法的C语言实现
基于身份的聚合签名体制研究
三星电子将开设应用程序下载商店