簡介
自從HTTP從1.1升級到了2,一切都變得不同了。雖然HTTP2沒有強制說必須使用加密協議進行傳輸,但是業界的標准包括各大流行的瀏覽器都只支持HTTPS情況下的HTTP2協議。
那么怎么在HTTPS之中加入HTTP2協議的支持呢?今天本文將會跟大家聊一下SSL/TLS協議的擴展NPN和ALPN。
SSL/TLS協議
SSL(Secure Socket Layer)安全套接層,是1994年由Netscape公司設計的一套協議,並與1995年發布了3.0版本。
TLS(Transport Layer Security)傳輸層安全是IETF在SSL3.0基礎上設計的協議,實際上相當於SSL的后續版本。
SSL/TLS是一種密碼通信框架,他是世界上使用最廣泛的密碼通信方法。
TLS主要分為兩層,底層的是TLS記錄協議,主要負責使用對稱密碼對消息進行加密。
上層的是TLS握手協議,主要分為握手協議,密碼規格變更協議和應用數據協議4個部分。
其中最重要的就是握手協議,通過客戶端和服務器端的交互,和共享一些必要信息,從而生成共享密鑰和交互證書。
接下來我們一步步的介紹每一步的含義:
-
client hello
客戶端向服務器端發送一個client hello的消息,包含下面內容:
- 可用版本號
- 當前時間
- 客戶端隨機數
- 會話ID
- 可用的密碼套件清單
- 可用的壓縮方式清單
我們之前提到了TLS其實是一套加密框架,其中的有些組件其實是可以替換的,這里可用版本號,可用的密碼套件清單,可用的壓縮方式清單就是向服務器詢問對方支持哪些服務。
客戶端隨機數是一個由客戶端生成的隨機數,用來生成對稱密鑰。
-
server hello
服務器端收到client hello消息后,會向客戶端返回一個server hello消息,包含如下內容:
- 使用的版本號
- 當前時間
- 服務器隨機數
- 會話ID
- 使用的密碼套件
- 使用的壓縮方式
使用的版本號,使用的密碼套件,使用的壓縮方式是對步驟1的回答。
服務器隨機數是一個由服務器端生成的隨機數,用來生成對稱密鑰。
-
可選步驟:certificate
服務器端發送自己的證書清單,因為證書可能是層級結構的,所以處理服務器自己的證書之外,還需要發送為服務器簽名的證書。
客戶端將會對服務器端的證書進行驗證。如果是以匿名的方式通信則不需要證書。 -
可選步驟:ServerKeyExchange
如果第三步的證書信息不足,則可以發送ServerKeyExchange用來構建加密通道。
ServerKeyExchange的內容可能包含兩種形式:
- 如果選擇的是RSA協議,那么傳遞的就是RSA構建公鑰密碼的參數(E,N)。我們回想一下RSA中構建公鑰的公式:\(密文=明文^E\ mod\ N\), 只要知道了E和N,那么就知道了RSA的公鑰,這里傳遞的就是E,N兩個數字。具體內容可以參考RSA算法詳解
- 如果選擇的是Diff-Hellman密鑰交換協議,那么傳遞的就是密鑰交換的參數,具體內容可以參考更加安全的密鑰生成方法Diffie-Hellman
-
可選步驟:CertificateRequest
如果是在一個受限訪問的環境,比如fabric中,服務器端也需要向客戶端索要證書。
如果並不需要客戶端認證,則不需要此步驟。 -
server hello done
服務器端發送server hello done的消息告訴客戶端自己的消息結束了。 -
可選步驟:Certificate
對步驟5的回應,客戶端發送客戶端證書給服務器
-
ClientKeyExchange
還是分兩種情況:
- 如果是公鑰或者RSA模式情況下,客戶端將根據客戶端生成的隨機數和服務器端生成的隨機數,生成預備主密碼,通過該公鑰進行加密,返送給服務器端。
- 如果使用的是Diff-Hellman密鑰交換協議,則客戶端會發送自己這一方要生成Diff-Hellman密鑰而需要公開的值。具體內容可以參考更加安全的密鑰生成方法Diffie-Hellman,這樣服務器端可以根據這個公開值計算出預備主密碼。
-
可選步驟:CertificateVerify
客戶端向服務器端證明自己是客戶端證書的持有者。
-
ChangeCipherSpec(准備切換密碼)
ChangeCipherSpec是密碼規格變更協議的消息,表示后面的消息將會以前面協商過的密鑰進行加密。
-
finished(握手協議結束)
客戶端告訴服務器端握手協議結束了。
-
ChangeCipherSpec(准備切換密碼)
服務器端告訴客戶端自己要切換密碼了。
-
finished(握手協議結束)
服務器端告訴客戶端,握手協議結束了。
-
切換到應用數據協議
這之后服務器和客戶端就是以加密的方式進行溝通了。
NPN和ALPN
上面我們介紹SSL/TLS協議的時候,最后一步是切換到應用數據協議,那么客戶端是怎么和服務器端討論協商具體使用哪種應用數據協議呢?是使用HTTP1.1?還是HTTP2?還是SPDY呢?
這里就要用到TLS擴展協議了。而NPN(Next Protocol Negotiation) 和 ALPN (Application Layer Protocol Negotiation) 就是兩個TLS的擴展協議。
他們主要用在TLS中,用來協商客戶端和服務器端到底應該使用什么應用數據協議進行溝通。
其中NPN是SPDY使用的擴展,而ALPN是HTTP2使用的擴展。
他們兩個有什么區別呢?
相較於NPN來說,ALPN在client hello消息中已經列出了客戶端支持的應用層協議,服務器端只需要從中選擇出它支持的協議即可。比NPN少了一個交互的步驟,所以ALPN是推薦的協議。
下面是具體的交互流程圖:
交互的例子
下面以ALPN為例,講解下具體的交互流程,首先是客戶端發送”Client Hello“消息:
Handshake Type: Client Hello (1)
Length: 141
Version: TLS 1.2 (0x0303)
Random: dd67b5943e5efd0740519f38071008b59efbd68ab3114587...
Session ID Length: 0
Cipher Suites Length: 10
Cipher Suites (5 suites)
Compression Methods Length: 1
Compression Methods (1 method)
Extensions Length: 90
[other extensions omitted]
Extension: application_layer_protocol_negotiation (len=14)
Type: application_layer_protocol_negotiation (16)
Length: 14
ALPN Extension Length: 12
ALPN Protocol
ALPN string length: 2
ALPN Next Protocol: h2
ALPN string length: 8
ALPN Next Protocol: http/1.1
可以看到在client hello消息中的Extension字段中,使用了ALPN,並且列出了可以選擇使用的兩種ALPN Protocol:h2和http/1.1。
對應的“server hello” 消息會選擇出具體使用的ALPN protocol如下:
Handshake Type: Server Hello (2)
Length: 94
Version: TLS 1.2 (0x0303)
Random: 44e447964d7e8a7d3b404c4748423f02345241dcc9c7e332...
Session ID Length: 32
Session ID: 7667476d1d698d0a90caa1d9a449be814b89a0b52f470e2d...
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
Compression Method: null (0)
Extensions Length: 22
[other extensions omitted]
Extension: application_layer_protocol_negotiation (len=5)
Type: application_layer_protocol_negotiation (16)
Length: 5
ALPN Extension Length: 3
ALPN Protocol
ALPN string length: 2
ALPN Next Protocol: h2
如上所示,服務器端選擇了h2, 最終當客戶端和服務器端TLS握手結束之后,會選擇使用HTTP2作為后續的應用層數據協議。
總結
NPN和ALPN都是TLS的擴展,相較而言,ALPN更加好用。
本文已收錄於 http://www.flydean.com/08-ssl-tls-npn-alpn/
最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程序那些事」,懂技術,更懂你!