大家好,我是藍胖子,之前出過一篇https的原理分析 ,完整的介紹了https概念以及通信過程,今天我們就來比較完整的模擬實現https通信的過程,通過這篇文章,你能了解到https核心的概念以及原理,https證書是如何申請的,以及如何用golang實現https通信,https雙向認證。
本章代碼已經上傳到github
(資料圖片僅供參考)
https://github.com/HobbyBear/codelearning/tree/master/httpsdemo
https原理回顧在開始之前,讓我們來了解下https相關的核心知識,可以作為上篇https原理分析的補充。學習一個東西一定要先知道為什么要用它,我總結了兩點:
1,https 第一個好處是使原本的http明文傳輸變成了密文傳輸,增加了安全性。
2,https第二好處是采用數字證書來解決了身份認證問題,起碼對端通信是經過ca認證的。
那么https又是通過什么技術來實現上述兩點的呢?
數字證書原理我先聊聊數字證書的實現原理,在https的握手階段,服務端會發送自身的證書給客戶端,客戶端會去驗證這個證書的有效性,有效性是這樣保證的:
數字證書上會寫明證書的簽名算法和證書的簽名,如下圖所示
證書經過簽名算法中指定的SHA-256算法將證書內容進行hash得到消息摘要,然后再將這個摘要值經過RSA算法用證書頒發機構的私鑰進行加密就得到了證書的簽名。
而客戶端拿到這個證書就會用證書頒發機構的公鑰去解密簽名,然后按SHA-256算法也對證書內容進行hash,也得到一個消息摘要值,客戶端就去比對自己計算的消息摘要和公鑰解密簽名得到的消息摘要是否一致,一致則說明證書未被篡改并且是證書頒發機構頒發的。
有同學可能會疑惑,證書頒發機構的公鑰是從哪里獲取的,證書頒發機構的公鑰就在頒發機構其自身的證書里,如下圖所示。
https密文加密原理知道了數字證書的驗證原理,我們來看看https通信中涉及到的加密過程,在https的握手階段,服務端會選擇一個與客戶端都支持的密鑰套件用于后續的加密,密鑰套件一般會有如下組件:
密鑰交換算法:用于在客戶端和服務器之間安全地交換加密密鑰。常見的密鑰交換算法有RSA和Diffie-Hellman等。
對稱加密算法:用于對通信數據進行加密和解密。常見的對稱加密算法有AES、DES和3DES等。
摘要算法:用于生成和驗證消息的完整性。常見的摘要算法有MD5和SHA-256等。
https采用非對稱加密的方式交換密鑰,然后使用對稱加密的方式對數據進行加密,并且對消息的內容采用摘要算法得到消息摘要,這樣對端在解密數據后可以通過相同的消息摘要算法對計算后的消息摘要和傳過來的消息摘要進行對比,從而判斷數據是否經過篡改。
具體步驟如下:
客戶端向服務器發送一個初始的握手請求,該請求中包含了客戶端支持的密碼套件列表。服務器收到握手請求后,會從客戶端提供的密碼套件列表中選擇一個與自己支持的密碼套件相匹配的套件。服務器將選定的密碼套件信息返回給客戶端。客戶端收到服務器返回的密碼套件信息后,會選擇一個與服務器相匹配的密碼套件。客戶端生成一個隨機的對稱加密密鑰,并使用服務器的公鑰對該密鑰進行加密。客戶端將加密后的對稱加密密鑰發送給服務器。服務器使用自己的私鑰對接收到的加密的對稱加密密鑰進行解密。客戶端和服務器現在都擁有了相同的對稱加密密鑰,可以使用該密鑰進行加密和解密通信數據。客戶端和服務器使用對稱加密密鑰對通信數據進行加密和解密,并使用摘要算法對數據進行完整性驗證。通過以上步驟,客戶端和服務器可以建立一個安全的HTTPS連接,并使用密碼套件來保護通信的安全性。
模擬證書頒發接下來,我們就要開始實現下https的通信了,由于只是實驗,我們不會真正的去為我的服務器去申請一個數字證書,所以我們暫時在本地用openssl來模擬下證書頒發的邏輯。
模擬根認證ca機構我們知道證書頒發的機構是ca,而ca根證書是默認信任的,一般內置在瀏覽器和操作系統里,所以首先來生成一個根證書,并且讓系統默認信任它。
先生成ca的私鑰
openssl genpkey -algorithm RSA -out ca_private.key
然后生成ca的證書請求
openssl req -new -key ca_private.key -out ca_csr.csr
生成ca證書
openssl x509 -req -in ca_csr.csr -signkey ca_private.key -out ca_cert.crt
我用的是mac系統,所以我這里演示下mac系統如何添加證書信任,
打開鑰匙串應用-> 將證書拖進登錄那一欄 -> 右擊證書點擊顯示簡介-> 將信任那一欄改為始終信任
模擬ca機構向服務器頒發證書生成 服務器自身的私鑰
openssl genpkey -algorithm RSA -out final_private.key
接著就是生成證書請求,和前面生成證書請求不同,因為目前主流瀏覽器都要求證書需要設置subjectAltName
,如果沒有設置SAN會報證書錯誤。
所以我們要換種方式生成證書請求,首先創建一個文件,比如我創建一個san.txt的文件
[req]default_bits = 4096distinguished_name = req_distinguished_namereq_extensions = v3_req[req_distinguished_name]countryName = countrystateOrProvinceName = provincelocalityName = cityorganizationName = company name## 換成自己的域名commonName = lanpangzi.com [v3_req]subjectAltName = @alt_names[alt_names]## 換成自己的域名DNS.1=*.lanpangzi.comDNS.2=*.lanpangzi2.com
到時候上述文件只需要更換為自己的域名即可。由于我的域名設置為了.lanpangzi.com 和.lanpangzi2.com,所以我還要改下本地的hosts文件。
## /etc/hosts127.0.0.1 www.lanpangzi2.com127.0.0.1 www.lanpangzi.com
接著生成服務器證書請求
openssl req -new -key final_private.key -out final_csr.csr -config san.txt -sha256
生成服務器證書
openssl x509 -req -days 365 -in final_csr.csr -CA ca_cert.crt -CAkey ca_private.key -set_serial 01 -out final_csr.crt -extfile san.txt -extensions v3_req
golang實現https服務驗證證書經過了上述步驟后算是生成了一個由ca機構頒發的證書,然后我們用golang代碼實現一個https服務器。需要為https服務器傳入證書以及服務器自身的私鑰。
func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World!\n") }) fmt.Println(http.ListenAndServeTLS(":443", "./final_csr.crt", "./final_private.key", nil)) }
接著實現下客戶端代碼
func main() { client := &http.Client{Transport: tr} resp, err := client.Get("https://www.lanpangzi.com") if err != nil { fmt.Println("Get error:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) }
啟動服務端和客戶端后能看到服務正常返回了。
/private/var/folders/yp/g914gkcd54qdm5d0qyc9ljm00000gn/T/GoLand/___go_build_codelearning_httpsdemo_clientHello, World!
說明證書配置已經成功,而客戶端驗證證書的邏輯已經在本文開始講解了。
golang實現https雙向認證上述代碼只是實現了https的單向認證,即客戶端對服務端的域名進行認證,在某些情況下,服務端也需要檢驗客戶端是否合法,所以下面我們就來看下如何用golang實現雙向認證的。首先我們還是要用ca位客戶端頒發一個證書。
模擬ca機構向客戶端頒發證書生成 服務器自身的私鑰
openssl genpkey -algorithm RSA -out client_private.key
創建一個san_client.txt的文件
[req]default_bits = 4096distinguished_name = req_distinguished_namereq_extensions = v3_req[req_distinguished_name]countryName = countrystateOrProvinceName = provincelocalityName = cityorganizationName = company name## 換成自己的域名commonName = lanpangziclient.com [v3_req]subjectAltName = @alt_names[alt_names]## 換成自己的域名DNS.1=*.lanpangziclient.comDNS.2=*.lanpangziclient2.com
到時候上述文件只需要更換為自己的域名即可。由于我的域名設置為了.lanpangzi.com 和.lanpangzi2.com,所以我還要改下本地的hosts文件。
## /etc/hosts127.0.0.1 www.lanpangziclient2.com127.0.0.1 www.lanpangziclient.com
接著生成服務器證書請求
openssl req -new -key client_private.key -out client_csr.csr -config san_client.txt -sha256
生成服務器證書
openssl x509 -req -days 365 -in client_csr.csr -CA ca_cert.crt -CAkey ca_private.key -set_serial 01 -out client_csr.crt -extfile san_client.txt -extensions v3_req
服務端和客戶端需要做下改動,服務端默認不會去校驗客戶端身份,但是現在改成強制校驗
func main() { s := &http.Server{ Addr: ":443", Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World!\n") }), TLSConfig: &tls.Config{ ClientAuth: tls.RequireAndVerifyClientCert, }, } fmt.Println(s.ListenAndServeTLS("./final_csr.crt", "./final_private.key")) }
客戶端代碼請求時需要帶上自己的證書
func main() { cliCrt, err := tls.LoadX509KeyPair("./client_csr.crt", "./client_private.key") if err != nil { fmt.Println("Loadx509keypair err:", err) return } tr := &http.Transport{ TLSClientConfig: &tls.Config{ Certificates: []tls.Certificate{cliCrt}, }, } client := &http.Client{Transport: tr} resp, err := client.Get("https://www.lanpangzi.com") if err != nil { fmt.Println("Get error:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) }
這樣就完成了一個https的雙向認證。

-
什么是尾盤?股票尾盤拉升是什么意思?股票尾盤拉升的目的什么是尾盤?1、在股市中,尾盤指的就是交易日的最后半個小時,也就是下午14:30-15:00這半個小時時間。2、在股市中,開盤被稱...
-
股票放量上漲是好事嗎?放量上漲和縮量上漲的區別是什么?股票放量上漲是好事嗎?放量上漲是指股票價格上漲,且成交量相比于之前更多,這意味著市場上的參與資金增多,資金增多帶來了上漲,...
-
新三板新股申購中簽規則是什么?上市分為幾個板塊?新三板新股申購中簽規則是什么?1、申購條件門檻100萬 2年經驗 開通新三板創新權限(精選層已改革為北交所,個人投資者準入門...
-
新三板新股申購中簽率高嗎?北交所打新收益如何?新三板新股申購中簽率高嗎?新三板新股中簽的概率大概是0 2%和0 1%,新三板中簽的收益率則是在1%-2%左右,而年化收益率大概...
-
低息配資公司安全嗎?正規的配資公司有哪些?低息配資公司安全嗎?配資本身是不合法的不建議使用,而且低息的或者免費的一般是假的ETF基金吸引用戶常用的手段,資金有進無...
-
什么是尾盤?股票尾盤拉升是什么意思?股票尾盤拉升的目的
2023-06-13 16:30:21
-
股票放量上漲是好事嗎?放量上漲和縮量上漲的區別是什么?
2023-06-13 16:28:21
-
新三板新股申購中簽規則是什么?上市分為幾個板塊?
2023-06-13 16:25:25
-
新三板新股申購中簽率高嗎?北交所打新收益如何?
2023-06-13 16:22:36
-
低息配資公司安全嗎?正規的配資公司有哪些?
2023-06-13 16:18:00