HTTPS 的原理和 NodeJS 的實現

基本原理

HTTP協議採用明文傳輸數據,當涉及敏感信息的傳送時,極有可能會受到竊聽或者中間人的攻擊。HTTPS是HTTP與SSL/TLS的組合,即便用加密通信以及網絡服務器的身份鑑定來進行信息的安全傳輸。其核心有二:算法

  • 使用證書對服務器及請求端的身份驗證
  • 使用一組對稱祕鑰加密包括請求頭在內的全部信息傳輸

握手流程

HTTPS連接的創建過程當中涉及到服務器端證書、客戶端證書(可選)、服務器端的非對稱祕鑰以及後續通訊過程當中使用的對稱祕鑰幾個內容。安全

  1. 客戶端對HTTPS的地址發出請求,而且將本身的SSL版本號等信息發送給服務器
  2. 服務器接收到請求,將服務器證書和公鑰等信息返回給客戶端
  3. 客戶端接收到證書後向證書頒發機構驗證證書的合法性。若是證書不合法(好比自行簽發的證書),則向用戶發出警告並確認是否繼續,用戶能夠選擇在此時離開終止HTTPS的連接。
  4. 證書合法或客戶端確認在不安全的狀況下繼續,客戶端生成pre-master secret而且使用2中收到的服務器公鑰加密後發送給服務器。若是是使用交互策略的TLS,則同時須要將客戶端的證書發送給服務器。服務器檢查客戶端的證書頒發機構是否在信任列表中,以及證書內容是否合法。若不合法,結束本次會話。
  5. 服務器使用私鑰解密pre-master secret,而後雙方經過一種實現商定好的加密算法生成本次通信使用的master secret
  6. 雙方互相通知對方本次SSL握手成功,其後均使用master secret對傳輸內容進行加密。

下圖簡要的說明了這個流程的實現。
圖片描述服務器

一開始我也心存疑問:爲何要單獨使用另一組對稱祕鑰來實現對信息的加密而不直接使用服務器和客戶端雙方的非對稱祕鑰呢?我自身很是認同下面這個回答的解釋:網絡

傳輸過程使用對稱密鑰是由於對稱加密比非對稱加密的運算量低一個數量級以上,因此這樣的方式能夠提升雙方會話的運算速度。ui

對於加密算法不是很是瞭解,但願大牛指點一二。加密

Openssl自簽名證書的生成

HTTPS中一個關鍵就是證書文件。固然咱們能夠找專業的第三方機構簽發。本身玩玩的話就用自簽名的證書就能夠了,用戶在訪問的時候則須要確認安全性問題。
一、生成傳輸pre-master secret的時候所須要的Server端的私鑰,運行時提示須要輸入密碼,用於對key的加密。之後每次讀取此文件的時候,都須要輸入指令。spa

# 生成服務器端的非對稱祕鑰
openssl genrsa -des3 -out server.key 1024

# 生成簽名請求的CSR文件
openssl req -new -key server.key -out server.csr

# 本身對證書進行簽名,簽名的有效期是365天
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

# 去除證書文件的password
cp server.key server.key.orig
openssl rsa -in server.key.orig -out server.key

最終在創建HTTPS連接中使用的文件是code

  • server.crt
  • server.key

NodeJS創建一個HTTPS的Server

var httpsModule = require('https');
var fs = require('fs');

var https = httpsModule.Server({
     key: fs.readFileSync('/path/to/server.key'),
     cert: fs.readFileSync('/path/to/server.crt')
}, function(req, res){
    res.writeHead(200);
    res.end("hello world\n");
});

//https默認de監聽端口時443,啓動1000如下的端口時須要sudo權限
https.listen(443, function(err){  
     console.log("https listening on port: 443");
});

這裏使用的fs.readFileSync方法會阻塞其餘進程直到文件的讀取完畢,在讀取關鍵的配置文件的時候這樣的方法是比較適宜的。server

相關文章
相關標籤/搜索