1990年互聯網誕生之初,就已經開始用超文本傳輸協議 HTTP 傳輸數據,這也是為什么現在網頁地址都是以 http 開頭的原因。但是HTTP協議傳輸數據是明文傳輸,任意的人抓包就能看到傳輸的數據,這顯然不安全。1994年,Netscape 公司用加密協議增加了 HTTP,開始在 HTTP 的基礎上加入 SSL 即安全套接層(Secure Socket Layer)。稱為 "HTTP over SSL" 或者 "HTTP Secure",也就是我們現在熟知的 HTTPS。
HTTPS 其實是一個“非常簡單”的協議,RFC 文檔很小,只有短短的 7 頁,里面規定了新的協議名“https”,默認端口號 443,至于其他的什么請求 - 應答模式、報文結構、請求方法、URI、頭字段、連接管理等等都完全沿用 HTTP,沒有任何新的東西。
也就是說,除了協議名“http”和端口號 80 這兩點不同,HTTPS 協議在語法、語義上和 HTTP 完全一樣,優缺點也“照單全收”(當然要除去“明文”和“不安全”)。
SSL/TLS
SSL/TLS是位于TCP/IP 7層協議中的會話層,用于認證用戶和服務器,加解密數據以及維護數據的完整性,確保數據在傳輸過程中不會被修改。
SSL 有 v2 和 v3 兩個版本,而 v1 因為有嚴重的缺陷從未公開過。SSL 發展到 v3 時已經證明了它自身是一個非常好的安全通信協議,于是互聯網工程組 IETF 在 1999 年把它改名為 TLS(傳輸層安全,Transport Layer Security),正式標準化,版本號從 1.0 重新算起,所以 TLS1.0 實際上就是 SSLv3.1。
到今天 TLS 已經發展出了三個版本,分別是 2006 年的 1.1、2008 年的 1.2 和去年(2018)的 1.3,每個新版本都緊跟密碼學的發展和互聯網的現狀,持續強化安全和性能,已經成為了信息安全領域中的權威標準。
目前應用的最廣泛的 TLS 是 1.2,而之前的協議(TLS1.1/1.0、SSLv3/v2)都已經被認為是不安全的,各大瀏覽器即將在 2020 年左右停止支持,所以接下來的講解都針對的是 TLS1.2。
TLS 由記錄協議、握手協議、警告協議、變更密碼規范協議、擴展協議等幾個子協議組成,綜合使用了對稱加密、非對稱加密、身份認證等許多密碼學前沿技術。瀏覽器和服務器在使用 TLS 建立連接時需要選擇一組恰當的加密算法來實現安全通信,這些算法的組合被稱為“密碼套件”(cipher suite,也叫加密套件)。
SSL/TLS分為對稱加密和非對稱加密兩種方式。
對稱加密
對稱加密是指加密和解密都用同一份密鑰。如下圖所示:
AES 的意思是“高級加密標準”(Advanced Encryption Standard),密鑰長度可以是 128、192 或 256。它是 DES 算法的替代者,安全強度很高,性能也很好,而且有的硬件還會做特殊優化,所以非常流行,是應用最廣泛的對稱加密算法。
ChaCha20 是 google 設計的另一種加密算法,密鑰長度固定為 256 位,純軟件運行性能要超過 AES,曾經在移動客戶端上比較流行,但 ARMv8 之后也加入了 AES 硬件優化,所以現在不再具有明顯的優勢,但仍然算得上是一個不錯算法。
非對稱加密
非對稱加密對應于一對密鑰,稱為私鑰和公鑰,用私鑰加密后需要用公鑰解密,用公鑰加密后需要用私鑰解密。如下圖所示:
對稱加密看上去好像完美地實現了機密性,但其中有一個很大的問題:如何把密鑰安全地傳遞給對方,術語叫“密鑰交換”。
因為在對稱加密算法中只要持有密鑰就可以解密。如果你和網站約定的密鑰在傳遞途中被黑客竊取,那他就可以在之后隨意解密收發的數據,通信過程也就沒有機密性可言了。
這個問題該怎么解決呢?
你或許會說:“把密鑰再加密一下發過去就好了”,但傳輸“加密密鑰的密鑰”又成了新問題。這就像是“雞生蛋、蛋生雞”,可以無限遞歸下去。只用對稱加密算法,是絕對無法解決密鑰交換的問題的。
所以,就出現了非對稱加密(也叫公鑰加密算法)。
它有兩個密鑰,一個叫“公鑰”(public key),一個叫“私鑰”(private key)。兩個密鑰是不同的,“不對稱”,公鑰可以公開給任何人使用,而私鑰必須嚴格保密。
公鑰和私鑰有個特別的“單向”性,雖然都可以用來加密解密,但公鑰加密后只能用私鑰解密,反過來,私鑰加密后也只能用公鑰解密。
非對稱加密可以解決“密鑰交換”的問題。網站秘密保管私鑰,在網上任意分發公鑰,你想要登錄網站只要用公鑰加密就行了,密文只能由私鑰持有者才能解密。而黑客因為沒有私鑰,所以就無法破解密文。
非對稱加密算法的設計要比對稱算法難得多,在 TLS 里只有很少的幾種,比如 DH、DSA、RSA、ECC 等。
- RSA 可能是其中最著名的一個,幾乎可以說是非對稱加密的代名詞,它的安全性基于“整數分解”的數學難題,使用兩個超大素數的乘積作為生成密鑰的材料,想要從公鑰推算出私鑰是非常困難的。10 年前 RSA 密鑰的推薦長度是 1024,但隨著計算機運算能力的提高,現在 1024 已經不安全,普遍認為至少要 2048 位。
- ECC(Elliptic Curve Cryptography)是非對稱加密里的“后起之秀”,它基于“橢圓曲線離散對數”的數學難題,使用特定的曲線方程和基點生成公鑰和私鑰,子算法 ECDHE 用于密鑰交換,ECDSA 用于數字簽名。
比起 RSA,ECC 在安全強度和性能上都有明顯的優勢。160 位的 ECC 相當于 1024 位的 RSA,而 224 位的 ECC 則相當于 2048 位的 RSA。因為密鑰短,所以相應的計算量、消耗的內存和帶寬也就少,加密解密的性能就上去了,對于現在的移動互聯網非常有吸引力。
對稱加密的優點是運算速度快,缺點是互聯網環境下無法將密鑰安全的傳送給對方。非對稱加密的優點是可以安全的將公鑰傳遞給對方,但是運算速度慢。
看到這里,你是不是認為可以拋棄對稱加密,只用非對稱加密來實現機密性呢?
這里 TLS 把對稱加密和非對稱加密結合起來,兩者互相取長補短,即能高效地加密解密,又能安全地密鑰交換。其實說穿了也很簡單:
在通信剛開始的時候使用非對稱算法,比如 RSA、ECDHE,首先解決密鑰交換的問題。
然后用隨機數產生對稱算法使用的“會話密鑰”(session key),再用公鑰加密。因為會話密鑰很短,通常只有 16 字節或 32 字節,所以慢一點也無所謂。
對方拿到密文后用私鑰解密,取出會話密鑰。這樣,雙方就實現了對稱密鑰的安全交換,后續就不再使用非對稱加密,全都使用對稱加密。
這樣混合加密就解決了對稱加密算法的密鑰交換問題,而且安全和性能兼顧,完美地實現了機密性。
不過這只是“萬里長征的第一步”,后面還有完整性、身份認證、不可否認等特性沒有實現,所以現在的通信還不是絕對安全。
數字簽名與證書
黑客雖然拿不到會話密鑰,無法破解密文,但可以通過竊聽收集到足夠多的密文,再嘗試著修改、重組后發給網站。因為沒有完整性保證,服務器只能“照單全收”,然后他就可以通過服務器的響應獲取進一步的線索,最終就會破解出明文。
另外,黑客也可以偽造身份發布公鑰。如果你拿到了假的公鑰,混合加密就完全失效了。你以為自己是在和“某寶”通信,實際上網線的另一端卻是黑客,銀行卡號、密碼等敏感信息就在“安全”的通信過程中被竊取了。
所以,在機密性的基礎上還必須加上完整性、身份認證等特性,才能實現真正的安全。
摘要算法
實現完整性的手段主要是摘要算法(Digest Algorithm),也就是常說的散列函數、哈希函數(Hash Function)。
你可以把摘要算法近似地理解成一種特殊的壓縮算法,它能夠把任意長度的數據“壓縮”成固定長度、而且獨一無二的“摘要”字符串,就好像是給這段數據生成了一個數字“指紋”。
換一個角度,也可以把摘要算法理解成特殊的“單向”加密算法,它只有算法,沒有密鑰,加密后的數據無法解密,不能從摘要逆推出原文。
摘要算法實際上是把數據從一個“大空間”映射到了“小空間”,所以就存在“沖突”(collision,也叫碰撞)的可能性,就如同現實中的指紋一樣,可能會有兩份不同的原文對應相同的摘要。好的摘要算法必須能夠“抵抗沖突”,讓這種可能性盡量地小。
因為摘要算法對輸入具有“單向性”和“雪崩效應”,輸入的微小不同會導致輸出的劇烈變化,所以也被 TLS 用來生成偽隨機數(PRF,pseudo random function)。
你一定在日常工作中聽過、或者用過 MD5(Message-Digest 5)、SHA-1(Secure Hash Algorithm 1),它們就是最常用的兩個摘要算法,能夠生成 16 字節和 20 字節長度的數字摘要。但這兩個算法的安全強度比較低,不夠安全,在 TLS 里已經被禁止使用了。
目前 TLS 推薦使用的是 SHA-1 的后繼者:SHA-2。
SHA-2 實際上是一系列摘要算法的統稱,總共有 6 種,常用的有 SHA224、SHA256、SHA384,分別能夠生成 28 字節、32 字節、48 字節的摘要。
完整性
摘要算法保證了“數字摘要”和原文是完全等價的。所以,我們只要在原文后附上它的摘要,就能夠保證數據的完整性。
比如,你發了條消息:“轉賬 1000 元”,然后再加上一個 SHA-2 的摘要。網站收到后也計算一下消息的摘要,把這兩份“指紋”做個對比,如果一致,就說明消息是完整可信的,沒有被修改。
如果黑客在中間哪怕改動了一個標點符號,摘要也會完全不同,網站計算比對就會發現消息被竄改,是不可信的。
不過摘要算法不具有機密性,如果明文傳輸,那么黑客可以修改消息后把摘要也一起改了,網站還是鑒別不出完整性。
所以,真正的完整性必須要建立在機密性之上,在混合加密系統里用會話密鑰加密消息和摘要,這樣黑客無法得知明文,也就沒有辦法動手腳了。
這有個術語,叫哈希消息認證碼(Hmac)。
數字簽名
加密算法結合摘要算法,我們的通信過程可以說是比較安全了。但這里還有漏洞,就是通信的兩個端點(endpoint)。
就像一開始所說的,黑客可以偽裝成網站來竊取信息。而反過來,他也可以偽裝成你,向網站發送支付、轉賬等消息,網站沒有辦法確認你的身份,錢可能就這么被偷走了。
現實生活中,解決身份認證的手段是簽名和印章,只要在紙上寫下簽名或者蓋個章,就能夠證明這份文件確實是由本人而不是其他人發出的。
在這里,使用非對稱加密里的“私鑰”再加上摘要算法,就能夠實現“數字簽名”,同時實現“身份認證”和“不可否認”。
數字簽名的原理其實很簡單,就是把公鑰私鑰的用法反過來,之前是公鑰加密、私鑰解密,現在是私鑰加密、公鑰解密。
但又因為非對稱加密效率太低,所以私鑰只加密原文的摘要,這樣運算量就小的多,而且得到的數字簽名也很小,方便保管和傳輸。
簽名和公鑰一樣完全公開,任何人都可以獲取。但這個簽名只有用私鑰對應的公鑰才能解開,拿到摘要后,再比對原文驗證完整性,就可以像簽署文件一樣證明消息確實是你發的。
剛才的這兩個行為也有專用術語,叫做“簽名”和“驗簽”。
只要你和網站互相交換公鑰,就可以用“簽名”和“驗簽”來確認消息的真實性,因為私鑰保密,黑客不能偽造簽名,就能夠保證通信雙方的身份。
比如,你用自己的私鑰簽名一個消息“我是小明”。網站收到后用你的公鑰驗簽,確認身份沒問題,于是也用它的私鑰簽名消息“我是某寶”。你收到后再用它的公鑰驗一下,也沒問題,這樣你和網站就都知道對方不是假冒的,后面就可以用混合加密進行安全通信了。
數字證書和 CA
到現在,綜合使用對稱加密、非對稱加密和摘要算法,是不是已經完美了呢?
不是的,這里還有一個“公鑰的信任”問題。因為誰都可以發布公鑰,我們還缺少防止黑客偽造公鑰的手段,也就是說,怎么來判斷這個公鑰就是你或者某寶的公鑰呢?
真是“按下葫蘆又起了瓢”,安全還真是個麻煩事啊,“一環套一環”的。
我們可以用類似密鑰交換的方法來解決公鑰認證問題,用別的私鑰來給公鑰簽名,顯然,這又會陷入“無窮遞歸”。但這次實在是“沒招”了,要終結這個“死循環”,就必須引入“外力”,找一個公認的可信第三方,讓它作為“信任的起點,遞歸的終點”,構建起公鑰的信任鏈。
這個“第三方”就是我們常說的 CA(Certificate Authority,證書認證機構)。它就像網絡世界里的公安局、教育部、公證中心,具有極高的可信度,由它來給各個公鑰簽名,用自身的信譽來保證公鑰無法偽造,是可信的。CA 對公鑰的簽名認證也是有格式的,不是簡單地把公鑰綁定在持有者身份上就完事了,還要包含序列號、用途、頒發者、有效時間等等,把這些打成一個包再簽名,完整地證明公鑰關聯的各種信息,形成“數字證書”(Certificate)。
知名的 CA 全世界就那么幾家,比如 DigiCert、VeriSign、Entrust、Let’s Encrypt 等,它們簽發的證書分 DV、OV、EV 三種,區別在于可信程度。
DV 是最低的,只是域名級別的可信,背后是誰不知道。EV 是最高的,經過了法律和審計的嚴格核查,可以證明網站擁有者的身份(在瀏覽器地址欄會顯示出公司的名字,例如 Apple、GitHub 的網站)。
不過,CA 怎么證明自己呢?
這還是信任鏈的問題。小一點的 CA 可以讓大 CA 簽名認證,但鏈條的最后,也就是Root CA,就只能自己證明自己了,這個就叫“自簽名證書”(Self-Signed Certificate)或者“根證書”(Root Certificate)。你必須相信,否則整個證書信任鏈就走不下去了。
有了這個證書體系,操作系統和瀏覽器都內置了各大 CA 的根證書,上網的時候只要服務器發過來它的證書,就可以驗證證書里的簽名,順著證書鏈(Certificate Chain)一層層地驗證,直到找到根證書,就能夠確定證書是可信的,從而里面的公鑰也是可信的。
證書體系的弱點
證書體系(PKI,Public Key Infrastructure)雖然是目前整個網絡世界的安全基礎設施,但絕對的安全是不存在的,它也有弱點,還是關鍵的“信任”二字。
如果 CA 失誤或者被欺騙,簽發了錯誤的證書,雖然證書是真的,可它代表的網站卻是假的。
還有一種更危險的情況,CA 被黑客攻陷,或者 CA 有惡意,因為它(即根證書)是信任的源頭,整個信任鏈里的所有證書也就都不可信了。
這兩種事情并不是“聳人聽聞”,都曾經實際出現過。所以,需要再給證書體系打上一些補丁。
針對第一種,開發出了 CRL(證書吊銷列表,Certificate revocation list)和 OCSP(在線證書狀態協議,Online Certificate Status Protocol),及時廢止有問題的證書。
對于第二種,因為涉及的證書太多,就只能操作系統或者瀏覽器從根上“下狠手”了,撤銷對 CA 的信任,列入“黑名單”,這樣它頒發的所有證書就都會被認為是不安全的。
HTTPS 建立連接
當你在瀏覽器地址欄里鍵入“https”開頭的 URI,再按下回車,會發生什么呢?
瀏覽器首先要從 URI 里提取出協議名和域名。因為協議名是“https”,所以瀏覽器就知道了端口號是默認的 443,它再用 DNS 解析域名,得到目標的 IP 地址,然后就可以使用三次握手與網站建立 TCP 連接了。
在 HTTP 協議里,建立連接后,瀏覽器會立即發送請求報文。但現在是 HTTPS 協議,它需要再用另外一個“握手”過程,在 TCP 上建立安全連接,之后才是收發 HTTP 報文。
這個“握手”過程與 TCP 有些類似,是 HTTPS 和 TLS 協議里最重要、最核心的部分,懂了它,你就可以自豪地說自己“掌握了 HTTPS”。
TLS 協議的組成
在講 TLS 握手之前,我先簡單介紹一下 TLS 協議的組成。
TLS 包含幾個子協議,你也可以理解為它是由幾個不同職責的模塊組成,比較常用的有記錄協議、警報協議、握手協議、變更密碼規范協議等。
- 記錄協議(Record Protocol)規定了 TLS 收發數據的基本單位:記錄(record)。它有點像是 TCP 里的 segment,所有的其他子協議都需要通過記錄協議發出。但多個記錄數據可以在一個 TCP 包里一次性發出,也并不需要像 TCP 那樣返回 ACK。
- 警報協議(Alert Protocol)的職責是向對方發出警報信息,有點像是 HTTP 協議里的狀態碼。比如,protocol_version 就是不支持舊版本,bad_certificate 就是證書有問題,收到警報后另一方可以選擇繼續,也可以立即終止連接。
- 握手協議(Handshake Protocol)是 TLS 里最復雜的子協議,要比 TCP 的 SYN/ACK 復雜的多,瀏覽器和服務器會在握手過程中協商 TLS 版本號、隨機數、密碼套件等信息,然后交換證書和密鑰參數,最終雙方協商得到會話密鑰,用于后續的混合加密系統。
- 最后一個是變更密碼規范協議(Change Cipher Spec Protocol),它非常簡單,就是一個“通知”,告訴對方,后續的數據都將使用加密保護。那么反過來,在它之前,數據都是明文的。
下面的這張圖簡要地描述了 TLS 的握手過程,其中每一個“框”都是一個記錄,多個記錄組合成一個 TCP 包發送。所以,最多經過兩次消息往返(4 個消息)就可以完成握手,然后就可以在安全的通信環境里發送 HTTP 報文,實現 HTTPS 協議。
ECDHE 握手過程
剛才你看到的是握手過程的簡要圖,又畫了一個詳細圖,下面我就用這個圖來仔細剖析 TLS 的握手過程。
在 TCP 建立連接之后,瀏覽器會首先發一個“Client Hello”消息,也就是跟服務器“打招呼”。里面有客戶端的版本號、支持的密碼套件,還有一個隨機數(Client Random),用于后續生成會話密鑰。
Handshake Protocol: Client Hello
Version: TLS 1.2 (0x0303)
Random: 1cbf803321fd2623408dfe…
Cipher Suites (17 suites)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
這個的意思就是:“我這邊有這些這些信息,你看看哪些是能用的,關鍵的隨機數可得留著。”復制代碼
作為“禮尚往來”,服務器收到“Client Hello”后,會返回一個“Server Hello”消息。把版本號對一下,也給出一個隨機數(Server Random),然后從客戶端的列表里選一個作為本次通信使用的密碼套件,在這里它選擇了“TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384”。
Handshake Protocol: Server Hello
Version: TLS 1.2 (0x0303)
Random: 0e6320f21bae50842e96…
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
這個的意思就是:“版本號對上了,可以加密,你的密碼套件挺多,我選一個最合適的吧,用橢圓曲線加 RSA、AES、SHA384。我也給你一個隨機數,你也得留著。”復制代碼
然后,服務器為了證明自己的身份,就把證書也發給了客戶端(Server Certificate)。
接下來是一個關鍵的操作,因為服務器選擇了 ECDHE 算法,所以它會在證書后發送“Server Key Exchange”消息,里面是橢圓曲線的公鑰(Server Params),用來實現密鑰交換算法,再加上自己的私鑰簽名認證。
Handshake Protocol: Server Key Exchange
EC Diffie-Hellman Server Params
Curve Type: named_curve (0x03)
Named Curve: x25519 (0x001d)
Pubkey: 3b39deaf00217894e...
Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
Signature: 37141adac38ea4...
這相當于說:“剛才我選的密碼套件有點復雜,所以再給你個算法的參數,和剛才的隨機數一樣有用,別丟了。為了防止別人冒充,我又蓋了個章。”復制代碼
之后是“Server Hello Done”消息,服務器說:“我的信息就是這些,打招呼完畢。”
這樣第一個消息往返就結束了(兩個 TCP 包),結果是客戶端和服務器通過明文共享了三個信息:Client Random、Server Random 和 Server Params。
客戶端這時也拿到了服務器的證書,那這個證書是不是真實有效的呢?
這就要用到第 25 講里的知識了,開始走證書鏈逐級驗證,確認證書的真實性,再用證書公鑰驗證簽名,就確認了服務器的身份:“剛才跟我打招呼的不是騙子,可以接著往下走。”
然后,客戶端按照密碼套件的要求,也生成一個橢圓曲線的公鑰(Client Params),用“Client Key Exchange”消息發給服務器。
Handshake Protocol: Client Key Exchange
EC Diffie-Hellman Client Params
Pubkey: 8c674d0e08dc27b5eaa…
現在客戶端和服務器手里都拿到了密鑰交換算法的兩個參數(Client Params、Server Params),就用 ECDHE 算法一陣算,算出了一個新的東西,叫“Pre-Master”,其實也是一個隨機數。
至于具體的計算原理和過程,因為太復雜就不細說了,但算法可以保證即使黑客截獲了之前的參數,也是絕對算不出這個隨機數的。
現在客戶端和服務器手里有了三個隨機數:Client Random、Server Random 和 Pre-Master。用這三個作為原始材料,就可以生成用于加密會 話的主密鑰,叫“Master Secret”。而黑客因為拿不到“Pre-Master”,所以也就得不到主密鑰。
為什么非得這么麻煩,非要三個隨機數呢?
這就必須說 TLS 的設計者考慮得非常周到了,他們不信任客戶端或服務器偽隨機數的可靠性,為了保證真正的“完全隨機”“不可預測”,把三個不可靠的隨機數混合起來,那么“隨機”的程度就非常高了,足夠讓黑客難以猜測。
你一定很想知道“Master Secret”究竟是怎么算出來的吧,貼一下 RFC 里的公式:
master_secret = PRF(pre_master_secret, "master secret",ClientHello.random + ServerHello.random)
這里的“PRF”就是偽隨機數函數,它基于密碼套件里的最后一個參數,比如這次的 SHA384,通過摘要算法來再一次強化“Master Secret”的隨機性。復制代碼
主密鑰有 48 字節,但它也不是最終用于通信的會話密鑰,還會再用 PRF 擴展出更多的密鑰,比如客戶端發送用的會話密鑰(client_write_key)、服務器發送用的會話密鑰(server_write_key)等等,避免只用一個密鑰帶來的安全隱患。
有了主密鑰和派生的會話密鑰,握手就快結束了。客戶端發一個“Change Cipher Spec”,然后再發一個“Finished”消息,把之前所有發送的數據做個摘要,再加密一下,讓服務器做個驗證。
意思就是告訴服務器:“后面都改用對稱算法加密通信了啊,用的就是打招呼時說的 AES,加密對不對還得你測一下。”
服務器也是同樣的操作,發“Change Cipher Spec”和“Finished”消息,雙方都驗證加密解密 OK,握手正式結束,后面就收發被加密的 HTTP 請求和響應了。
RSA 握手過程
整個握手過程可真是夠復雜的,但你可能會問了,好像這個過程和其他地方看到的不一樣呢?
剛才說的其實是如今主流的 TLS 握手過程,這與傳統的握手有兩點不同。
第一個,使用 ECDHE 實現密鑰交換,而不是 RSA,所以會在服務器端發出“Server Key Exchange”消息。
第二個,因為使用了 ECDHE,客戶端可以不用等到服務器發回“Finished”確認握手完畢,立即就發出 HTTP 報文,省去了一個消息往返的時間浪費。這個叫“TLS False Start”,意思就是“搶跑”,和“TCP Fast Open”有點像,都是不等連接完全建立就提前發應用數據,提高傳輸的效率。
這里我也畫了個圖。
大體的流程沒有變,只是“Pre-Master”不再需要用算法生成,而是客戶端直接生成隨機數,然后用服務器的公鑰加密,通過“Client Key Exchange”消息發給服務器。服務器再用私鑰解密,這樣雙方也實現了共享三個隨機數,就可以生成主密鑰。
雙向認證
到這里 TLS 握手就基本講完了。
不過上面說的是“單向認證”握手過程,只認證了服務器的身份,而沒有認證客戶端的身份。這是因為通常單向認證通過后已經建立了安全通信,用賬號、密碼等簡單的手段就能夠確認用戶的真實身份。
但為了防止賬號、密碼被盜,有的時候(比如網上銀行)還會使用 U 盾給用戶頒發客戶端證書,實現“雙向認證”,這樣會更加安全。
雙向認證的流程也沒有太多變化,只是在“Server Hello Done”之后,“Client Key Exchange”之前,客戶端要發送“Client Certificate”消息,服務器收到后也把證書鏈走一遍,驗證客戶端的身份。
作者:huansky
來源:https://www.cnblogs.com/huansky/p/13977181.html