首頁>技術>

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-T1:ISO2:ITU-T/ISO聯合釋出

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

1.3.6.1.4.1.343

對應於OID樹中的含義:

1               ISO1.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/Tmember-body 156		: ISO-CN		: ISO CN Member BodyISO-CN 10197		: osccaoscca 1			: sm-schemesm-scheme 103 1		: SSF33-ECB		: ssf33-ecbsm-scheme 103 2		: SSF33-CBC		: ssf33-cbc!Cname ssf33-ofb128sm-scheme 103 3		: SSF33-OFB		: ssf33-ofb!Cname ssf33-cfb128sm-scheme 103 4		: SSF33-CFB		: ssf33-cfbsm-scheme 103 5		: SSF33-CFB1		: ssf33-cfb1sm-scheme 103 6		: SSF33-CFB8		: ssf33-cfb8sm-scheme 103 7		: SSF33-CBC-MAC		: ssf33-cbc-macsm-scheme 102 1		: SM1-ECB		: sm1-ecbsm-scheme 102 2		: SM1-CBC		: sm1-cbc!Cname sm1-ofb128sm-scheme 102 3		: SM1-OFB		: sm1-ofb!Cname sm1-cfb128sm-scheme 102 4		: SM1-CFB		: sm1-cfbsm-scheme 102 5		: SM1-CFB1		: sm1-cfb1sm-scheme 102 6		: SM1-CFB8		: sm1-cfb8# SM2 OIDssm-scheme 301		: sm2p256v1sm-scheme 301 1		: sm2signsm-scheme 301 2		: sm2exchangesm-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=AEAD0xE1,0x02  -  ECDHE-SM2-WITH-SMS4-SM3        TLSv1.2    Kx=ECDH      Au=SM2    Enc=SMS4(128)               Mac=SM30xF1,0x20  -  ECDHE-PSK-WITH-SMS4-CBC-SM3    TLSv1      Kx=ECDHEPSK  Au=PSK    Enc=SMS4(128)               Mac=SM30xE0,0x17  -  SM9-WITH-SMS4-SM3              GMTLSv1.1  Kx=SM9       Au=SM9    Enc=SMS4(128)               Mac=SM30xE0,0x15  -  SM9DHE-WITH-SMS4-SM3           GMTLSv1.1  Kx=SM9DHE    Au=SM9    Enc=SMS4(128)               Mac=SM30xE0,0x13  -  SM2-WITH-SMS4-SM3              GMTLSv1.1  Kx=SM2       Au=SM2    Enc=SMS4(128)               Mac=SM30xE0,0x11  -  SM2DHE-WITH-SMS4-SM3           GMTLSv1.1  Kx=SM2DHE    Au=SM2    Enc=SMS4(128)               Mac=SM30xE0,0x1A  -  RSA-WITH-SMS4-SHA1             GMTLSv1.1  Kx=RSA       Au=RSA    Enc=SMS4(128)               Mac=SHA10xE0,0x19  -  RSA-WITH-SMS4-SM3              GMTLSv1.1  Kx=RSA       Au=RSA    Enc=SMS4(128)               Mac=SM30xF1,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開發,開始面對一大堆的協議和標準,可能會懵圈,希望本文能給你一個探索國密的入口通道。在和第三方服務進行對接時,由於對這些概念理解不深,也是掉了很多坑,希望本文對你有所幫助。

出處:https://mp.weixin.qq.com/s/t82z0uKW2AZjtPop79wjvg

19
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 多執行緒程式中操作的原子性