QUIC学习笔记之 如何做到0RTT加密传输
簡單介紹下什么是QUIC,這是從Google官方文檔抄錄的一段話
QUIC (Quick UDP Internet Connections) is a new transport protocol for the internet, developed by Google.
QUIC solves a number of transport-layer and application-layer problems experienced by modern web applications, while requiring little or no change from application writers. QUIC is very similar to TCP+TLS+HTTP2, but implemented on top of UDP. Having QUIC as a self-contained protocol allows innovations which aren’t possible with existing protocols as they are hampered by legacy clients and middleboxes.
簡單來說,就是QUIC是Google提出的一種基于UDP改進(jìn)的通信協(xié)議,其目的是降低網(wǎng)絡(luò)通信的延遲,提供更好的用戶交互體驗。
原本的TCP+TLS的RTT耗時大,主要是由于TCP需要三次握手,以及TLS需要多次交換數(shù)據(jù)來生成安全的密鑰
而QUIC則使用了Diffie-Hellman算法(迪菲-赫爾曼算法)來保證數(shù)據(jù)交互的安全性并合并了它的加密和握手過程來減小連接建立過程中的往返次數(shù),以此來達(dá)到0RTT的目的
Diffie-Hellman算法
DH算法,由W.Diffie和M.E.Hellman在1976年公布的一種密鑰一致性算法,該算法是一種建立密鑰的方法,并非加密方法,但其產(chǎn)生的密鑰可用于加密、密鑰管理或任何其它的加密方式,這種密鑰交換技術(shù)的目的在于使兩個用戶間能安全地交換密鑰(KEY)以便用于今后的報文加密。
離散對數(shù):定義素數(shù)p的原始根為滿足如下條件的整數(shù),如果g為p的原始根,則:g mod p,g^ mod p,…,g^(p-1) mod p是各不相同的整數(shù),且以某種排列方式組成了從1到p-1的所有整數(shù)。
對于任意數(shù)b及素數(shù)p的原始根g,可以找到一個唯一的指數(shù)i,滿足:b=(g^ i )mod p,其中0≤i≤p-1,那么指數(shù)i 稱為b的以g為基數(shù)的模p的離散對數(shù)。
Diffie-Hellman算法的有效性依賴于計算離散對數(shù)的難度,當(dāng)已知大素數(shù)p和它的一個原根a后,對于給定的b,要計算出i 被認(rèn)為是很困難的,而給定i 計算b卻相對容易。
其協(xié)商密鑰的流程如下:
1)雙方都共享一個大素數(shù)p和它的原始根g
2)各自產(chǎn)生一個隨機數(shù)X,通過g^X mod p 計算出一個public value Y,將其發(fā)送給對方
3)各自在使用接收到的Y(public value)計算出相同的密鑰K (K = Y^X mod p)
最終雙方計算出一致的密鑰,就可以用于加解密了
將這種發(fā)送給對方的key稱為public key,保留在自己手上的key為private key
這里Ya,Yb就是public key,A和B就是private key
QUIC Handshake
QUIC協(xié)議依賴于合并加密和數(shù)據(jù)傳輸過程中的握手來創(chuàng)建一個安全的連接。 在連接建立成功后, 客戶端會緩存起來原始的連接信息等。 在接下來與相同的服務(wù)器建立連接的過程中, 客戶端能夠在不增加額外RTT的情況下建立一個加密的連接,數(shù)據(jù)要發(fā)送的數(shù)據(jù)可以在握手的包中捎帶著發(fā)送過去,而不用等待服務(wù)器的回復(fù),從而實現(xiàn)0RTT。
所以,所謂QUIC的0RTT是指在建立連接之后,后續(xù)發(fā)送數(shù)據(jù)都不需要增加額外的RTT時間,最開始的握手還是需要1RTT的時間消耗的
注意這里的Diffie-Hellman key不單單分為public key和private key,還有各自不同的生命周期long-term key 和ephemeral key,前者用于生成初始密鑰,后者用于生成后續(xù)加密的密鑰
Initial Handshake:
開始握手時,客戶端會像服務(wù)端發(fā)送Inchoate CHLO的命令,服務(wù)器會返回REJ消息,它包括:
接收到這個REJ消息后,客戶端會進(jìn)行解析認(rèn)證,緩存必要的配置,之后客戶端再向服務(wù)端發(fā)送一個COMPLETE CHLO, 會在其中帶上客戶端的ephemeral DH public value
Final (and repeat) handshake
一個連接的所有key都是通過Diffie-Hellman算法來創(chuàng)建的。
發(fā)送Complete CHLO之后, 客戶端會產(chǎn)生自己的initial key (通過服務(wù)端的long-term Diffie-Hellman public value以及客戶端的ephemeral Diffie-Hellman private value)
有了密鑰,此時客戶端就能使用initial key加密應(yīng)用數(shù)據(jù)發(fā)送到服務(wù)端了(為了實現(xiàn)這里的0RTT,客戶端不會等待COMPLETE CHLO的回復(fù),而是直接發(fā)送加密的數(shù)據(jù)包)。 如果握手成功了, 服務(wù)端返回一個server hello(SHLO)消息。 這個消息用initial keys進(jìn)行了加密, 并且含有服務(wù)端ephemeral的Diffie-Hellman的public value。
這樣客戶端和服務(wù)端就都有了對方的ephemeral的Diffie-Hellman的public value,這樣就會生成第二個密鑰 forward-secure key.服務(wù)端會使用這個密鑰來加密自己對客戶請求的response結(jié)果,而客戶端后面的數(shù)據(jù)包也會使用forward-secure key來加密
QUIC提供了兩個層面的安全性保證:
最初的handshake通過initial keys加密,后續(xù)的客戶端信息和服務(wù)端信息通過forward-secure 加密
這樣就可以保證密鑰的前向安全性,之后也可以在通信的過程中就實現(xiàn)對密鑰的更新。接收方意識到有新的密鑰要更新時,會嘗試使用新舊兩種密鑰對數(shù)據(jù)進(jìn)行解密,直到成功才會正式更新密鑰,否則會一直保留舊密鑰。
客戶端會緩存server config和source-address token,如果再次向相同的服務(wù)器建立連接就會直接發(fā)送Complete CHLO命令,實現(xiàn)0-RTT
如果source-address token或者server config過期,服務(wù)端會發(fā)送REJ消息 ,就會像Initial handshake一樣,重新進(jìn)行連接的建立
我認(rèn)為之所以將發(fā)送連接拒絕的情形也認(rèn)為是0RTT,是因為在拒絕連接的同時也返回了建立連接所需的REJ消息,這樣客戶端在下次交互時就可以直接傳輸有效的數(shù)據(jù)包給服務(wù)端而不需要額外的RTT時間
版本協(xié)商:
Quic 的客戶端會在第一個packet里聲明自己的version ,如果server端并不使用這個client version,那么服務(wù)端會發(fā)送一個帶有所有server端支持的版本信息的Version Negotiation packet,以供客戶端選擇合適的版本
最后是一個Google官網(wǎng)關(guān)于QUIC握手的一個流程圖
(1) 客戶端判斷本地是否已有服務(wù)器的全部配置參數(shù),如果有則直接跳轉(zhuǎn)到(5)發(fā)送client hello
(2) 客戶端向服務(wù)器發(fā)送inchoate client hello(CHLO)消息,嘗試建立連接
(3) 服務(wù)器收到CHLO,回復(fù)rejection(REJ)消息,其中包含服務(wù)器的server config ,long-term DH public key 等
(4) 客戶端收到REJ,提取并認(rèn)證和存儲服務(wù)器server config
(5) 客戶端向服務(wù)器發(fā)送client hello消息,開始準(zhǔn)備發(fā)送數(shù)據(jù)包,消息中包括客戶端的DH public vlaue。此時客戶端可以根據(jù)server config參數(shù)和自己的public value,計算出初始密鑰。
(6) 服務(wù)器收到 client hello,如果不同意連接就回復(fù)REJ,同(3);如果同意連接,根據(jù)客戶端的public value計算出初始密鑰initial key,并回復(fù)server hello(SHLO)消息,SHLO使用initial key加密,并且其中包含服務(wù)器的臨時的DH public value
(7) 客戶端收到服務(wù)器的回復(fù),如果是REJ則情況同(4);如果是SHLO,則嘗試用初始密鑰解密,提取出ephemeral DH public value
(8) 客戶端和服務(wù)器根據(jù)得到的ephemeral public key, 計算出新的forward-secure key
(9) 雙方更換為使用 forward-secure key 通信,QUIC握手過程完畢。之后會話密鑰更新的流程與以上過程類似。
參考鏈接:
The QUIC Transport Protocol:Design and Internet-Scale Deployment
QUIC Crypto
總結(jié)
以上是生活随笔為你收集整理的QUIC学习笔记之 如何做到0RTT加密传输的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 让互联网更快的协议,QUIC在腾讯的实践
- 下一篇: TCP的拥塞控制--慢启动,拥塞避免,快