本文首發於 hzzly的博客面試
原文連接:深究HTTPS算法
前言:尚未用上https的能夠看一下我以前寫的Nginx下升級https,把你的http升級到https。數組
金九銀十或許你也碰到過關於HTTPS的面試問題瀏覽器
接下來就跟着筆者助你攻破HTTPS。安全
HTTP
:超文本傳輸協議(英文:HyperText Transfer Protocol,縮寫:HTTP)是一種用於分佈式、協做式和超媒體信息系統的應用層協議。HTTP是萬維網的數據通訊的基礎。 HTTPS
:超文本傳輸安全協議(英語:Hypertext Transfer Protocol Secure,縮寫:HTTPS,常稱爲HTTP over TLS,HTTP over SSL或HTTP Secure)是一種經過計算機網絡進行安全通訊的傳輸協議。HTTPS經由HTTP進行通訊,但利用SSL/TLS來加密數據包。HTTPS開發的主要目的,是提供對網站服務器的身份認證,保護交換數據的隱私與完整性。bash
從上面概念也能夠看出來HTTP是不安全的,且攻擊者經過監聽和中間人攻擊等手段,能夠獲取網站賬戶和敏感信息等。HTTPS被設計爲可防止前述攻擊,並在正確配置時被認爲是安全的。服務器
HTTP的URL由"http://"起始且默認使用端口80,而HTTPS的URL由"https://"起始且默認使用端口443。網絡
HTTP協議運行在TCP之上,全部傳輸的內容都是明文,客戶端和服務器端都沒法驗證對方的身份。HTTPS是運行在SSL/TLS之上的HTTP協議,SSL/TLS運行在TCP之上。全部傳輸的內容都通過加密,加密採用對稱加密,但對稱加密的密鑰用服務器方的證書進行了非對稱加密。curl
HTTPS在進行數據傳輸以前會與服務器和瀏覽器進行一次握手,在握手時肯定雙方的加密密碼信息。分佈式
具體過程以下:
瀏覽器將支持的加密信息發送給網站服務器;
服務器會選擇出一套加密算法和哈希算法,將驗證身份的信息以證書(證書發佈CA機構、證書有效期、公鑰、證書全部者、簽名等)的形式發送給瀏覽器;
當瀏覽器收到證書以後首先須要驗證證書的合法性,若是證書受到瀏覽器信任則在瀏覽器地址欄會有標誌顯示,不然就會顯示不受信的標識。當證書受信以後,瀏覽器會隨機生成一串密碼,並使用證書中的公鑰加密。以後就是使用約定好的哈希算法握手消息,並生成隨機數對消息進行加密,再將生成的信息發送給服務器;
當服務器接收到瀏覽器發送過來的數據後,會使用服務器自己的私鑰將信息解密肯定密碼,而後經過密碼解密瀏覽器發送過來的握手信息,並驗證哈希是否與瀏覽器一致。而後服務器會使用密碼加密新的握手信息,發送給瀏覽器;
最後瀏覽器解密並計算通過哈希算法加密的握手消息,若是與服務發送過來的哈希一致,則此握手過程結束後,服務器與瀏覽器會使用以前瀏覽器生成的隨機密碼和對稱加密算法進行加密交換數據。
HTTPS在加密過程當中使用了非對稱加密技術和對稱加密技術。
採用單鑰密碼系統的加密方式,同一個密鑰能夠同時作信息的加密和解密,這種加密的方法稱爲對稱加密。
SSL在通訊過程當中,使用了對稱加密算法,也就是說客戶端和服務器同時共享一個密鑰。
因而,以共享密鑰的方式加密,必須將密鑰發給對方。這個時候,假如通訊過程被監聽,密鑰被攻擊者獲取了,那麼這個時候也就失去了加密的意義了。
因而就須要使用兩把密鑰的非對稱加密算法。
與對稱加密算法相反,非對稱加密算法須要兩個密鑰來進行加密和解密,這兩個密鑰是配對的,分別是公開密鑰(公鑰)和私有密鑰(私鑰)。
因而如今,假設如今由服務器來生成一對公鑰和密鑰。
當客戶端第一次發請求和服務器協商的時候,服務器就生成了一對公鑰和私鑰。
緊接着,服務器把公鑰發給客戶端(明文,不須要作任何加密),客戶端接收後,使用服務器發過來的公鑰進行數據加密。
再接着,服務器接收到了之後,用配對的私鑰進行解密,就獲得了客戶端發送的數據。
非對稱加密算法的特色:算法強度複雜、安全性依賴於算法與密鑰可是因爲其算法複雜,而使得加解密速度性能上比較差,沒有對稱加密算法加解密的速度快。
可是咱們還存在一個問題,若是公鑰被中間人拿到篡改呢?
這時咱們就須要使用證書保證公鑰的正確性
首先,服務器的運營人員向數字證書機構(CA)提出公開密鑰的申請。數字證書認證機構在驗證申請者的身份以後,會對申請的公開密鑰作數字簽名,而後分配這個已簽名的公開密鑰,並將該公開密鑰放入公鑰證書後綁定在一塊兒。
簡單點理解就是: CA會向申請者頒發一個證書文件和證書的私鑰文件,這個證書文件裏面的內容有:簽發者、證書用途、服務器申請的時候附帶的公鑰、服務器的加密算法、使用的HASH算法、證書到期的時間等等,私鑰文件就是與證書中公鑰對應的私鑰。
緊接着,把上面所提到的證書文件裏的內容,作一次HASH求值,獲得一個HASH值。
再接着,用CA的私鑰進行加密,這樣就完成了數字簽名。而用CA的私鑰加密後,就生成了相似人體指紋的簽名,任何篡改證書的嘗試,都會被數字簽名發現。
最後,把數字簽名,附在數字證書的末尾,傳輸回來給服務器。
接下來,服務器會把這份由數字證書認證機構頒發的公鑰證書發給客戶端。 客戶端拿到這個數字證書之後,會去校驗證書籤名的合法性,先對證書進行SHA256(瀏覽器的加密算法)獲得一個哈希值,而後用證書的公鑰對證書的簽名進行解密從中取得另外一個哈希值,若是這兩個哈希值相等,說明證書沒有被篡改過,確實是權威機構頒發。
若是認證經過,就能夠取得服務器的公開密鑰。
接下來就可使用對稱加密算法通訊了。
HTTPS中不只可使用服務器證書,還可使用客戶端證書。以客戶端證書進行客戶端認證,它的做用與服務器證書是相同的。
例如,銀行的網上銀行就採用了客戶端證書(網銀盾)。在登陸網銀時不只要求用戶確認輸入ID和密碼,還會要求用戶的客戶端證書(網銀盾),以確認用戶是否從特定的終端訪問網銀。
這一步中,客戶端經過發送client_hello
報文開始SSL通訊。在請求中,瀏覽器會帶上一些創建鏈接的必要信息(注意:這一步的信息全都是明文的),包括:
版本
: 客戶端支持的最高的 TLS 協議版本。從高到低依次爲:TLS v1.2, TLS v1.1, TLS v1.0, SSL v3, SSL v2。其中低於 TLS v1.0 的版本基本再也不使用,由於 SSL v3 和 SSL v2 都存在漏洞,Google 和 Mozilla 已明確禁用 SSL 協議。密碼套件
: 按優先級降序排列的、客戶端支持的加密套件列表。每一個加密套件會各包含一個認證算法(用於身份驗證)、密鑰交換算法(用於協商密鑰)、對稱加密算法(用於消息加密)和信息摘要算法(用於完整性校驗)。壓縮方法
: 客戶端支持的用於壓縮消息、下降傳輸體積的壓縮算法列表。隨機數
: 一個由客戶端生成的隨機數,使用 32 位時間戳和一個安全隨機數生成器生成的 28 字節隨機數組成。這個隨機數用於後續Master Key
的生成,並防止重放攻擊。會話標識
: 一個變長的會話標誌。非 0 值意味着客戶端但願更新當前已存在的鏈接的參數或者爲此鏈接建立一個新的鏈接。0 值表示客戶端想在新會話上建立一個新鏈接。擴展字段
: 包含一些其餘的相關參數(好比 SNI)。客戶端在發出client_hello
消息以後,會等待服務器返回server_hello
消息,包含和 client_hello
相同的參數。通常來講,參數結構以下:
版本
: 包含客戶端支持的最低版本和服務器支持的最高版本。密碼套件
: 包含了服務器從客戶端發來的密碼套件列表中選擇出的將要使用的密碼套件。壓縮方法
: 包含了服務器從客戶端發來的壓縮方法列表中選擇出的將要使用的壓縮方法。隨機數
: 由服務器生成的不一樣於客戶端在client_hello
中發來的隨機數的另外一個獨立的隨機數。會話標識
: 若是客戶端發送的會話標識不爲 0,服務器會使用與客戶端發送的一致的會話標識,不然返回的是服務器生成的一個新的會話標識。一般來講,服務器會在certificate
消息中發送其自身的公開密鑰證書供客戶端進行驗證。
最後,服務器發送server_hello_done
消息,代表服務器的 hello 相關的消息結束。在發送此消息以後,服務器會等待客戶端應答,該消息沒有參數。
在這一步結束以後代表最初階段的SSL握手協商部分結束。
客戶端在收到服務器發來的server_hello_done
消息以後,會驗證服務器提供的證書是否合法,並檢查server_hello
的各項參數。若是驗證經過,則客戶端會向服務器發送一條或多條消息。
而後客戶端會發送client_key_exchange
報文消息,報文中包含通訊加密中使用的一種被稱爲PreMaster Key
的隨機密碼串,並使用服務器證書中的公鑰或者服務器密鑰交換消息中的臨時 RSA 密鑰加密。這個密鑰會被用於以後的Master Key
的計算。
通過以上步驟,客戶端和服務器已經能夠經過獲得的消息計算出Master Key
了。從如今開始,客戶端和服務器都將開始使用協商好的加密算法、密鑰進行通訊,在正式傳遞消息以前會計算Master Key
和以前握手過程當中收到的全部信息的hash
,並經過協商好的加密算法使用 Master Key
加密,做爲change_cipher_spec
消息的內容,接着發送finished
消息。服務器在收到客戶端發來的change_cipher_spec
和finished
消息以後,也會計算Master Key
並使用協商好的加密算法和以前握手過程當中收到的全部信息的hash
,發回給客戶端用以驗證。至此,握手階段結束,以後就能夠交換應用層的內容了。
服務器和客戶端的finished
報文交換完畢以後,SSL鏈接就算創建完成,固然,通訊會受到SSL的保護。今後處開始進行應用層協議的通訊,即發送HTTP請求。
至此,整個過程介紹完畢。
咱們可使用 curl 命令來簡略查看創建 HTTPS 時的握手過程,在命令行中執行:curl -v -I -L hzzly.cn
能獲得以下的輸出:
簡單說明一下鏈接的創建過程:
# 表示創建了和 hzzly.cn 服務器 443 端口的鏈接。
Connected to hzzly.cn (39.108.182.125) port 443 (#0)
# 客戶端發出 client_hello 消息。
TLSv1.2 (OUT), TLS handshake, Client hello (1):
# 服務器發出 server_hello 消息。
TLSv1.2 (IN), TLS handshake, Server hello (2):
# 服務器發出 certificate 消息。
TLSv1.2 (IN), TLS handshake, Certificate (11):
# 服務器發出 server_key_exchange 消息。
TLSv1.2 (IN), TLS handshake, Server key exchange (12):
# 服務器發出 server_done 消息。
TLSv1.2 (IN), TLS handshake, Server finished (14):
# 客戶端發出 client_key_exchange 消息。
TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
# 客戶端發出加密後的 client_hello 消息。
TLSv1.2 (OUT), TLS change cipher, Client hello (1):
# 客戶端發出 hello_done 消息。
TLSv1.2 (OUT), TLS handshake, Finished (20):
# 服務器將加密後的 client_hello 消息發回。
TLSv1.2 (IN), TLS change cipher, Client hello (1):
# 握手結束。
TLSv1.2 (IN), TLS handshake, Finished (20):
# SSL 鏈接採用 ECDHE-RSA-AES256-GCM-SHA384 密碼套件。
# ECDHE 表示密鑰交換方法採用橢圓曲線迪菲-赫爾曼交換方法
# RSA 表示密鑰交換中使用的簽名方式
# AES-256-GCM 表示的是對稱加密算法
# SHA-384 表示的是內容完整性校驗使用的哈希算法
SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
# 以後的幾行包含了證書的內容,包括有效時間、經常使用名、證書籤發機構等。
Server certificate:
# Common Name 爲 hzzly.cn
subject: CN=hzzly.cn
# 在此時間以前無效
start date: Aug 2 00:00:00 2019 GMT
# 在此時間以後無效
expire date: Aug 1 12:00:00 2020 GMT
# 域名和證書的域名匹配
subjectAltName: host "hzzly.cn" matched certs "hzzly.cn"
# 簽發者是 Encryption
issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=Encryption Everywhere DV TLS CA - G1
複製代碼