在這里整理一下最近這兩天整理的https的相關知識。
大家都知道要使用https,需要在網站的服務器上配置https證書(一般是nginx,或者tomcat),證書可以使用自己生成,也可以向專門的https證書提供商進行購買。這兩種的區別是自己生成的證書是不被瀏覽器信任的,所以當訪問的時候回提示不安全的網站,需要點擊信任之后才能繼續訪問
而購買的https證書會提示安全
這是因為瀏覽器中預置了一些https證書提供商的證書,在瀏覽器獲取到服務器的https證書進行驗證的時候就知道這個https證書是可信的;而自己生成的證書,瀏覽器獲取到之后無法進行驗證是否可信,所以就給出不安全的提示。
下面對具體的一些知識點進行介紹
1. 什么是https
https簡單的說就是安全版的http,因為http協議的數據都是明文進行傳輸的,所以對于一些敏感信息的傳輸就很不安全,為了安全傳輸敏感數據,網景公司設計了SSL(Secure Socket Layer),在http的基礎上添加了一個安全傳輸層,對所有的數據都加密后再進行傳輸,客戶端和服務器端收到加密數據后按照之前約定好的秘鑰解密。
2. 加密和解密
Https的發展和密碼學的發展是分不開的。大家應該知道加密方式可以大體分為對稱加密和非對稱加密(反正我就知道這兩種)
- 對稱加密,就是加密和解密都是用同一個秘鑰,這種方式優點就是速度快,缺點就是在管理和分配秘鑰的時候不安全。
- 非對稱加密算法,非對稱加密有一個秘鑰對,叫做公鑰和私鑰,私鑰自己持有,公鑰可以公開的發送給使用的人。使用公鑰進行加密的信息,只有和其配對的私鑰可以解開。目前常見的非對稱加密算法是RSA,非對稱的加密算法的優點是安全,因為他不需要把私鑰暴露出去。
在正式的使用場景中一般都是對稱加密和非對稱加密結合使用,使用非對稱加密完成秘鑰的傳遞,然后使用對稱秘鑰進行數據加密和解密
3. https證書的申請流程
1 在服務器上生成CSR文件(證書申請文件,內容包括證書公鑰、使用的Hash算法、申請的域名、公司名稱、職位等信息)
可以使用命令在服務器上生成;也可以使用線上的工具進行生成,線上的工具會把公鑰加入到CSR文件中,并同時生成私鑰。
2 把CSR文件和其他可能的證件上傳到CA認證機構,CA機構收到證書申請之后,使用申請中的Hash算法,對部分內容進行摘要,然后使用CA機構自己的私鑰對這段摘要信息進行簽名
,
3 然后CA機構把簽名過的證書通過郵件形式發送到申請者手中。
4 申請者收到證書之后部署到自己的web服務器中。下面會在寫一篇關于部署的文章
當然這是不通過CA代理機構進行申請的流程,現在網上有好多CA的代理機構,像騰訊云,阿里云都可以申請https證書,流程都差不多。
阿里云申請證書流程
4. 客戶端(瀏覽器)和服務器端交互流程
- client Hello,客戶端(通常是瀏覽器)先向服務器發出加密通信的請求
(1) 支持的協議版本,比如TLS 1.0版。
(2) 一個客戶端生成的隨機數 random1,稍后用于生成"對話密鑰"。
(3) 支持的加密方法,比如RSA公鑰加密。
(4) 支持的壓縮方法。
- 服務器收到請求,然后響應 (server Hello)
(1) 確認使用的加密通信協議版本,比如TLS 1.0版本。如果瀏覽器與服務器支持的版本不一致,服務器關閉加密通信。
(2) 一個服務器生成的隨機數random2,稍后用于生成"對話密鑰"。
(3) 確認使用的加密方法,比如RSA公鑰加密。
(4) 服務器證書。
- 客戶端收到證書之后會首先會進行驗證
- 驗證流程
- 我們知道CA機構在簽發證書的時候,都會使用自己的私鑰對證書進行簽名
證書里的簽名算法字段 sha256RSA 表示,CA機構使用sha256對證書進行摘要,然后使用RSA算法對摘要進行私鑰簽名,而我們也知道RSA算法中,使用私鑰簽名之后,只有公鑰才能進行驗簽。- 如果我們使用的是購買的證書,那么很有可能,頒發這個證書的CA機構的公鑰已經預置在操作系統中。這樣瀏覽器就可以使用CA機構的公鑰對服務器的證書進行驗簽。確定這個證書是不是由正規的CA機構頒發的。驗簽之后得到CA機構使用sha256得到的證書摘要,然后客戶端再使用sha256對證書內容進行一次摘要,如果得到的值和驗簽之后得到的摘要值相同,則表示證書沒有被修改過。
- 如果驗證通過,就會顯示上面的安全字樣,如果服務器購買的證書是更高級的EV類型,就會顯示出購買證書的時候提供的企業名稱。如果沒有驗證通過,就會顯示不安全的提示。
- 生成隨機數
驗證通過之后,客戶端會生成一個隨機數pre-master secret,然后使用證書中的公鑰進行加密,然后傳遞給服務器端
PreMaster secret
PreMaster Secret是在客戶端使用RSA或者Diffie-Hellman等加密算法生成的。它將用來跟服務端和客戶端在Hello階段產生的隨機數結合在一起生成 Master Secret。在客戶端使用服務端的公鑰對PreMaster Secret進行加密之后傳送給服務端,服務端將使用私鑰進行解密得到PreMaster secret。也就是說服務端和客戶端都有一份相同的PreMaster secret和隨機數。
PreMaster secret前兩個字節是TLS的版本號,這是一個比較重要的用來核對握手數據的版本號,因為在Client Hello階段,客戶端會發送一份加密套件列表和當前支持的SSL/TLS的版本號給服務端,而且是使用明文傳送的,如果握手的數據包被破解之后,攻擊者很有可能串改數據包,選擇一個安全性較低的加密套件和版本給服務端,從而對數據進行破解。所以,服務端需要對密文中解密出來對的PreMaster版本號跟之前Client Hello階段的版本號進行對比,如果版本號變低,則說明被串改,則立即停止發送任何消息。
pre-master secret
- 服務器收到使用公鑰加密的內容,在服務器端使用私鑰解密之后獲得隨機數pre-master secret,然后根據radom1、radom2、pre-master secret通過一定的算法得出session Key和MAC算法秘鑰,作為后面交互過程中使用對稱秘鑰。同時客戶端也會使用radom1、radom2、pre-master secret,和同樣的算法生成session Key和MAC算法的秘鑰。
生成session Key的過程中會用到PRF(Pseudorandom Function偽隨機方法)來生成一個key_block,然后再使用key_block,生成后面使用的秘鑰。
key_block = PRF(SecurityParameters.master_secret,"key expansion",SecurityParameters.server_random +SecurityParameters.client_random);
PRF是在規范中約定的偽隨機函數
在信息交互過程中用到的秘鑰有6個分別是。客戶端和服務器端分別使用相同的算法生成。
秘鑰名稱 | 秘鑰作用 |
---|---|
client_write_MAC_key[SecurityParameters.mac_key_length] | 客戶端發送數據使用的摘要MAC算法 |
server_write_MAC_key[SecurityParameters.mac_key_length] | 服務端發送數據使用摘要MAC算法 |
client_write_key[SecurityParameters.enc_key_length] | 客戶端數據加密,服務端解密 |
server_write_key[SecurityParameters.enc_key_length] | 服務端加密,客戶端解密 |
client_write_IV[SecurityParameters.fixed_iv_length] | 初始化向量,運用于分組對稱加密 |
server_write_IV[SecurityParameters.fixed_iv_length] | 初始化向量,運用于分組對稱加密 |
- 然后再后續的交互中就使用session Key和MAC算法的秘鑰對傳輸的內容進行加密和解密。
具體的步驟是先使用MAC秘鑰對內容進行摘要,然后把摘要放在內容的后面使用sessionKey再進行加密。對于客戶端發送的數據,服務器端收到之后,需要先使用client_write_key進行解密,然后使用client_write_MAC_key對數據完整性進行驗證。服務器端發送的數據,客戶端會使用server_write_key和server_write_MAC_key進行相同的操作。