基于 CNG API 實現國密算法注冊及應用
摘 要:
下一代加密技術接口是微軟在 Windows 下實現的取代上一代加密應用程序接口的密碼服務接口。其目的是提供一種可擴展的方式以支持各種應用程序和未知的密碼算法,以便不同的算法、協議向操作系統注冊,并對應用程序提供統一的調用接口,應用程序無需改造即可支持對新算法的使用。研究了基于下一代加密技術接口在操作系統中注冊國密SM2、SM3 算法,完成解析和驗證國密 SM2 證書,實現了國密算法在系統中的注冊及應用。
內容目錄:
1 CNG 簡介
2 國密算法在系統中的注冊
2.1 算法 OID 的注冊
2.2 算法 Provider 的注冊
2.3 Provider 庫的實現
2.3.1 SM3 的實現
2.3.2 SM2 的實現
3 國密算法的實際應用
4 結 語
目前,國內主流企業所采用的密碼算法都是國際公開算法。國家密碼管理局早在 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 所示。

圖 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 OID 注冊前后證書顯示對比
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.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 值 ,再將 Z 值與待簽名消息通過 SM3 計算哈希后簽名 / 驗簽 。該使用規范為 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 系統中,證書都是通過 WinVerifyTrustEx 接口函數進行驗證的,在該接口里面內置有證書解碼、證書完整性、有效性、證書鏈校驗等函數。基于 SM2 算法的應用規范 ,在對數據進行簽名 / 驗簽時,先使用簽名公鑰與用戶標識計算 Z 值,然后與源數據合并計算 SM3,最后對 SM3 的結果進行簽名 / 驗簽。
通過對 Windows 系統中證書驗證的過程進行分析,對證書完整性和有效性的驗證實際就是直接使用 CryptDecodeObjectEx 接口對證書解碼,然后根據解碼后的數據計算哈希值,再將哈希值驗簽。該操作流程與 SM2 的使用規范不符,無法通過 SM2 的驗簽。為符合 SM2 使用規范,需要在證書解碼后的數據前面添加簽發者 Z 值。Windows 系統提供 CryptInstallOIDFunctionAddress函數用于注冊自定義的編解碼函數,通過該函數對 X509_ASN_ENCODING 編碼類型注冊自定義編解碼。從簽名算法使用 SM2 的證書獲取到簽發者的公鑰,并計算 Z 值,再與系統自動編 /解碼后的證書數據合并,以使簽名 / 驗簽的數據符合 SM2 使用規范。
分別使用 CFCA 提供的測試證書 SM2 的根證書、下級證書為例,驗證未注冊國密算法的Windows 操作系統和已注冊國密算法的操作系統,通過直接雙擊 SM2 證書文件得到如圖 3、圖 4 和圖 5 的結果。
通過圖片可直觀地看出:在系統中注冊國密算法后,操作系統自動實現了對國密算法證書的驗證。使用 Windows 的標準接口 WinVerifyTrustEx驗證證書,同樣能得到證書驗證通過的結果。

圖 3 未注冊算法時根證書無法通過驗證

圖 4 算法注冊后根證書通過驗證

圖 5 算法注冊后下級證書通過驗證
4 結 語
本文通過對 Windows 系統下新一代密碼接口的功能分析,完成了國密 SM2、SM3 算法向系統中注冊,同時實現了對國密算法簽發的證書驗證,為進一步實現國密 SSL 協議在 Windows 系統中的集成奠定了基礎,同時也為其他非公開算法向系統中注冊提供了一種實現思路。
引用本文:夏凡 , 文剛 , 朱紅宏 . 基于 CNG API 實現國密算法注冊及應用 [J]. 信息安全與通信保密 ,2022(4):71-78.