https詳解
目前大部分大型網站已經全部切換到了https
服務,所以很有必要了解整個https
的原理,https
是如何保證信息安全的。這里希望大家對以下部分名詞有一定的了解:
- 數字證書
是互聯網通信中的身份標識(主要是用戶身份信息和公鑰),一般由CA中心頒發,既CA認證中心,或第三方權威機構。數字證書上通常包括:CA的簽名,證書所有人的公鑰,CA中心的簽名算法,指紋以及指紋算法,證書的唯一編號,版本,有效期等。 - 數字簽名、簽名算法
對信息的摘要【通過hash算法
/摘要算法
/指紋算法
計算的信息摘要
/hash值
】使用簽名算法進行加密,得到的密文就叫做數字簽名 - 指紋、指紋算法/摘要算法【hash值計算】
對消息使用hash算法/摘要算法
進行單向處理,獲取一個固定長度的信息的摘要/hash值
。 - 非對稱加密
可以使用公鑰、私鑰分解進行對應的加密、解密的算法,即加解密使用的是不同的一堆秘鑰。 - 對稱加密
使用相同秘鑰進行加解密的算法 - 公鑰、私鑰
非對稱加解密的一對秘鑰。
https服務部署過程和原理
了解https
的原理,最好的方法就是走一遍流程,理論上的流程和原理通過以下幾點來解釋:
- 證書申請
- 證書信任
- 密文通信
證書的獲取
https
的關鍵之一就是ssl
證書,為了保證證書的安全有效性,在各類委員會/廠商之間合作,通過類似圓桌會議來形成若干權威的認證機構【頂級認證機構可以有若干附屬的二級、三級...認證機構】,想要得到受信任的證書,就需要向CA機構提交證書簽名請求 (CSR, Certificate Signing Request)。過程如下:
- 證書申請者【一般是公司、個人開發者等】需要使用加密算法【大部分是RSA算法】來生成私鑰,其中私鑰保存在服務器上,不提供給任何人。
- 使用私鑰生成證書簽名請求 (CSR, Certificate Signing Request)【CSR中附帶有公鑰】,需要提供一些申請者相關的信息【域名、擁有者等信息】,發送給CA機構請求他們的簽名,經過他們簽名才能成為被信任的證書。
- CA機構對申請者進行驗證【這里不同類型收費不同,驗證方式也會不同】,驗證通過后,將會在證書中添加部分信息【證書頒發機構、有效期、指紋/hash算法、簽名算法】,形成新的證書。【CA機構也是使用其自身的私鑰來簽名其他證書的】
-
對新的證書進行簽名,步驟如下:
- 對新證書按照
指紋/hash算法
進行hash值計算 - 使用CA機構的私鑰對計算出來的hash值按照簽名算法進行加密,得出的密文就是數字簽名;
- 將數字簽名放在證書的最后面【簽名完成】,得到完整的證書,並返回給申請者;
- 申請者獲取簽名證書,保證自己的
HTTPS
服務被信任。
- 對新證書按照
所以最后的證書基本包括但不限於的內容如下:
- 證書的有效期
- 公鑰
- 證書所有者(Subject)
- 簽名所使用的算法
- 指紋以及指紋算法【hash算法】
- Version Number,版本號。
- Serial Number,序列號。
- 頒發機構
- 數字簽名
客戶端識別證書
在申請到受信任的證書后,客戶端是怎么知道這些證書是值得信任的呢,不同瀏覽器和系統的具體實現不太一樣,但是基本的方式差不多,都是在系統或者瀏覽器中事先准備好權威的CA機構的相關信息[公鑰、常使用的各類hash、簽名、加密算法等]。具體過程如下:
- 瀏覽器訪問某
https
服務,帶上瀏覽器自身支持的一系列Cipher Suite(密鑰算法套件,后文簡稱Cipher)[C1,C2,C3, …]發給服務器【算法套件包括非對稱算法、對稱算法、hash算法
】; - 服務器接收到瀏覽器的所有Cipher后,與自己支持的套件作對比,如果找到雙方都支持的Cipher【雙方套件中都能支持的最優先算法】,則告知瀏覽器,並返回自己的證書;
- 瀏覽器確認和服務端后續的密文通信的加密算法,同時對證書進行認證;
- 使用證書中的認證機構【可能是二級、三級機構】的公鑰【系統、瀏覽器事先准備好的】按照證書中的簽名算法進行解密【認證機構使用私鑰加密的密文只能通過該認證機構的公鑰進行解密】,解密獲取hash值;
- 使用證書中的
hash/摘要算法
對證書信息【證書簽名除外的信息[服務器公鑰、有效期等]】hash值計算,和4中解密的hash值進行對比,如果相等,表示證書值得信任;【通過數字簽名來保證證書內容沒有被篡改】。
https的加密通信過程
在上文的流程之后【證書信任,客戶端和服務端握手中需要的非對稱算法
、握手信息驗證的hash算法
、正文傳輸的對稱加密
】,就是具體的通信過程:
- 客戶端信任了服務端的證書,並和服務端確認了雙方的加密算法【握手中需要的
非對稱算法
、握手信息驗證的hash算法
、正文傳輸的對稱加密
】; - 客戶端生成
隨機數
,通過證書中的公鑰按照約定的非對稱加密算法進行加密,得到加密的隨機數秘鑰,同時將之前所有的通信信息【秘鑰算法套件、證書等所有的通信內容】按照約定的hash/摘要算法
獲取hash值,並使用隨機數和協商好的對稱加密算法進行簽名加密,將隨機數秘鑰和加密簽名
發送到服務端。 - 服務端收到
隨機數秘鑰和加密簽名
,先使用私鑰將隨機數
按照約定的非對稱解密算法進行解密,獲取隨機數,同時使用隨機數按照約定的對稱解密算法進行解密,獲取待驗證的hash值
,將之前的通信消息體【秘鑰算法套件、證書等所有的通信內容】按照約定的hash/摘要算法
獲取hash值,與剛才解密獲取的待驗證的hash值
對比,驗證加密成功與否。 - 成功以后,服務器再次將之前所有的通信信息【秘鑰算法套件、證書等所有的通信內容】按照約定的
hash/摘要算法
獲取hash值,並使用隨機數和協商好的對稱加密算法進行簽名加密,將隨機數秘鑰
發送到客戶端, - 客戶端使用隨機數按照約定的對稱解密算法進行解密,獲取
待驗證的hash值
,將之前的通信消息體【秘鑰算法套件、證書等所有的通信內容】按照約定的hash/摘要算法
獲取hash值,與剛才解密獲取的待驗證的hash值
對比,驗證加密成功與否, - 成功的話整個鏈接過程完成,之后將使用隨機數和約定的對稱加密算法進行密文通信,【如果上面的任何步驟出現問題,都將會結束整個握手過程,導致建立安全連接失敗】。
整個過程其實還有很多細節;ssl握手報文
綜合解惑
這里的整個過程分的很細,不過還是很清晰的把整個https
的原理和過程闡述了;下面解釋一下其中一些疑惑點:
- CA機構認證的作用?
可以作為全球有限的權威認證,經過其簽名的證書都可以視為可信任的,所以他們的私鑰必須要保證不被泄露,如果泄露的話需要及時的進行吊銷, - 簽名為什么需要加密計算的hash值,hash值已經是單向不可逆的運算了?
因為雖然hash值是單向的,但是計算hash的算法和內容都是公開的,如果不進行加密,那么由於其他人可以修改證書內容,根據hash算法重新計算hash,這樣就會出現安全漏洞,所以使用加密的密文才是安全的。 - 為什么要有隨機數,為什么在客戶端生成?
隨機數是作為后續整個密文加解密的關鍵秘鑰,只有獲取這個隨機數的人才可以看到通信的內容,保證通信的安全;通過客戶端產生是因為會話的發起者是用戶端,為了保證用戶端的唯一,以及保證服務端和客服端的會話內容不被篡改,如果是服務端來生成的話,第三方可以通過公鑰來解密服務端加密的隨機數,存在不安全因素。 - 證書驗證完成后,為什么客戶端需要和服務端互相發送一次簽名信息?
證書驗證完成以后,需要傳遞一個隨機數,使用公鑰、私鑰進行非對稱加解密,后面在發生內容消息的前面是為了驗證通過隨機數進行對稱加解密,保證雙方獲取的數據正確性。
openssl生成證書
在大部分開發調試過程中,我們需要本地調試https
的頁面時候,我們需要在本地擁有證書,而openssl
就是就是這樣一個集成工具;通過使用openssl
來完成本地調試https
的請求。
openssl
簡介- 自簽名證書
- 本地私有CA證書
openssl
的簡介
OpenSSL 是一個開源項目,其組成主要包括一下三個組件:
- openssl:多用途的命令行工具
- libcrypto:加密算法庫
- libssl:加密模塊應用庫,實現了ssl及tls
openssl可以實現:秘鑰證書管理、對稱加密和非對稱加密更多簡介和官網和openssl簡介。
自簽名證書
為了能夠把線上的https
的請求,走向本地,需要我們本地也有https
服務,那么證書就是不可避免的,然而一般情況我們並不是使用線上的證書,因為走本地需要本地啟用服務,如果證書使用線上的,那么本地起服務的話就需要線上的私鑰等隱私信息,這很容易導致私鑰泄露,所以不安全,那么我們就需要生成一個本地的證書;
前文講過了,一個證書是需要經過CA機構
進行認證簽名的,那么我們本地測試使用的證書然道也要去申請認證嗎?但是否定的,因為這個這是只是我們本地使用,所以只需要我們有證書,並且手動添加信任就行,那么自簽名證書就很好的解決了這個問題。
自簽名證書
:跟多詳細介紹,自簽名證書的核心就是自己對自己的申請進行簽名【CA根證書就是這樣產生的】;使用自己的私鑰對自身生成的證書申請CSR進行簽名得出的證書。
通過自簽名證書
我們獲得了https
服務需要的證書,根據本地不同的環境,都需要對該證書進行一個信任,這樣我們本地起的https
服務才會被瀏覽器正確的識別。整個過程如下:
-
生成秘鑰
openssl genrsa -des3 -out cwj.key 2048
使用以上命令,來生成一個我們本地需要的私鑰,后面需要使用私鑰來生成證書申請CSR以及對證書申請CSR使用私鑰進行自簽名
-
生成證書申請CSR
openssl req -new -key cwj.key -out cwj.csr
需要填寫一系列信息,包括地點、單位、域名、email之類的,這里會自動使生產與服務端私鑰匹配的公鑰,CSR中包含了公鑰;
-
使用私鑰完成自簽名,生成完整的證書
openssl x509 -req -sha256 -days 3650 -in cwj.csr -signkey cwj.key -out cwj.crt
使用前生產的秘鑰對證書申請CSR進行信任簽名,得到完整的證書;
這樣的確滿足了部分需求,只需要使用該證書和私鑰來啟動https
服務,同時本地信任這個證書就大功告成了,其中優點如下:
- 本地自簽名,無須CA根證書;
- 過程簡單
不過也存在一些弊端:
- 該證書無法被吊銷,私鑰需要保存好,不過對於僅用於本地調試來說就無傷大雅;
- 多域名需要多個證書,需要根據域名生成多個證書,客服端需要分別信任這些證書。【不過
openssl
也可以生成多域名證書,一個證書可以供多個域名使用,一般使用openssl.cnf
配置文件來生成】
所以還存在其他的方法:為了模擬完整的真是的https
服務,我們可以在本地生成一個類似CA根證書,通過CA的私鑰來對其他的所有的本地證書進行簽名,只有信任了本地的CA根證書,那么他簽名的證書都會被信任,這樣就是下面文提到的進化方法本地私有CA根證書
。
本地私有CA根證書偽CA根證書
這個方法的整體流程就是本地生成一個CA證書,就類似CA機構的存在,【暫且稱為偽CA根證書
】通過偽CA根證書
的私鑰來對其他的所有的本地證書進行簽名,我們本地信任了這個偽CA根證書
,那么通過偽CA根證書
簽名的證書都會被信任。避免了多個域名需要生成多個自簽名證書
以及要進行分別信任的復雜行為。
-
偽CA根證書
生成並添加信任openssl genrsa -des3 -out ca.key 2048 openssl req -new -key ca.key -out ca.csr openssl x509 -req -sha256 -days 3650 -in ca.csr -signkey ca.key -out ca.crt
可以看到,其實ca根證書就是一個自簽名證書的例子;
-
本地單一域名證書秘鑰、申請CSR
openssl genrsa -des3 -out cwj.key 2048 openssl req -new -key cwj.key -out cwj.csr
生成一個證書請求;
-
偽CA根證書
的私鑰簽名其他的申請CSRopenssl x509 -req -sha256 -days 3650 -in cwj.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out cwj.crt
更多內容openssl;這樣證書的問題就解決了,視情況來看使用者是采用哪種方案來生成證書。
信任證書需要一些操作,不同系統有不同的過程,MAC是在鑰匙串中信任,windows是需要導入證書;
nginx部署https實踐
本地啟動https
服務的方式很多,這里就說一說nginx
;nginx官網https模塊,主要用到的就是私鑰和證書;根據之前提到的使用不同方法生成的證書以及服務器私鑰【本地CA根證書也需要本地進行信任】。
server { listen 443 ssl; server_name cwj.cc; ssl_certificate /cwjhttps/cwj.crt; ssl_certificate_key /cwjhttps/cwj.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { root /cwjhttps; index home.html index.htm test.html; } }
其實這樣的做法在chrome
高版本還是會被認為是不安全網站;后面的openssl
的介紹會具體的進行說明,或者參見自簽名證書過程詳解和解決chrome不信任自簽名證書、摘要/hash算法不被認為安全