參考鏈接
- SSL通信雙方如何判斷對方采用了國密 - Bigben - 博客園
- 滑動驗證頁面??OpenSSL TLS1.2密碼套件推薦
- 安全的TLS協議 | Hexo
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
- 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分配、注冊和解析等工作,實現自我管理和維護。相應的,針對國密,國家密碼局也定義了各類對象的標識符:
- GMT 0006-2012 密碼應用標識規范.pdf?GM-Standards/GMT 0006-2012 密碼應用標識規范.pdf at master · guanzhi/GM-Standards · GitHub
?
- 像"1.2.156.10197.1.100"這種字符串,人讀起來比較直觀,但對于計算機對字符串處理的效率非常低,所以在程序代碼中,對OID又進行了一次編碼。
- 通過 objects.pl 腳本,生成 obj_data.h文件,這個才是在代碼中使用到的OID編碼。 boringssl也類似,不過其采用了 go 語言編寫的轉換腳本。
- 在GmSSL源碼中,原始的OIDs定義在crypto/objects/objects.txt文件中,在文件的尾部,我們可以看到國密的相關定義:
?國密相關定義
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 : sm2encryptsm-scheme 501 : SM2Sign-with-SM3 : sm2sign-with-sm3
sm-scheme 502 : SM2Sign-with-SHA1 : sm2sign-with-sha1
sm-scheme 503 : SM2Sign-with-SHA256 : sm2sign-with-sha256
sm-scheme 504 : SM2Sign-with-SHA511 : sm2sign-with-sha512
sm-scheme 505 : SM2Sign-with-SHA224 : sm2sign-with-sha224
sm-scheme 506 : SM2Sign-with-SHA384 : sm2sign-with-sha384
sm-scheme 507 : SM2Sign-with-RMD160 : sm2sign-with-rmd160
sm-scheme 520 : SM2Sign-with-Whirlpool : sm2sign-with-whirlpool
sm-scheme 521 : SM2Sign-with-Blake2b512 : sm2sign-with-blake2b512
sm-scheme 522 : SM2Sign-with-Blake2s256 : sm2sign-with-blake2s256sm2encrypt 1 : sm2encrypt-recommendedParameters
sm2encrypt 2 : sm2encrypt-specifiedParameters
sm2encrypt 2 1 : sm2encrypt-with-sm3
sm2encrypt 2 2 : sm2encrypt-with-sha1
sm2encrypt 2 3 : sm2encrypt-with-sha224
sm2encrypt 2 4 : sm2encrypt-with-sha256
sm2encrypt 2 5 : sm2encrypt-with-sha384
sm2encrypt 2 6 : sm2encrypt-with-sha512
sm2encrypt 2 7 : sm2encrypt-with-rmd160
sm2encrypt 2 8 : sm2encrypt-with-whirlpool
sm2encrypt 2 9 : sm2encrypt-with-blake2b512
sm2encrypt 2 10 : sm2encrypt-with-blake2s256
sm2encrypt 2 11 : sm2encrypt-with-md5# SM3
sm-scheme 401 : SM3 : sm3
sm-scheme 401 2 : HMAC-SM3 : hmac-sm3# SM4
sm-scheme 104 1 : SMS4-ECB : sms4-ecb
sm-scheme 104 2 : SMS4-CBC : sms4-cbc
!Cname sms4-ofb128
sm-scheme 104 3 : SMS4-OFB : sms4-ofb
!Cname sms4-cfb128
sm-scheme 104 4 : SMS4-CFB : sms4-cfb
sm-scheme 104 5 : SMS4-CFB1 : sms4-cfb1
sm-scheme 104 6 : SMS4-CFB8 : sms4-cfb8
sm-scheme 104 7 : SMS4-CTR : sms4-ctr
sm-scheme 104 8 : SMS4-GCM : sms4-gcm
sm-scheme 104 9 : SMS4-CCM : sms4-ccm
sm-scheme 104 10 : SMS4-XTS : sms4-xts
sm-scheme 104 11 : SMS4-WRAP : sms4-wrap
sm-scheme 104 12 : SMS4-WRAP-PAD : sms4-wrap-pad
sm-scheme 104 100 : SMS4-OCB : sms4-ocb# SM5/6/7/8
sm-scheme 201 : SM5 : sm5
sm-scheme 101 1 : SM6-ECB : sm6-ecb
sm-scheme 101 2 : SM6-CBC : sm6-cbc
!Cname sm6-ofb128
sm-scheme 101 3 : SM6-OFB : sm6-ofb
!Cname sm6-cfb128
sm-scheme 101 4 : SM6-CFB : sm6-cfb
!Alias sm7 sm-scheme 105
!Alias sm8 sm-scheme 106# SM9
sm-scheme 302 : id-sm9PublicKey
sm-scheme 302 1 : sm9sign
sm-scheme 302 2 : sm9keyagreement
sm-scheme 302 3 : sm9encrypt
sm-scheme 302 4 : sm9hash1
sm-scheme 303 7 : sm9hash2
sm-scheme 302 5 : sm9kdf
sm-scheme 302 6 : id-sm9MasterSecret
sm-scheme 302 6 1 : sm9bn256v1
sm9sign 1 : sm9sign-with-sm3
sm9sign 2 : sm9sign-with-sha256
sm9encrypt 1 : sm9encrypt-with-sm3-xor
sm9encrypt 2 : sm9encrypt-with-sm3-sms4-cbc
sm9encrypt 3 : sm9encrypt-with-sm3-sms4-ctr
sm9hash1 1 : sm9hash1-with-sm3
sm9hash1 2 : sm9hash1-with-sha256
sm9hash2 1 : sm9hash2-with-sm3
sm9hash2 2 : sm9hash2-with-sha256
sm9kdf 1 : sm9kdf-with-sm3
sm9kdf 2 : sm9kdf-with-sha256
密碼套件
- 僅僅定義了OID還不夠,因為國密并不是一個單一的標準,包含了很多加密、解密、哈希等算法,可以形成很多種組合,不能簡單假定對方采用了國密就可以建立通信。
- 在SSL通信開始,雙方就需要進行協商,采用何種算法進行通信。這就引出了密碼套件(CipherSuite)的概念。
- 密碼套件是一系列密碼學算法的組合,主要包含多個密碼學算法:
- 密鑰交換算法:用于握手過程中建立信道,一般采用非對稱加密算法
- 數據加密算法:用于信道建立之后的加密傳輸數據,一般采用對稱加密算法
- 消息驗證算法:用于驗證消息的完整性,包括整個握手流程的完整性(例如TLS握手的最后一步就是一個對已有的握手消息的全盤哈希計算的過程)
- 密碼套件的構成如下圖所示:
- /home/chy-cpabe/Downloads/GmSSL-master/README.md? 文件內部包含了國密算法套件的定義?
- 代碼可以參考 gmtls.h 文件,也可以使用GMSSL的命令查看所支持的密碼套件: openssl ciphers -V | column -t
- 如果使用gmssl,將openssl替換成gmssl即可,如果未配置全局路徑,需要到編譯后生成的可執行腳本處執行上述命令?
?
- 第一列:數值代表密碼套件的編號,每個密碼套件的編號由IANA定義。
- 第二列:代表密碼套件的名稱,雖然密碼套件編號是一致的,不同的TLS/SSL協議實現其使用的名稱可能是不一樣的。
- 第三列:表示該密碼套件適用于哪個TLS/SSL版本的協議。
- 第四列:表示密鑰協商算法。
- 第五列:表示身份驗證算法。
- 第六列:表示加密算法、加密模式、密鑰長度。
- 第七列:表示HMAC算法。其中AEAD表示采用的是AEAD加密模式(比如AES128-GCM),無須HMAC算法。
操作流程
- 一個密碼學套件是完成整個TLS握手的關鍵。在TLS握手的時候ClientHello里面攜帶了客戶端支持的密碼學套件列表,ServerHello中攜帶了Server根據Client提供的密碼學套件列表中選擇的本地也支持的密碼學套件。
- 也就是說選擇使用什么密碼學套件的選擇權在Server的手里,這句話感覺有問題,客戶端先選擇密碼學套件列表,看服務器是否支持,或者服務器考慮到算法的安全性會禁用不安全的密碼學套件? 我的這句話有問題,借此提醒
注意事項
- 值得注意的是,這里的編碼又沒有采用OID,這也是開發過程中需要注意的,不同的地方使用了不同標準規范,需要在開發中翻閱相應的協議和規范。
- 可以看出,GmSSL并沒有實現所有的國密的密碼套件,但同時又擴充了幾個標準未定義的密碼套件,比如ECDHE-SM2-WITH-SMS4-GCM-SM3、ECDHE-SM2-WITH-SMS4-SM3等。這就體現出協商的重要性了,對雙方所支持的密碼套件取一個交集,從中選擇一個。如果不存在交集,協商也就不成功。注意,協商過程中服務器端可能會禁用一些不太安全的密碼套件(比如歷史遺留的一些現今已不太安全的算法),這時即使雙方都支持,也可能協商不成功。
- 我們可以測試服務器是否支持某個特定的密碼套件:
?代碼編寫
- Openssl定義了4中選擇符號:“+”,“-”,“!”,“@”。其中,“+”表示取交集;“-”表示臨時刪除一個算法;“!”表示永久刪除一個算法;“@“表示了排序方法。
- 多個描述之間可以用“:”或“,”或空格或“;”來分開。選擇加密套件的時候按照從左到的右順序構成雙向鏈表,存放與內存中。
ALL:!DH:RC4+RSA:+SSLv2:@STRENGTH
- 表示的意義是:首先選擇所有的加密套件,然后在得到的雙向鏈表之中去掉密鑰交換采用DH的加密套件;加入包含RC4對稱加密算法與RSA身份認證算法的交集加密套件;再將支持老版本SSLv2的加密套件放在尾部;最后,
@STRENGTH
表示將得到的結果按照安全強度進行排序。 - SSL建立鏈接之前,客戶端和服務器端用openssl函數來設置自己支持的加密套件。主要的函數有:
int SSL_set_cipher_list(SSL *s, const char *str);
int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str);
- 比如只設置一種加密套件:
int ret=SSL_set_cipher_list(ssl,"RC4-MD5");
- 如果服務端只設置了一種加密套件,那么客戶端要么接受要么返回錯誤。
- 加密套件的選擇是由服務端做出的。客戶端沒有權利指定其他加密套件。