安全基礎
我們先來看下資料在網際網路上資料傳遞可能會出現的三個比較有代表性的問題,其實後面提到的所有方法,都是圍繞解決這三個問題而提出來的。
竊聽

偽造

否認

對稱金鑰加密
假設 A
正在通過網際網路向 B
傳送資料,如果不對資料進行加密,資料就可能被惡意的第三者 X
看到
因此,需要保密的資料需要進行加密再傳送

- 用將資料進行加密,使其成為密文
- 把密文傳送給
B
B
使用金鑰解密從A
收到的密文,這樣就能得到原始資料- 因為是加密資料,即使它被惡意的第三方截獲也是安全的
“對稱金鑰加密” 一個很重要的特點就是使用相同的金鑰進行加密和解密

回到剛剛那個場景,假設 B
是沒有解金鑰匙的,所以 A
需要通過網際網路將鑰匙傳送給 B
- 但是
X
也有可能看到這個鑰匙 - 因此,
X
也可以通過這個鑰匙來解密密文
上面這個場景就會引出一個新問題,這個問題被稱為 “鑰匙交付問題”,那怎麼解決這個問題?
公開金鑰加密
為了解決上面的 “鑰匙交付問題”,我們這裡引入一個新的方法 —— "公開金鑰加密",下圖是 “公開金鑰加密” 的主要特點

- 用於加密的金鑰被稱為“公鑰”,用於解密的金鑰被稱為“私鑰”
- 跟 “對稱金鑰加密” 相比,公開金鑰加密往往需要更多的時間用於加密和解密
我們來看看 “公開金鑰加密” 的一整個過程

接收方 B
建立一個公鑰和一個私鑰,公鑰被髮送給 A

A
使用從B
收到的公鑰加密資料,將密文傳送給B
B
使用私鑰解密從A
接收到的密文,得到原始資料
在這個過程中
- 密文和公鑰也可能被惡意第三方 X 截獲
- 但是私鑰是
B
儲存的,X
無法獲取到,自然沒有辦法解密密文 - 這樣就很好的解決了 “鑰匙交付問題”
公開金鑰加密的問題
- 加密和解密都需要耗費時間,有一種叫 “混合加密” 的方法可以解決這個問題
- 公開金鑰的可靠性
混合加密

混合金鑰加密分為兩個步驟
- 通過公開金鑰加密傳遞金鑰
- 通過速度更快的對稱金鑰加密方法傳遞資料
中間人攻擊
為了更好地理解公開金鑰加密的可靠性問題,我們回到傳遞公鑰的場景

A
拿到的其實是 X
傳送給他的偽造公鑰,但是 A
無法察覺

最後,X
用他自己的金鑰加密響應資料,併傳送給 A
,就這樣,雖然 A
、B
雙方能順利完成通訊,但是惡意的第三方 X
能看到解密後的請求資料和響應資料,而 A
、B
雙方則毫不知情。
這種通過祕密替換公鑰竊取資料的方法被稱為“中間人攻擊”,問題的根源在於 A
無法確認他們收到的公鑰是否由 B
方建立。怎麼避免中間人攻擊呢?我們放到數字證書那節再探討,接下來再講解一點前置知識
訊息鑑別碼
訊息鑑別碼在英文中被稱為 MAC
,MAC
可以理解為金鑰和密文組成的字串的雜湊值

訊息鑑別碼雖然可以解決偽造
問題,但是仍然無法避免 否認
問題
數字簽名
為了解決這個 否認
問題,我們接下來看看 “數字簽名” 方法

數字證書
雖然上面的方法已經能避免 竊聽
、偽造
、否認
等問題,但是現在還是沒辦法避免“中間人攻擊”,因為我們還是沒辦法驗證公鑰的所有者,因此我們需要 “數字證書” 系統來驗證公鑰的所有者。
接下來,先看看數字證書申請的過程,我們將數字證書認證機構(Certificate Authority)我們稱之為 CA

現在 B 已經申請到一個數字證書了,那麼怎麼使用數字證書來檢驗公鑰 PB 是屬於 B 呢

現在可以驗證 PB 是屬於 B 的,但是怎麼驗證 PC 是屬於受信任的 CA 的呢

事實上,認證機構形成一個樹形結構,高階別的權威機構為較低階別的機構建立證書,那就是說,如果要驗證的話,就是一級一級向上認證,信任鏈條的最終是Root CA,他採用自簽名,對他的簽名是無條件的信任。

HTTPS
完全理解上面說的東西之後,就能夠很容易理解 HTTPS
,它採用的就是上面說的 “混合加密” + “數字證書” 兩種技術,來保證整個通訊過程的安全可靠。
HTTPS
做的事情其實就是在傳輸層跟應用層之間加了一層 SSL/TLS
,用於對 TCP
傳輸內容的加密和解密

下圖我們再看一下詳細的工作流程

用 Node 實現一箇中間人代理伺服器
到此,我們都知道了 HTTPS、數字證書等相關的知識,可以動手實現一箇中間人代理服務了,這裡附上一個連結,有興趣的話可以看下怎麼 用 Node 實現一箇中間人代理伺服器