Q1: 什麼是 HTTPS?
BS: HTTPS 是安全的 HTTP
HTTP 協議中的內容都是明文傳輸,HTTPS 的目的是將這些內容加密,確保信息傳輸安全。最後一個字母 S 指的是 SSL/TLS 協議,它位於 HTTP 協議與 TCP/IP 協議中間。html
Q2: 你說的信息傳輸安全是什麼意思
BS: 信息傳輸的安全有三個方面:linux
一、客戶端和服務器直接的通訊只
二、有本身能看懂,即便第三方拿到數據也看不懂這些信息的真實含義。
三、第三方雖然看不懂數據,但能夠 XJB 改,所以客戶端和服務器必須有能力判斷數據是否被修改過。
四、客戶端必須避免中間人攻擊,即除了真正的服務器,任何第三方都沒法冒充服務器。
很遺憾的是,目前的 HTTP 協議還不知足上述三條要求中的任何一條。算法
Q3: 這麼多要求,一個一個去知足是否是很累?
BS: 不累,第三個要求能夠不用管瀏覽器
是的,我沒開玩笑,你能夠暫時別管第三個要求,由於它實際上隸屬於第一個需求。咱們都知道加密須要密碼,密碼不是天下掉下來,也得須要雙方通過通訊才能協商出來。因此一個設計良好的加密機制必然會防止第三者的干擾和僞造。等搞明白了加密的具體原理,咱們天然能夠檢驗是否知足:「任何第三者沒法冒充服務器」這一要求。安全
Q4: 那怎麼加密信息呢
BS: 使用對稱加密技術服務器
對稱加密能夠理解爲對原始數據的可逆變換。好比 Hello 能夠變換成 Ifmmp,規則就是每一個字母變成它在字母表上的後一個字母,這裏的祕鑰就是 1,另外一方拿到 Ifmmp 就能夠還原成原來的信息 Hello 了。
引入對稱加密後,HTTPS 的握手流程就會多了兩步,用來傳遞對稱加密的祕鑰:
一、客戶端: 你好,我須要發起一個 HTTPS 請求
一、服務器: 好的,你的祕鑰是 1。
提到了對稱加密,那麼天然還有非對稱加密。它的思想很簡單,計算兩個質數的乘積很容易,但反過來分解成兩個質數的乘積就很難,要通過極爲複雜的運算。非對稱加密有兩個祕鑰,一個是公鑰,一個是私鑰。公鑰加密的內容只有私鑰能夠解密,私鑰加密的內容只有公鑰能夠解密。通常咱們把服務器本身留着,不對外公佈的密鑰稱爲私鑰,全部人均可以獲取的稱爲公鑰。
使用對稱加密通常要比非對稱加密快得多,對服務器的運算壓力也小得多。函數
Q5: 對稱祕鑰如何傳輸
服務器直接返回明文的對稱加密密鑰是否是不安全。若是有監聽者拿到這個密鑰,不就知道客戶端和服務器後續的通訊內容了麼?
BS: 利用非對稱加密
是這樣,因此不能明文傳遞對稱祕鑰,並且也不能用一個新的對稱加密算法來加密原來的對稱祕鑰,不然新的對稱祕鑰一樣沒法傳輸,這就是雞生蛋、蛋生雞的悖論。
這裏咱們引入非對稱加密的方式,非對稱加密的特性決定了服務器用私鑰加密的內容並非真正的加密,由於公鑰全部人都有,因此服務器的密文能被全部人解析。但私鑰只掌握在服務器手上,這就帶來了兩個巨大的優點:
一、服務器下發的內容不可能被僞造,由於別人都沒有私鑰,因此沒法加密。強行加密的後果是客戶端用公鑰沒法解開。
二、任何人用公鑰加密的內容都是絕對安全的,由於私鑰只有服務器有,也就是隻有真正的服務器能夠看到被加密的原文。
因此傳輸對稱祕鑰的問題就迎刃而解了: 祕鑰不是由服務器下發,而是由客戶端生成而且主動告訴服務器。
因此當引入非對稱加密後,HTTPS 的握手流程依然是兩步,不過細節略有變化:
客戶端: 你好,我須要發起一個 HTTPS 請求,這是個人 (用公鑰加密後的) 祕鑰。
服務器: 好的,我知道你的祕鑰了,後續就用它傳輸。性能
Q5: 那公鑰怎麼傳輸
你好像仍是沒有解決雞生蛋,蛋生雞的問題。你說客戶端發送請求時要用公鑰加密對稱祕鑰,那公鑰怎麼傳輸呢?
BS: 對公鑰加密就好了。。。
每個使用 HTTPS 的服務器都必須去專門的證書機構註冊一個證書,證書中存儲了用權威機構私鑰加密的公鑰。這樣客戶端用權威機構的公鑰解密就能夠了。
如今 HTTPS 協議的握手階段變成了四步:
一、客戶端: 你好,我要發起一個 HTTPS 請求,請給我公鑰
二、服務器: 好的,這是個人證書,裏面有加密後的公鑰
三、客戶端: 解密成功之後告訴服務器: 這是個人 (用公鑰加密後的) 對稱祕鑰。
四、服務器: 好的,我知道你的祕鑰了,後續就用它傳輸。加密
Q6: 你在逗我麼。。。。
那權威機構的公鑰又怎麼傳輸?
BS: 存在電腦裏
這個公鑰不用傳輸,會直接內置在各大操做系統(或者瀏覽器)的出廠設置裏。之因此不把每一個服務器的公鑰內置在電腦裏,一方面是由於服務器太多,存不過來。另外一方面操做系統也不信任你,憑什麼你說你這個就是百度/淘寶的證書呢?
因此各個公司要先去權威機構認證,申請證書,而後操做系統只會存儲權威機構的公鑰。由於權威機構數量有限,因此操做系統廠商相對來講容易管理。若是這個權威機構不夠權威,XJB 發證書,就會取消他的資格,好比可憐的沃通。。。。操作系統
Q7: 怎麼知道證書有沒有被篡改?
你說服務器第一次會返回證書,也就是加密之後的公鑰,那我怎麼知道這個證書是可靠的?
BS: 將信息 hash 值隨着信息一塊兒傳遞
咱們都知道哈希算法的特色,它能夠壓縮數據,若是從函數角度來看,無論多複雜的數據(定義域能夠很是大)通過哈希算法都會獲得一個值,並且這個值處在某個特定(遠小於定義域的範圍)值域內。相同數據的哈希結果必定相同,不相同數據的哈希結果通常不一樣,不過也有小几率會重複,這叫哈希衝突。
爲了確保原始證書沒有被篡改,咱們能夠在傳遞證書的同時傳遞證書的哈希值。因爲第三者沒法解析數據,只能 XJB 改,那麼修改後的數據在解密後,就不可能經過哈希。
好比說公鑰就是以前的例子 Hello,咱們假設哈希算法是獲取字符串的最後一個字符,那麼 Hello 的哈希值就是 o,因此加密字符串是 Ifmmpp。雖然公鑰已知,每一個人均可以解密,解密完也能夠篡改,可是由於沒有私鑰, 因此沒法正確的加密。因此它再返回給客戶端的數據是無效數據,用公鑰解析後會獲得亂碼。即便攻擊者經過屢次嘗試碰巧可以解析,也沒法經過哈希校驗。
Q8: 這樣能夠防止第三方冒充服務器麼
BS: 也許能夠
首先真正的服務器下發的內容,沒法被別人篡改。他們有權威機構的公鑰,因此能夠解密,可是由於沒有私鑰,因此解密之後的信息沒法加密。沒有加密或者錯誤加密的信息被客戶端用公鑰解密之後,必然沒法經過哈希校驗。
可是,若是你一開始請求的就不是真的服務器,而是一個攻擊者,此時的他徹底有機會進行中間人攻擊。咱們知道第一次握手的時候服務器會下發用於證實本身身份的證書,這個證書會用預設在設備上的公鑰來解密。因此要麼是通過認證的證書用權威機構的私鑰加密,再用權威機構解密,要麼是用非權威機構的私鑰加密,而後找不到公鑰解密。
因此若是不當心安裝過非權威機構的根證書,好比黑客提供的惡意證書,這時候設備上就多了一個預設的公鑰,那麼用惡意私鑰加密的證書就能被正常解析出來。因此千萬不要隨便裝根證書,這等因而爲那些惡意證書留了一扇門。
固然,凡是都有兩面性。咱們知道 Charles 能夠調試 HTTPS 通訊,它的原理就是須要用戶安裝 Charles 的根證書,而後咱們的請求會被代理到 Charles 服務器,它下發的 Charles 證書才能被正確解析。另外一方面,Charles 會做爲客戶端,從真正的服務器哪裏拿到正確的 https 證書並用於後續通訊。幸虧 Charles 不是流氓軟件,或者它的私鑰一旦泄露,對用戶都會形成很大的影響。
我能夠舉一個例子,證書有多個種類,最貴的叫 EV (Extended Validation),它須要公司營業執照等多個文件才能申請人工審覈,好處也很明顯,能夠在瀏覽器地址欄左側準確顯示公司名稱,好比 Bitbucket 的官網:
代理模式下沒法顯示
Q9: HTTPS 握手會影響性能麼
TCP 有三次握手,再加上 HTTPS 的四次握手,會不會影響性能?
BS: 影響確定有,可是能夠接受
首先,HTTPS 確定會更慢一點,時間主要花費在兩組 SSL 之間的耗時和證書的讀取驗證上,對稱算法的加解密時間幾乎能夠忽略不計。
並且若是不是首次握手,後續的請求並不須要完整的握手過程。客戶端能夠把上次的加密狀況直接發送給服務器從而快速恢復,具體細節能夠參考 圖解SSL/TLS協議。
除此之外,SSL 握手的時間並非只能用來傳遞加密信息,還能夠承擔起客戶端和服務器溝通 HTTP2 兼容狀況的任務。所以從 HTTPS 切換到 HTTP2.0 不會有任何性能上的開銷,反卻是得益於 HTTP2.0 的多路複用等技術,後續能夠節約大量時間。
若是把 HTTPS2.0 當作目標,那麼 HTTPS 的性能損耗就更小了,遠遠比不上它帶來的安全性提高。
結語
相信以上九個問題足夠幫助新人瞭解 HTTPS 了,但這只是基本概念,關於 HTTPS 的使用(好比 iOS 上的一些具體問題)還須要不斷嘗試和研究。