SSL通信雙方如何判斷對方採用了國密?

SSL通信涉及兩方的參與者,通常採用的模型是Client/Server。如果我們開發Client端產品(比如瀏覽器),可能會和多方的Server產品對接。那麼問題來了,雙方是如何知道對方使用了國密算法呢?這個問題非常重要,只有雙方採用同樣的加密標準,才能正常通信。難道採用“天王蓋地虎,寶塔鎮河妖”的接頭暗號?

在揭開這個謎底之前,我們先了解一下OID(Object Identifier,對象標誌符),然後再聊一聊密碼套件(Cipher Suite),就可以慢慢理解SSL通信雙方是如何接上頭的。當然,整個SSL通信涉及到很多標準和協議,不是一篇文章能講完的,所以本文只是拋磚引玉,探討一些基本的概念。可能對於資深人士而言,不值得一提,但我初入門時,也是摸索了好久,才慢慢能深入到細節。

OID

OID是由ISO/IEC、ITU-T國際標準化組織上世紀80年代聯合提出的標識機制,其野心很大,爲任何類型的對象(包括實體對象、虛擬對象和組合對象)進行全球唯一命名。通過唯一的編碼,我們就可以識別出對象。但要爲所有對象進行唯一命名,其難度和工作量都很大,所以它採用了分層樹形結構。

OID對應於“OID樹”或層次結構中的一個節點,該節點是使用ITU的OID標準X.660正式定義的。樹的根包含以下三個起點:

0:ITU-T
1:ISO
2:ITU-T/ISO聯合發佈

樹中的每個節點都由一系列由句點分隔的整數表示。比如,表示英特爾公司的OID如下所示:

1.3.6.1.4.1.343

對應於OID樹中的含義:

1               ISO
1.3             識別組織
1.3.6           美國國防部
1.3.6.1         互聯網
1.3.6.1.4       私人
1.3.6.1.4.1     IANA企業編號
1.3.6.1.4.1.343 英特爾公司

這裏採用分而治之的策略,解決編碼重複問題。樹中的每個節點均由分配機構控制,該機構可以在該節點下定義子節點,併爲子節點委託分配機構。

在上面的例子中,根節點“1”下的節點號由ISO分配,“1.3.6”下的節點由美國國防部分配,“1.3.6.1.4.1”下的節點由IANA分配,“1.3.6.1.4.1.343”下的節點由英特爾公司分配,依此類推。只要有需求,可以一直往下分配下去,也解決了編碼不夠的問題。

在實際應用中,ISO/IEC國際標準化機構維護頂層OID標籤,各個國家負責該國家分支下的OID分配、註冊和解析等工作,實現自我管理和維護。

相應的,針對國密,國家密碼局也定義了各類對象的標識符:

國密相關OID定義

詳細可參考 GM/T 0006-2012 這份標準。

像"1.2.156.10197.1.100"這種字符串,人讀起來比較直觀,但對於計算機處理而言,卻是大大的不方便,要知道字符串處理的效率非常低,所以在程序代碼中,對OID又進行了一次編碼。

在GmSSL源碼中,原始的OIDs定義在objects.txt文件中,在文件的尾部,我們可以看到國密的相關定義:

# GM/T
member-body 156		: ISO-CN		: ISO CN Member Body
ISO-CN 10197		: oscca
oscca 1			: sm-scheme


sm-scheme 103 1		: SSF33-ECB		: ssf33-ecb
sm-scheme 103 2		: SSF33-CBC		: ssf33-cbc
!Cname ssf33-ofb128
sm-scheme 103 3		: SSF33-OFB		: ssf33-ofb
!Cname ssf33-cfb128
sm-scheme 103 4		: SSF33-CFB		: ssf33-cfb
sm-scheme 103 5		: SSF33-CFB1		: ssf33-cfb1
sm-scheme 103 6		: SSF33-CFB8		: ssf33-cfb8
sm-scheme 103 7		: SSF33-CBC-MAC		: ssf33-cbc-mac


sm-scheme 102 1		: SM1-ECB		: sm1-ecb
sm-scheme 102 2		: SM1-CBC		: sm1-cbc
!Cname sm1-ofb128
sm-scheme 102 3		: SM1-OFB		: sm1-ofb
!Cname sm1-cfb128
sm-scheme 102 4		: SM1-CFB		: sm1-cfb
sm-scheme 102 5		: SM1-CFB1		: sm1-cfb1
sm-scheme 102 6		: SM1-CFB8		: sm1-cfb8




# SM2 OIDs
sm-scheme 301		: sm2p256v1
sm-scheme 301 1		: sm2sign
sm-scheme 301 2		: sm2exchange
sm-scheme 301 3		: sm2encrypt


通過 objects.pl 腳本,生成 obj_data.h文件,這個纔是在代碼中使用到的OID編碼。

boringssl也類似,不過其採用了 go 語言編寫的轉換腳本。

密碼套件

僅僅定義了OID還不夠,因爲國密並不是一個單一的標準,包含了很多加密、解密、哈希等算法,可以形成很多種組合,不能簡單假定對方採用了國密就可以建立通信。

在SSL通信開始,雙方就需要進行協商,採用何種算法進行通信。這裏需要重點理解密碼套件(CipherSuite)的概念。

密碼套件是一系列密碼學算法的組合,主要包含多個密碼學算法:

  • 身份驗證算法。

  • 密碼協商算法。

  • 加密算法或者加密模式。

  • HMAC算法的加密基元。

  • PRF算法的加密基元,需要注意的是,不同的TLS/SSL協議版本、密碼套件,PRF算法最終使用的加密基元和HMAC算法使用的加密基元是不一樣的。

密碼套件的構成如下圖所示:

密碼套件結構

密碼套件決定了本次連接採用哪一種加密算法、密鑰協商算法、HMAC算法,協商的結果就是雙方都認可的密碼套件。

密碼套件協商過程有點類似於客戶採購物品的過程,客戶(客戶端)在向商家(服務器端)買東西之前需要告知商家自己的需求、預算,商家瞭解用戶的需求後,根據用戶的具體情況(比如客戶願意接受的價格,客戶期望物品的使用年限)給用戶推薦商品,只有雙方都滿意了,交易才能完成。對於TLS/SSL協議來說,只有協商出密碼套件,才能進行下一步的工作。

除了現有國際上標準的密碼套件,國密還定義了一系列的密碼套件:

國密密碼套件列表

代碼可以參考 gmtls.h 文件,也可以使用GMSSL的命令查看所支持的密碼套件:

openssl ciphers -V | column -t

與國密相關的密碼套件有:

0xE1,0x07  -  ECDHE-SM2-WITH-SMS4-GCM-SM3    TLSv1.2    Kx=ECDH      Au=SM2    Enc=SMS4GCM(128)            Mac=AEAD
0xE1,0x02  -  ECDHE-SM2-WITH-SMS4-SM3        TLSv1.2    Kx=ECDH      Au=SM2    Enc=SMS4(128)               Mac=SM3
0xF1,0x20  -  ECDHE-PSK-WITH-SMS4-CBC-SM3    TLSv1      Kx=ECDHEPSK  Au=PSK    Enc=SMS4(128)               Mac=SM3
0xE0,0x17  -  SM9-WITH-SMS4-SM3              GMTLSv1.1  Kx=SM9       Au=SM9    Enc=SMS4(128)               Mac=SM3
0xE0,0x15  -  SM9DHE-WITH-SMS4-SM3           GMTLSv1.1  Kx=SM9DHE    Au=SM9    Enc=SMS4(128)               Mac=SM3
0xE0,0x13  -  SM2-WITH-SMS4-SM3              GMTLSv1.1  Kx=SM2       Au=SM2    Enc=SMS4(128)               Mac=SM3
0xE0,0x11  -  SM2DHE-WITH-SMS4-SM3           GMTLSv1.1  Kx=SM2DHE    Au=SM2    Enc=SMS4(128)               Mac=SM3
0xE0,0x1A  -  RSA-WITH-SMS4-SHA1             GMTLSv1.1  Kx=RSA       Au=RSA    Enc=SMS4(128)               Mac=SHA1
0xE0,0x19  -  RSA-WITH-SMS4-SM3              GMTLSv1.1  Kx=RSA       Au=RSA    Enc=SMS4(128)               Mac=SM3
0xF1,0x01  -  PSK-WITH-SMS4-CBC-SM3          SSLv3      Kx=PSK       Au=PSK    Enc=SMS4(128)               Mac=SM3
  • 第一列:數值代表密碼套件的編號,每個密碼套件的編號由IANA定義。

  • 第二列:代表密碼套件的名稱,雖然密碼套件編號是一致的,不同的TLS/SSL協議實現其使用的名稱可能是不一樣的。

  • 第三列:表示該密碼套件適用於哪個TLS/SSL版本的協議。

  • 第四列:表示密鑰協商算法。

  • 第五列:表示身份驗證算法。

  • 第六列:表示加密算法、加密模式、密鑰長度。

  • 第七列:表示HMAC算法。其中AEAD表示採用的是AEAD加密模式(比如AES128-GCM),無須HMAC算法。

值得注意的是,這裏的編碼又沒有采用OID,這也是開發過程中需要注意的,不同的地方使用了不同標準規範,需要在開發中翻閱相應的協議和規範。

可以看出,GmSSL並沒有實現所有的國密的密碼套件,但同時又擴充了幾個標準未定義的密碼套件,比如ECDHE-SM2-WITH-SMS4-GCM-SM3、ECDHE-SM2-WITH-SMS4-SM3等。這就體現出協商的重要性了,對雙方所支持的密碼套件取一個交集,從中選擇一個。如果不存在交集,協商也就不成功。注意,協商過程中服務器端可能會禁用一些不太安全的密碼套件(比如歷史遺留的一些現今已不太安全的算法),這時即使雙方都支持,也可能協商不成功。

我們可以測試服務器是否支持某個特定的密碼套件:

openssl s_client -cipher "ECDHE-SM2-WITH-SMS4-SM3" -connect sm2test.ovssl.cn:443 -tls1_2 -servername sm2test.ovssl.cn

當然,如何協商出密碼套件,涉及到SSL通信協議細節,如果開發中涉及到,就需要翻閱相應的RFC,這裏不做過多展開。

小結

本文簡單介紹了OID和密碼套件的概念,這對於理解SSL通信有很重要的幫助,如果從事SSL開發,開始面對一大堆的協議和標準,可能會懵圈,希望本文能給你一個探索國密的入口通道。在和第三方服務進行對接時,由於對這些概念理解不深,也是掉了很多坑,希望本文對你有所幫助。

如果大家有什麼問題,歡迎交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章