[TOC]
# 什么是Https
HTTPS(全稱:Hypertext Transfer Protocol over Secure Socket Layer),是以安全為目標的HTTP通道,簡單講是HTTP的安全版。即HTTP下加入SSL層,HTTPS的安全基礎是SSL,因此加密的詳細內容就需要SSL
<br>
<br>
# Https的作用
* **內容加密**建立一個信息安全通道,來保證數據傳輸的安全;
* **身份認證**確認網站的真實性
* **數據完整性**防止內容被第三方冒充或者篡改
<br>
<br>
## Https的劣勢
* 對數據進行加解密決定了它比http慢
> 需要進行非對稱的加解密,且需要三次握手。首次連接比較慢點,當然現在也有很多的優化。
<br>
<br>
> 出于安全考慮,瀏覽器不會在本地保存HTTPS緩存。實際上,只要在HTTP頭中使用特定命令,HTTPS是可以緩存的。Firefox默認只在內存中緩存HTTPS。但是,只要頭命令中有Cache-Control: Public,緩存就會被寫到硬盤上。 IE只要http頭允許就可以緩存https內容,緩存策略與是否使用HTTPS協議無關。
<br>
<br>
# HTTPS和HTTP的區別
* https協議需要到CA申請證書。
* http是超文本傳輸協議,信息是明文傳輸;https 則是具有安全性的ssl加密傳輸協議。
* http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。
* http的連接很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全。
# 加解密相關知識
HTTPS 還是通過了 HTTP 來傳輸信息,但是信息通過 TLS 協議進行了加密。
<br>
TLS 協議位于傳輸層之上,應用層之下。首次進行 TLS 協議傳輸需要兩個 RTT ,接下來可以通過 Session Resumption 減少到一個 RTT。
<br>
在 TLS 中使用了兩種加密技術,分別為:對稱加密和非對稱加密。
<br>
## 對稱加密
對稱加密就是兩邊擁有相同的秘鑰,兩邊都知道如何將密文加密解密。
<br>
這種加密方式固然很好,但是問題就在于如何讓雙方知道秘鑰。因為傳輸數據都是走的網絡,如果將秘鑰通過網絡的方式傳遞的話,一旦秘鑰被截獲就沒有加密的意義的。
<br>
## 非對稱加密
有公鑰私鑰之分,公鑰所有人都可以知道,可以將數據用公鑰加密,但是將數據解密必須使用私鑰解密,私鑰只有分發公鑰的一方才知道。
<br>
這種加密方式就可以完美解決對稱加密存在的問題。假設現在兩端需要使用對稱加密,那么在這之前,可以先使用非對稱加密交換秘鑰。
<br>
簡單流程如下:首先服務端將公鑰公布出去,那么客戶端也就知道公鑰了。接下來客戶端創建一個秘鑰,然后通過公鑰加密并發送給服務端,服務端接收到密文以后通過私鑰解密出正確的秘鑰,這時候兩端就都知道秘鑰是什么了。
<br>
<br>
# SSL 與 TLS
## SSL (Secure Socket Layer,安全套接字層)
SSL為Netscape所研發,用以保障在Internet上數據傳輸之安全,利用數據加密(Encryption)技術,可確保數據在網絡上之傳輸過程中不會被截取,當前為3.0版本。
SSL協議可分為兩層: SSL記錄協議(SSL Record Protocol):它建立在可靠的傳輸協議(如TCP)之上,為高層協議提供數據封裝、壓縮、加密等基本功能的支持。 SSL握手協議(SSL Handshake Protocol):它建立在SSL記錄協議之上,用于在實際的數據傳輸開始前,通訊雙方進行身份認證、協商加密算法、交換加密密鑰等。
<br>
## TSL (Transport Layer Security,傳輸層安全協議)
用于兩個應用程序之間提供保密性和數據完整性。
TLS 1.0是IETF(Internet Engineering Task Force,Internet工程任務組)制定的一種新的協議,它建立在SSL 3.0協議規范之上,是SSL 3.0的后續版本,可以理解為SSL 3.1,它是寫入了 RFC 的。該協議由兩層組成: TLS 記錄協議(TLS Record)和 TLS 握手協議(TLS Handshake)。較低的層為 TLS 記錄協議,位于某個可靠的傳輸協議(例如 TCP)上面。
<br>
## SSL/TLS協議作用:
* 認證用戶和服務器,確保數據發送到正確的客戶機和服務器;
* 加密數據以防止數據中途被竊取;
* 維護數據的完整性,確保數據在傳輸過程中不被改變。
<br>
## TLS比SSL的優勢
1. 對于消息認證使用密鑰散列法:TLS 使用“消息認證代碼的密鑰散列法”(HMAC),當記錄在開放的網絡(如因特網)上傳送時,該代碼確保記錄不會被變更。SSLv3.0還提供鍵控消息認證,但HMAC比SSLv3.0使用的(消息認證代碼)MAC 功能更安全。
2. 增強的偽隨機功能(PRF):PRF生成密鑰數據。在TLS中,HMAC定義PRF。PRF使用兩種散列算法保證其安全性。如果任一算法暴露了,只要第二種算法未暴露,則數據仍然是安全的。
3. 改進的已完成消息驗證:TLS和SSLv3.0都對兩個端點提供已完成的消息,該消息認證交換的消息沒有被變更。然而,TLS將此已完成消息基于PRF和HMAC值之上,這也比SSLv3.0更安全。
4. 一致證書處理:與SSLv3.0不同,TLS試圖指定必須在TLS之間實現交換的證書類型。
5. 特定警報消息:TLS提供更多的特定和附加警報,以指示任一會話端點檢測到的問題。TLS還對何時應該發送某些警報進行記錄。
<br>
<br>
# SSL、TLS的握手過程

## 客戶端首次發出請求
由于客戶端(如瀏覽器)對一些加解密算法的支持程度不一樣,但是在TLS協議傳輸過程中必須使用同一套加解密算法才能保證數據能夠正常的加解密。在TLS握手階段,客戶端首先要告知服務端,自己支持哪些加密算法,所以客戶端需要將本地支持的加密套件(Cipher Suite)的列表傳送給服務端。除此之外,客戶端還要產生一個隨機數,這個隨機數一方面需要在客戶端保存,另一方面需要傳送給服務端,客戶端的隨機數需要跟服務端產生的隨機數結合起來產生后面要講到的 Master Secret 。
客戶端需要提供如下信息:
* 支持的協議版本,比如TLS 1.0版
* 一個客戶端生成的隨機數,稍后用于生成”對話密鑰”
* 支持的加密方法,比如RSA公鑰加密
* 支持的壓縮方法
## 服務端首次回應
服務端在接收到客戶端的Client Hello之后,服務端需要確定加密協議的版本,以及加密的算法,然后也生成一個隨機數,以及將自己的證書發送給客戶端一并發送給客戶端,這里的隨機數是整個過程的第二個隨機數。
服務端需要提供的信息:
* 協議的版本
* 加密的算法
* 隨機數
* 服務器證書
## 客戶端再次回應
客戶端首先會對服務器下發的證書進行驗證,驗證通過之后,則會繼續下面的操作,客戶端再次產生一個隨機數(第三個隨機數),然后使用服務器證書中的公鑰進行加密,以及放一個ChangeCipherSpec消息即編碼改變的消息,還有整個前面所有消息的hash值,進行服務器驗證,然后用新秘鑰加密一段數據一并發送到服務器,確保正式通信前無誤。
客戶端使用前面的兩個隨機數以及剛剛新生成的新隨機數,使用與服務器確定的加密算法,生成一個Session Secret。
> ChangeCipherSpec
> ChangeCipherSpec是一個獨立的協議,體現在數據包中就是一個字節的數據,用于告知服務端,客戶端已經切換到之前協商好的加密套件(Cipher Suite)的狀態,準備使用之前協商好的加密套件加密數據并傳輸了。
## 服務器再次響應
服務端在接收到客戶端傳過來的第三個隨機數的 加密數據之后,使用私鑰對這段加密數據進行解密,并對數據進行驗證,也會使用跟客戶端同樣的方式生成秘鑰,一切準備好之后,也會給客戶端發送一個 ChangeCipherSpec,告知客戶端已經切換到協商過的加密套件狀態,準備使用加密套件和 Session Secret加密數據了。之后,服務端也會使用 Session Secret 加密一段 Finish 消息發送給客戶端,以驗證之前通過握手建立起來的加解密通道是否成功。
## 后續客戶端與服務器間通信
確定秘鑰之后,服務器與客戶端之間就會通過商定的秘鑰加密消息了,進行通訊了。整個握手過程也就基本完成了。
> 值得特別提出的是:
> SSL協議在握手階段使用的是非對稱加密,在傳輸階段使用的是對稱加密,也就是說在SSL上傳送的數據是使用對稱密鑰加密的!因為非對稱加密的速度緩慢,耗費資源。其實當客戶端和主機使用非對稱加密方式建立連接后,客戶端和主機已經決定好了在傳輸過程使用的對稱加密算法和關鍵的對稱加密密鑰,由于這個過程本身是安全可靠的,也即對稱加密密鑰是不可能被竊取盜用的,因此,保證了在傳輸過程中對數據進行對稱加密也是安全可靠的,因為除了客戶端和主機之外,不可能有第三方竊取并解密出對稱加密密鑰!如果有人竊聽通信,他可以知道雙方選擇的加密方法,以及三個隨機數中的兩個。整個通話的安全,只取決于第三個隨機數(Premaster secret)能不能被破解。
### 其他補充
對于非常重要的保密數據,服務端還需要對客戶端進行驗證,以保證數據傳送給了安全的合法的客戶端。服務端可以向客戶端發出 Cerficate Request 消息,要求客戶端發送證書對客戶端的合法性進行驗證。比如,金融機構往往只允許認證客戶連入自己的網絡,就會向正式客戶提供USB密鑰,里面就包含了一張客戶端證書。
PreMaster secret前兩個字節是TLS的版本號,這是一個比較重要的用來核對握手數據的版本號,因為在Client Hello階段,客戶端會發送一份加密套件列表和當前支持的SSL/TLS的版本號給服務端,而且是使用明文傳送的,如果握手的數據包被破解之后,攻擊者很有可能串改數據包,選擇一個安全性較低的加密套件和版本給服務端,從而對數據進行破解。所以,服務端需要對密文中解密出來對的PreMaster版本號跟之前Client Hello階段的版本號進行對比,如果版本號變低,則說明被串改,則立即停止發送任何消息。
<br>
<br>
# 中間人攻擊
HTTPS 的過程并不是密不透風的,HTTPS 有若干漏洞,給中間人攻擊(Man In The Middle Attack,簡稱 MITM)提供了可能。
<br>
所謂中間人攻擊,指攻擊者與通訊的兩端分別建立獨立的聯系,并交換其所收到的數據,使通訊的兩端認為他們正在通過一個私密的連接與對方直接對話,但事實上整個會話都被攻擊者完全控制。在中間人攻擊中,攻擊者可以攔截通訊雙方的通話并插入新的內容。
<br>
## SSL 剝離
SSL 剝離即阻止用戶使用 HTTPS 訪問網站。由于并不是所有網站都只支持 HTTPS,大部分網站會同時支持 HTTP 和 HTTPS 兩種協議。用戶在訪問網站時,也可能會在地址欄中輸入`http://`的地址,第一次的訪問完全是明文的,這就給了攻擊者可乘之機。通過攻擊 DNS 響應,攻擊者可以將自己變成中間人。
<br>
> DNS 作為基于 UDP 的協議是相當不安全的,為了保證 DNS 的安全可以使用 DNS over TCP 等機制,這里不贅述了。
<br>
## HSTS
為了防止上面說的這種情況,一種叫做 HSTS 的技術被引入了。HSTS(HTTP Strict Transport Security)是用于強制瀏覽器使用 HTTPS 訪問網站的一種機制。它的基本機制是在服務器返回的響應中,加上一個特殊的頭部,指示瀏覽器對于此網站,強制使用 HTTPS 進行訪問:
<br>
~~~
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
~~~
<br>
可以看到如果這個過期時間非常長,就是導致在很長一段時間內,瀏覽器都會強制使用 HTTPS 訪問該網站。
<br>
HSTS 有一個很明顯的缺點,是需要等待第一個服務器的影響中的頭部才能生效,但如果第一次訪問該網站就被攻擊呢?為了解決這個問題,瀏覽器中會帶上一些網站的域名,被稱為 HSTS preload list。對于在這個 list 的網站來說,直接強制使用 HTTPS。
<br>
## 偽造證書攻擊
HSTS 只解決了 SSL 剝離的問題,然而即使在全程使用 HTTPS 的情況下,我們仍然有可能被監聽。
<br>
假設我們想訪問`www.google.com`,但我們的 DNS 服務器被攻擊了,指向的 IP 地址并非 Google 的服務器,而是攻擊者的 IP。當攻擊者的服務器也有合法的證書的時候,我們的瀏覽器就會認為對方是 Google 服務器,從而信任對方。這樣,攻擊者便可以監聽我們和谷歌之前的所有通信了。
<br>
可以看到攻擊者有兩步需要操作,第一步是需要攻擊 DNS 服務器。第二步是攻擊者自己的證書需要被用戶信任,這一步對于用戶來說是很難控制的,需要證書頒發機構能夠控制自己不濫發證書。
<br>
> 2015 年 Google 稱發現賽門鐵克旗下的 Thawte 未經同意簽發了眾多域名的數千個證書,其中包括 Google 旗下的域名和不存在的域名。當年 12 月,Google 發布公告稱 Chrome、Android 及其他 Google 產品將不再信任賽門鐵克旗下的"Class 3 Public Primary CA"根證書。
>
> 2016 年 Mozilla 發現沃通 CA 存在嚴重的信任問題,例如偷簽`github.com`的證書,故意倒填證書日期繞過瀏覽器對 SHA-1 證書的限制等,將停止信任 WoSign 和 StartCom 簽發的新證書。
<br>
## HPKP
HPKP 技術是為了解決偽造證書攻擊而誕生的。
<br>
HPKP(Public Key Pinning Extension for HTTP)在 HSTS 上更進一步,HPKP 直接在返回頭中存儲服務器的公鑰指紋信息,一旦發現指紋和實際接受到的公鑰有差異,瀏覽器就可以認為正在被攻擊:
<br>
~~~
Public-Key-Pins: pin-sha256="base64=="; max-age=expireTime [; includeSubDomains][; report-uri="reportURI"]
~~~
<br>
和 HSTS 類似,HPKP 也依賴于服務器的頭部返回,不能解決第一次訪問的問題,瀏覽器本身也會內置一些 HPKP 列表。
<br>
> HPKP 技術仍然不能阻止第一次訪問的攻擊問題,部署和配置 HPKP 相當繁瑣,一旦網站配置錯誤,就會導致網站證書驗證失敗,且在過期時間內無法有效恢復。HPKP 的機制也引來了一些安全性問題。Chrome 67 中廢除了對 HPKP 的支持。
<br>
<br>
# 參考資料
[詳解https是如何確保安全的?](http://www.wxtlife.com/2016/03/27/%E8%AF%A6%E8%A7%A3https%E6%98%AF%E5%A6%82%E4%BD%95%E7%A1%AE%E4%BF%9D%E5%AE%89%E5%85%A8%E7%9A%84%EF%BC%9F/)
[HTTP over SSL/TLS · 筆試面試知識整理](https://hit-alibaba.github.io/interview/basic/network/HTTPS.html)
- 第一部分 HTML
- meta
- meta標簽
- HTML5
- 2.1 語義
- 2.2 通信
- 2.3 離線&存儲
- 2.4 多媒體
- 2.5 3D,圖像&效果
- 2.6 性能&集成
- 2.7 設備訪問
- SEO
- Canvas
- 壓縮圖片
- 制作圓角矩形
- 全局屬性
- 第二部分 CSS
- CSS原理
- 層疊上下文(stacking context)
- 外邊距合并
- 塊狀格式化上下文(BFC)
- 盒模型
- important
- 樣式繼承
- 層疊
- 屬性值處理流程
- 分辨率
- 視口
- CSS API
- grid(未完成)
- flex
- 選擇器
- 3D
- Matrix
- AT規則
- line-height 和 vertical-align
- CSS技術
- 居中
- 響應式布局
- 兼容性
- 移動端適配方案
- CSS應用
- CSS Modules(未完成)
- 分層
- 面向對象CSS(未完成)
- 布局
- 三列布局
- 單列等寬,其他多列自適應均勻
- 多列等高
- 圣杯布局
- 雙飛翼布局
- 瀑布流
- 1px問題
- 適配iPhoneX
- 橫屏適配
- 圖片模糊問題
- stylelint
- 第三部分 JavaScript
- JavaScript原理
- 內存空間
- 作用域
- 執行上下文棧
- 變量對象
- 作用域鏈
- this
- 類型轉換
- 閉包(未完成)
- 原型、面向對象
- class和extend
- 繼承
- new
- DOM
- Event Loop
- 垃圾回收機制
- 內存泄漏
- 數值存儲
- 連等賦值
- 基本類型
- 堆棧溢出
- JavaScriptAPI
- document.referrer
- Promise(未完成)
- Object.create
- 遍歷對象屬性
- 寬度、高度
- performance
- 位運算
- tostring( ) 與 valueOf( )方法
- JavaScript技術
- 錯誤
- 異常處理
- 存儲
- Cookie與Session
- ES6(未完成)
- Babel轉碼
- let和const命令
- 變量的解構賦值
- 字符串的擴展
- 正則的擴展
- 數值的擴展
- 數組的擴展
- 函數的擴展
- 對象的擴展
- Symbol
- Set 和 Map 數據結構
- proxy
- Reflect
- module
- AJAX
- ES5
- 嚴格模式
- JSON
- 數組方法
- 對象方法
- 函數方法
- 服務端推送(未完成)
- JavaScript應用
- 復雜判斷
- 3D 全景圖
- 重載
- 上傳(未完成)
- 上傳方式
- 文件格式
- 渲染大量數據
- 圖片裁剪
- 斐波那契數列
- 編碼
- 數組去重
- 淺拷貝、深拷貝
- instanceof
- 模擬 new
- 防抖
- 節流
- 數組扁平化
- sleep函數
- 模擬bind
- 柯里化
- 零碎知識點
- 第四部分 進階
- 計算機原理
- 數據結構(未完成)
- 算法(未完成)
- 排序算法
- 冒泡排序
- 選擇排序
- 插入排序
- 快速排序
- 搜索算法
- 動態規劃
- 二叉樹
- 瀏覽器
- 瀏覽器結構
- 瀏覽器工作原理
- HTML解析
- CSS解析
- 渲染樹構建
- 布局(Layout)
- 渲染
- 瀏覽器輸入 URL 后發生了什么
- 跨域
- 緩存機制
- reflow(回流)和repaint(重繪)
- 渲染層合并
- 編譯(未完成)
- Babel
- 設計模式(未完成)
- 函數式編程(未完成)
- 正則表達式(未完成)
- 性能
- 性能分析
- 性能指標
- 首屏加載
- 優化
- 瀏覽器層面
- HTTP層面
- 代碼層面
- 構建層面
- 移動端首屏優化
- 服務器層面
- bigpipe
- 構建工具
- Gulp
- webpack
- Webpack概念
- Webpack工具
- Webpack優化
- Webpack原理
- 實現loader
- 實現plugin
- tapable
- Webpack打包后代碼
- rollup.js
- parcel
- 模塊化
- ESM
- 安全
- XSS
- CSRF
- 點擊劫持
- 中間人攻擊
- 密碼存儲
- 測試(未完成)
- 單元測試
- E2E測試
- 框架測試
- 樣式回歸測試
- 異步測試
- 自動化測試
- PWA
- PWA官網
- web app manifest
- service worker
- app install banners
- 調試PWA
- PWA教程
- 框架
- MVVM原理
- Vue
- Vue 餓了么整理
- 樣式
- 技巧
- Vue音樂播放器
- Vue源碼
- Virtual Dom
- computed原理
- 數組綁定原理
- 雙向綁定
- nextTick
- keep-alive
- 導航守衛
- 組件通信
- React
- Diff 算法
- Fiber 原理
- batchUpdate
- React 生命周期
- Redux
- 動畫(未完成)
- 異常監控、收集(未完成)
- 數據采集
- Sentry
- 貝塞爾曲線
- 視頻
- 服務端渲染
- 服務端渲染的利與弊
- Vue SSR
- React SSR
- 客戶端
- 離線包
- 第五部分 網絡
- 五層協議
- TCP
- UDP
- HTTP
- 方法
- 首部
- 狀態碼
- 持久連接
- TLS
- content-type
- Redirect
- CSP
- 請求流程
- HTTP/2 及 HTTP/3
- CDN
- DNS
- HTTPDNS
- 第六部分 服務端
- Linux
- Linux命令
- 權限
- XAMPP
- Node.js
- 安裝
- Node模塊化
- 設置環境變量
- Node的event loop
- 進程
- 全局對象
- 異步IO與事件驅動
- 文件系統
- Node錯誤處理
- koa
- koa-compose
- koa-router
- Nginx
- Nginx配置文件
- 代理服務
- 負載均衡
- 獲取用戶IP
- 解決跨域
- 適配PC與移動環境
- 簡單的訪問限制
- 頁面內容修改
- 圖片處理
- 合并請求
- PM2
- MongoDB
- MySQL
- 常用MySql命令
- 自動化(未完成)
- docker
- 創建CLI
- 持續集成
- 持續交付
- 持續部署
- Jenkins
- 部署與發布
- 遠程登錄服務器
- 增強服務器安全等級
- 搭建 Nodejs 生產環境
- 配置 Nginx 實現反向代理
- 管理域名解析
- 配置 PM2 一鍵部署
- 發布上線
- 部署HTTPS
- Node 應用
- 爬蟲(未完成)
- 例子
- 反爬蟲
- 中間件
- body-parser
- connect-redis
- cookie-parser
- cors
- csurf
- express-session
- helmet
- ioredis
- log4js(未完成)
- uuid
- errorhandler
- nodeclub源碼
- app.js
- config.js
- 消息隊列
- RPC
- 性能優化
- 第七部分 總結
- Web服務器
- 目錄結構
- 依賴
- 功能
- 代碼片段
- 整理
- 知識清單、博客
- 項目、組件、庫
- Node代碼
- 面試必考
- 91算法
- 第八部分 工作代碼總結
- 樣式代碼
- 框架代碼
- 組件代碼
- 功能代碼
- 通用代碼