非對稱加密演算法與TLS
來自專欄 TLS與OpenSSL
非對稱加密是一大類加密演算法,這種演算法中有一個公鑰,一個私玥,使用公鑰加密的數據只有使用對應的私鑰才能解密,使用私鑰進行加密的數據只有公鑰才能解密。也就是說,本質上,非對稱加密的本質是一對密鑰,至於哪一個做公鑰,哪一個做私鑰,這個沒有太本質的區別。但是一定有一個密鑰是自己保存的保密密鑰,另一個是可以公開給任何人看的公鑰。
在這種演算法框架下,非對稱加密有兩個重要作用。一個是驗證,一個是加密。在驗證上,A使用B的公鑰對一個數字進行加密發給B,如果B能成功解密,那麼B必然持有對應的正確的私鑰。B就把解密之後的數字返還給A,這時A就可以認證B為真實的通信目標。同樣的,如果B返回解密之後的數字的時候使用的A的公鑰進行加密,A再用A的私鑰進行解密再用B的公鑰再次返還給B,整個通信過程就是加密的,B也就認證了A,就完成了雙向認證,同時還包括了加密傳輸的能力。
但是實際的非對稱加密的應用複雜得多。由於非對稱加密的性能相對於對稱加密差很多,所以雖然非對稱加密可以用於加密的數據傳輸,但是實際的應用中,非對稱加密一般用於協商更加快速的對稱加密的密碼學參數。也就是說是一個輔助信道建立的過程。因此,非對稱加密在產業中的應用主要是驗證和信道建立的協商過程。
非對稱加密又叫做公鑰加密,公鑰和私鑰之間是有數學關聯的,外部都是可以輕鬆獲得到公鑰,但是無法獲得或者計算得到私鑰。這個私鑰雖然與公鑰有關聯,但是無法計算的能力,就是非對稱加密的核心,或者說是健壯性。這種健壯性通常依賴於某個目前難以解決的數學問題。比如大整數分解,橢圓曲線關係等至今不能很好得出答案的數學問題。例如給定一個超大的整數,分解為兩個素數的積,在私鑰持有方,他同時持有兩個私鑰,所以他能輕鬆的計算得到兩個素數的積,但是公開的數據只有兩個素數的積,其他人沒有很強大的數學工具是無法輕鬆的得到這兩個素數的。
TLS協議的證書系統和握手過程都是重度的依賴非對稱加密方法。市場上還有很多其他的協議應用,例如MIME,PGP等也是依賴非對稱加密。事實上,大部分的加密通信的基礎設施框架都是同時依賴了非對稱加密(認證和握手),哈希演算法(完整性檢查)和對稱加密(加密通信)。
互聯網中通信的雙方,客戶對服務端發起請求,通常情況下客戶端通過域名確定一個服務端就是服務端,但是很多時候域名很多仿造的名字相似的釣魚網站,還有域名被劫持的情況,在這種情況下,單靠域名已經不能有效的從根本上解決客戶端對服務端的信任問題。同樣的服務端更沒有辦法解決懟客戶端的信任問題,大部分情況下,互聯網中更關係客戶端對服務端的信任。這種情況下,即使使用非對稱加密在客戶端和服務端建立了秘密的協議,客戶端都難以從根本上判斷服務端的身份,所以第三方介入的證書系統就誕生了。非對稱加密在證書系統中充分的發揮他的威力,來做到客戶端對服務端的認證問題。
大概的思路是這樣的。參與通信的有三方,CA(certificate authority )作為一個第三方參與進來。現在服務端和CA各有一個私鑰和公鑰,客戶端可以同時拿到CA的公鑰和伺服器的公鑰,這兩者都是公開的。我們知道只有CA的公鑰可以解密CA私鑰加密的數據,因此假設使用一個域名作為一個證書請求(例如http://abc.com),伺服器的服務域名就是http://abc.com,現在伺服器要使得客戶端信任這個域名,客戶端首先是無條件信任CA的,也就是說他會CA的公鑰去驗證服務端的身份。在通信之前,服務端把http://abc.com這個字元串發送給CA(這一步是要保證百分百安全的,因為是一個線下的複雜認證過程),CA用自己的私鑰對這個字元串進行簽名,就獲得了一個頒發給伺服器的證書。當客戶端要訪問伺服器的時候,伺服器傳送給客戶端這個證書,客戶端用CA的公鑰解密得到的域名與他要訪問的域名相匹配,他就可以認為這個網站是可信的。因為這個伺服器持有了CA給他頒發的證書。
我們看整個步驟只使用了CA的公鑰和私鑰對,客戶端也只是確認了服務端的身份。並且這個確認是有嚴重問題的,也就是服務端把CA頒發給他的證書明文發出去了,這個時候其他人也就持有了這個證書,如果發生了域名劫持。其他人完全可以使用域名和截獲的證書對服務端進行輕鬆的偽造。所以上面的過程仍然是不安全的,但是他已經代表了CA的主要思路。整個CA系統的複雜度遠超過這個簡單的模型,整套CA系統的所有參與者共同組成了public key infrastructure (PKI) 這套互聯網中的基礎設施的統稱。
上表是wiki中列出的在各個版本的TLS中各種非對稱加密的使用情況。由於TLS是使用各種加密演算法的急先鋒,通過TLS的使用情況就大概的能看到加密演算法的發展情況。RSA是最古老,最成熟,也是應用最廣泛的非對稱加密演算法,其發明時間早在1978年。RSA三個字母就是三個發明人的名字的首字母。
RSA利用的核心思想就是大素數分解的問題。這個問題雖然理解起來簡單,但是破解起來非常難,以至於RSA至今為止仍舊是應用最廣泛的非對稱加密演算法。雖然描述起來是兩個大素數分解因式,但是實際的實現相對複雜很多。不是任何的兩個大素數都可以用,而必須要滿足一系列的條件。本書不是一本密碼學的書,不進行深入探討。
雖然RSA三人發明了RSA,但是非對稱加密的思想的提出者確是鼎鼎大名的DH兩人。DH這兩個字母也是兩位發明人的首字母,這兩個字母在密碼學上的地位,可以說是開創性和開拓性的。我們看SSL 2.0的時候還只是支持RSA,在3.0的時候就開始支持了DH-RSA,這也就充分說明了密碼學的發展路線,此時開始,DH正式登場。但是實際的發明DH演算法的並不是DH兩人,而是伯克利大學的默克爾教授(鼎鼎大名的默克爾可信樹就是他的傑作)。
表格中的第二個是DH-RSA,寫成兩個的意思是DH是密鑰交換的演算法,RSA是證書演算法。也就是說是RSA證書。我們常說的公鑰私玥證書大部分情況下就是RSA證書。事實上任何的證書都是公鑰私鑰結構的,只是具體的演算法有區別。RSA利用的大素數分解因式,在RSA的基礎上改進的DSA也同樣是利用大素數分解因式,在DSA基礎上改進的ECDSA就是用了DSA的改進基礎,將大素數分解因式替換成了橢圓曲線問題。使用了ECDSA這個非對稱加密演算法的證書叫做ECC證書(橢圓曲線),使用了RSA做證書的非對稱加密演算法的叫做RSA證書。這裡面有一個特殊的地方,是DSA。
DSA本身雖然是經過RSA改進而來的,但是我們知道DSA並沒有對應的DSA證書。
DSA(Digital Signature Algorithm)的全稱就是數字簽名演算法,雖然和RSA只是差了一個字母,但是DSA如其名字所述,是一種專用的數字簽名演算法,從應用上是哈希演算法的一種,雖然其使用了公鑰和私鑰的體系,但是並不能用於加密。而ECDSA卻是可以用於加密的,所以有對應的證書格式。
在TLS中,證書的目標是用非對稱加密演算法來驗證身份,而握手演算法的目標是使用非對稱加密演算法協商出對稱加密的密鑰。雖然證書的主要目標是驗證身份,但是其畢竟也同時是一種可以用來加密數據的信道演算法。所以早期是可以直接用RSA證書的公鑰和私鑰本身來溝通對稱加密的密鑰的。PGP就是直接利用RSA本身的公鑰私鑰來溝通對稱加密密鑰的典型做法。
DH是一種加密的溝通信息的方法,沒有身份驗證功能。所以常用於握手溝通非對稱加密的密鑰。事實上,DH從發明的那一刻起就是專用於溝通密鑰的,而不是用於加密的,非對稱加密的數學原理也不是分解因式,而是離散對數問題。DH演算法在TLS中應用的時候叫做DHE(exchange),性能比RSA稍差,但是比RSA的一個巨大的優勢是提供了PFS支持(完美前向安全)。也就是安全性上的提高。ECDHE是對DHE的改進,無論在安全性還是在性能上都比DHE要好,所以ECDHE可以用的情況下,DHE就基本沒有採用的可能性。
騰訊雲的統計
使用RSA雖然可以做到性能上是最快的,但是RSA證書的大小是最大的。ECC證書(橢圓曲線證書)當前正在一個推廣的過程中,取代RSA證書是時間問題。所以當前最通過的握手套件是ECDHE-RSA。但是在大規模推廣了ECC證書之後,這個組合就會變成ECDSA-ECDSA,也就是同時使用ECDSA進行證書和對稱加密的密鑰溝通。
PSK的全稱是Pre-Shared Keys,雖然叫起來比較專業難懂,但是其實這是我們最常見的密鑰協議。我們最長使用的在一個網站上先註冊一個用戶名,給自己設置一個密碼,然後之後再使用這個密碼登陸這個網站,就是PSK。這個Pre-Shared Keys就是我們註冊的時候設置的密碼,這個設置的過程就是一個pre-share的過程。也就是說,在TLS中也可以如此,我們知道大部分的網站是面向公共環境的,誰都可以訪問,這種情況下PSK是無效的,因為PSK必須要預置密鑰,這個預置的過程就代表了服務端已經知道有哪些客戶端需要訪問了。所以基於PSK的TLS適合在內部系統中使用,而不適合在公網環境用來提供Web服務。
表格中的ANON代表是匿名的意思。也就是說不需要經過任何的證書認證。這種形式的TLS信道就是一種純對稱加密的信道,通信的雙方通過非對稱加密演算法溝通得到對稱加密信道的參數,然後直接使用這個信道通信。雙方都不知道對方是否是真實的通信對象,關注的是信道加密和數據的完整性,而不關注身份驗證。因此這種機制在公網的web服務很少見,但是在特殊情況下,例如使用其他的方式提供了身份驗證的時候,就可以使用。
性能
RSA演算法中有一步最耗費CPU的操作就是取模運算,這個運算在OpenSSL採用的是蒙哥馬利乘法,就是一種將除法運算變為乘法的操作,這個操作在整個TLS握手中都是最耗費CPU資源的。這個演算法位於OpenSSL的大數引擎部分,BoringSSL也是用了同樣的大數引擎。GMP大數引擎在新版本的表現也並不比OpenSSL的大數引擎好。
openssl命令當然也不能放過對非對稱加密演算法的支持。非對稱加密在業務上遠比對稱加密複雜,所以對應的命令和選項也會相對多很多。例如rsa演算法也會有對應的專門的子命令openssl rsa和openssl rsautl還有一個genrsa的相關命令。幾乎需要的任何與rsa相關的操作,使用openssl命令都可以直接實現。openssl的豐富的子命令主要有三個價值,一個是腳本編程的價值,它提供了完整的密碼學解決方案。另外一個是驗證性價值,我們可以使用命令從各個方位多個角度評估OpenSSL主體的實現質量。還有一個對於開發者來說最重要的是它本身就是一個demo程序,可以讓我們以最好的角度學習OpenSSL的源代碼開發。
推薦閱讀:
※最大根方法——一段往事
※非常規進位 —— 以 -2 為底的按位計數系統
※急!孩子對數學不感興趣怎麼辦?
※局部域(二)完備化