HTTP
Hyper Text Transfer Protocol
使用TCP端口默認(rèn)為:80
超文本傳輸協(xié)議涂炎,是互聯(lián)網(wǎng)上使用最廣泛的一種協(xié)議,所有WWW文件必須遵循的標(biāo)準(zhǔn)愉豺。HTTP協(xié)議傳輸?shù)臄?shù)據(jù)都是未加密的,也就是明文的,因此使用HTTP協(xié)議傳輸隱私信息非常不安全瓣喊。
HTTPS
Hyper Text Transfer Protocol over Secure Socket Layer
使用TCP端口默認(rèn)為:443
安全的超文本傳輸協(xié)議,Netscape(網(wǎng)景公司)設(shè)計(jì)了 SSL(Secure Sockets Layer) 協(xié)議用于對(duì)Http協(xié)議傳輸?shù)臄?shù)據(jù)進(jìn)行加密黔酥,保證會(huì)話過程中的安全性藻三。SSL中文為 安全套接層 。
SSL簡(jiǎn)介
SSL協(xié)議位于TCP/IP協(xié)議與各種應(yīng)用層協(xié)議(如HTTP)之間跪者。SSL協(xié)議可分為兩層:
- SSL Record Protocol (SSL記錄協(xié)議)建立在可靠的傳輸協(xié)議(如TCP)上棵帽,為高層協(xié)議提供數(shù)據(jù)封裝、壓縮渣玲、加密等基本功能的支持逗概;
- SSL Handshake Protocol (SSL握手協(xié)議)建立在記錄協(xié)議上,用于在實(shí)際數(shù)據(jù)傳輸開始前忘衍,通訊雙方進(jìn)行身份驗(yàn)證逾苫、協(xié)商加密算法、交換加密秘鑰等枚钓。
SSL協(xié)議即用到了 對(duì)稱加密 也用到了 非對(duì)稱加密(公鑰加密)铅搓,在建立傳輸鏈路時(shí),SSL首先對(duì) 對(duì)稱加密 的密鑰使用公鑰進(jìn)行 非對(duì)稱加密 搀捷,鏈路建立好之后星掰,SSL對(duì)傳輸內(nèi)容使用 對(duì)稱加密 。
- 對(duì)稱加密 速度高,可加密內(nèi)容大氢烘,用來加密會(huì)話過程中的消息便斥。
- 公鑰加密 加密速度慢,但能提供更好的身份認(rèn)證技術(shù)威始,用來加密 對(duì)稱加密 的秘鑰枢纠。
https單向認(rèn)證
Https在建立Socket連接之前,需要進(jìn)行握手黎棠,具體過程如下:
客戶端 | 單向認(rèn)證 | 服務(wù)端 |
---|---|---|
>>> | 1. 發(fā)送客戶端SSL版本等信息 | >>> |
<<< | 2. 服務(wù)端給客戶端返回SSL版本晋渺、隨機(jī)數(shù)等信息,以及服務(wù)器公鑰 | <<< |
CHECK | 3. 客戶端校驗(yàn)服務(wù)端證書是否合法脓斩,合法繼續(xù)木西,否則警告 | WAIT |
>>> | 4. 客戶端發(fā)送自己可支持的對(duì)稱加密方案給服務(wù)端供選擇 | >>> |
WAIT | 5. 服務(wù)端選擇加密程度高的加密方式 | CHECK |
<<< | 6. 將選擇好的加密方案以明文方式發(fā)送給客戶端 | <<< |
>>> | 7. 客戶端收到加密方式產(chǎn)生隨機(jī)碼,作為對(duì)稱加密秘鑰随静,使用服務(wù)器公鑰加密后發(fā)給服務(wù)器 | >>> |
WAIT | 8. 服務(wù)端使用私鑰對(duì)加密信息進(jìn)行解密八千,獲得對(duì)稱加密秘鑰 | CHECK |
--- | 9. 使用對(duì)稱加密進(jìn)行通信確保安全 | --- |
https雙向認(rèn)證
雙向認(rèn)證和單向認(rèn)證原理基本差不多,只是除了客戶端需要認(rèn)證服務(wù)端以外燎猛,增加了服務(wù)端對(duì)客戶端的認(rèn)證恋捆,具體過程如下:
客戶端 | 單向認(rèn)證 | 服務(wù)端 |
---|---|---|
>>> | 1. 發(fā)送客戶端SSL版本等信息 | >>> |
<<< | 2. 服務(wù)端給客戶端返回SSL版本、隨機(jī)數(shù)等信息重绷,以及服務(wù)器公鑰 | <<< |
CHECK | 3. 客戶端校驗(yàn)服務(wù)端證書是否合法沸停,合法繼續(xù),否則警告 | WAIT |
>>> | 4. 客戶端校驗(yàn)通過后昭卓,將自己的證書和公鑰發(fā)送至客戶端 | >>> |
WAIT | 5. 對(duì)客戶端校驗(yàn)愤钾,校驗(yàn)結(jié)束后獲得客戶端公鑰 | CHECK |
>>> | 6. 客戶端發(fā)送自己可支持的對(duì)稱加密方案給服務(wù)端供選擇 | >>> |
WAIT | 7. 服務(wù)端選擇加密程度高的加密方式 | CHECK |
<<< | 8. 將選擇好的加密方案以客戶端公鑰進(jìn)行加密后方式發(fā)送給客戶端 | <<< |
>>> | 9. 客戶端收到加密方式,使用私鑰進(jìn)行解密,產(chǎn)生隨機(jī)碼候醒,作為對(duì)稱加密秘鑰能颁,使用服務(wù)器公鑰加密后發(fā)給服務(wù)器 | >>> |
WAIT | 10. 服務(wù)端使用私鑰對(duì)加密信息進(jìn)行解密,獲得對(duì)稱加密秘鑰 | CHECK |
--- | 11. 使用對(duì)稱加密進(jìn)行通信確保安全 | --- |
使用openssl進(jìn)行證書生成
由于TLS(SSL)是基于非對(duì)稱的加密體系倒淫,所以在開發(fā)前需要準(zhǔn)備用于加密解密及驗(yàn)證的私鑰及數(shù)字證書伙菊。這里分別為CA、服務(wù)器昌简、客戶端分別準(zhǔn)備1套密鑰及證書占业。
生成CA證書及秘鑰
- 生成一個(gè)秘鑰為ca-key.pem
openssl genrsa -out ca-key.pem -des 1024
- 根據(jù)秘鑰ca-key.pem生成一個(gè)證書簽名請(qǐng)求文件ca-csr.pem,根據(jù)這個(gè)文件可以簽出秘鑰對(duì)應(yīng)的證書纯赎。在這里會(huì)要求填入相關(guān)信息谦疾,可以用“.”表示為空,但Common Name必須要填入對(duì)應(yīng)域名犬金,否則瀏覽器檢查證書與簽名域名不相符會(huì)不允許通過念恍。
openssl req -new -key ca-key.pem -out ca-csr.pem
- 另可以不執(zhí)行第一步六剥,直接執(zhí)行以下語句,也會(huì)自動(dòng)生成一個(gè)private.pem以及ca-csr.pem峰伙。
openssl req -new -out ca-csr.pem
- 利用證書簽名請(qǐng)求文件ca-csr.pem疗疟,并利用ca-key.pem簽名生成證書ca-cert.pem。其中x509為證書格式X.509瞳氓,-days為有效期天數(shù)策彤。
openssl x509 -req -days 3650 -in ca-csr.pem -signkey ca-key.pem -out ca-cert.pem
- 當(dāng)然,也可以拿著ca-csr.pem去權(quán)威的第三方申請(qǐng)一個(gè)證書匣摘,這樣的話申請(qǐng)得到的證書是被接收的〉晔現(xiàn)在我們自簽自申證書,則如上所示使用證書簽名請(qǐng)求文件簽一個(gè)證書音榜。
生成服務(wù)端證書及秘鑰
- 生成一個(gè)服務(wù)器私鑰為server-key.pem
openssl genrsa -out server-key.pem 1024
- 生成證書簽名請(qǐng)求文件server-csr.pem
openssl req -new -key server-key.pem -out server-csr.pem
- 另庞瘸,假如我們需要多DNS和多IP的主機(jī)使用同一個(gè)證書完成驗(yàn)證,則不能通過上面的命令來實(shí)現(xiàn)赠叼。我們需要一個(gè)openssl.cnf配置文件擦囊,并執(zhí)行以下語句
openssl req -new -key server-key.pem -config openssl.cnf -out server-csr.pem
- openssl.cnf配置文件內(nèi)容格式如下所示:
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = CN
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = BeiJing
localityName = Locality Name (eg, city)
localityName_default = YaYunCun
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = Domain Control Validated
commonName = Internet Widgits Ltd
commonName_max = 64
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = ns1.dns.com
DNS.2 = ns2.dns.com
DNS.3 = ns3.dns.com
IP.1 = 192.168.1.84
IP.2 = 127.0.0.1
IP.3 = 127.0.0.2
- 生成服務(wù)器證書為server-sert.pem,具體選項(xiàng)含義查詢openssl
openssl x509 -req -days 730 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -in server-csr.pem -out server-cert.pem -extensions v3_req -extfile openssl.cnf
生成客戶端證書及秘鑰
- 生成客戶端秘鑰client-key.pem
openssl genrsa -out client-key.pem
- 生成證書簽名請(qǐng)求文件client-csr.pem
openssl req -new -key client-key.pem -out client-csr.pem
- 生成服務(wù)器證書為server-sert.pem,具體選項(xiàng)含義查詢openssl
openssl x509 -req -days 365 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -in client-csr.pem -out client-cert.pem
打包和轉(zhuǎn)換
- 另外的,我們可以將服務(wù)器的私鑰嘴办、證書瞬场、CAz證書打包成一個(gè)單獨(dú)的.pfx或.p12文件以便于使用,比如.p12導(dǎo)入瀏覽器可以讓瀏覽器信任該證書
openssl pkcs12 -export -in server-cert.pem -inkey server-key.pem -certfile ca-cert.pem -out server.pfx
openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem -certfile ca-cert.pem -out client.p12
- 證書的轉(zhuǎn)換户辞,由10打包好的文件泌类,可以經(jīng)過轉(zhuǎn)換變?yōu)槠渌袷揭韵绿峁┏R姷母袷睫D(zhuǎn)換方法
openssl pkcs12 -export -inkey test.key -in test.cer -out test.pfx
openssl pkcs12 -in test.pfx -nodes -out test.pem
openssl rsa -in test.pem -out test.key
openssl x509 -in test.pem -out test.crt
單向驗(yàn)證和雙向驗(yàn)證的配置
node.js 實(shí)現(xiàn)HTTPS的配置
- 導(dǎo)入https, fs
var https = require ('https'); // https服務(wù)器
const fs = require("fs"); // 文件輸入輸出癞谒,用來導(dǎo)入證書
- 導(dǎo)入證書,利用fs導(dǎo)出三個(gè)證書并存入變量
var privateKey = fs.readFileSync('./cert/ca.key').toString();
var certificate = fs.readFileSync('./cert/ca.crt').toString();
var client_certificate = fs.readFileSync('./cert/client.crt').toString();
- https設(shè)置,利用鍵值對(duì)來進(jìn)行設(shè)置底燎,rrequestCert表示是否需要客戶端證書,rejectUnauthorized表示如果客戶端證書不符合則是否拒絕訪問弹砚,這兩個(gè)為true則意味著雙向認(rèn)證双仍,否則為單向認(rèn)證
var credentials = { key: privateKey,
cert: certificate,
ca: client_certificate,
requestCert: true,
rejectUnauthorized: true};
- 創(chuàng)建服務(wù)器對(duì)象,比http多了一個(gè)參數(shù)桌吃,即3中所提的credentials
var server = http.createServer(app); // 若http只需要一個(gè)參數(shù)就行
var server = https.createServer(credentials, app); // https需要參數(shù)
- 開啟端口監(jiān)聽
server.listen(port); // port即為端口號(hào)