再談HTTPS

本篇將討論HTTPS的加解密原理,不少人都知道RSA,覺得HTTPS = RSA,使用RSA加解密數據,實際上這是不對的。HTTPS是使用RSA進行身份驗證和交換密鑰,而後再使用交換的密鑰進行加解密數據。身份驗證是使用RSA的非對稱加密,而數據傳輸是雙方使用相同的密鑰進行的對稱加密。那麼,什麼是對稱加密和非對稱加密?node

1. 對稱加密和非對稱加密

假設隔壁小王想要約小紅出來,可是他不想讓小明知道,因而他想用對稱加密給小紅傳了個小紙條,以下圖所示:nginx

他想發送的數據的數據是"Meet at 5:00 PM"(5點見面,若是是中文的話可使用UTF-8編碼),加密方式是直接在ASCII表進行左移或右移,他的密鑰是3,表示在ASCII表日後移3位,就會變成"Phhw#dw#8=33#SP",這樣通常人若是截獲了不知道是什麼意思的。可是咱們能夠想一下,若是既然他能夠載獲你的數據,天然也能夠截獲你的密鑰,進而進行解密,以下圖所示:算法

因此小王打算用非對稱加密,非對稱加密的特色是雙方都有本身的公鑰和私鑰對,其中公鑰發給對方,密鑰不交換本身保管不泄漏,以下圖所示:windows

其中小紅的公鑰爲:瀏覽器

public_key = (N, e) = (3233, 17)安全

她把公鑰發給了小明,她本身的私鑰爲:服務器

private_key = (N, e) = (3233, 2753)工具

這裏注意公鑰和私鑰都是兩個數,N一般是一個大整數,e表示一個冪指數。如今小王想給小紅髮消息,因而他用小紅的公鑰進行加密,怎麼加密呢?他要發送的第一個字母爲t = 「M」,「M」的ASCII編碼爲77,77的加密過程以下計算:網站

T = 77 ^ e % N = 77 ^ 17 % 3233 = 3123google

把77作e次冪而後模以N,便獲得了T = 3123,而後把這個數發給小紅(其它字母按一樣方式處理)。小紅收到T以後便用她的私鑰進行解密,計算以下:

t = T ^ e % N = 3123 ^ 2753 % 3233 = 77

計算方法是同樣的,這樣便把T還原成了t,只要公私鑰配對,即可經過一些數學公式證書上面的推算是成立的。這個就是RSA的加解密原理,若是沒法知道私鑰便沒法進行正確解密。反過來,使用私鑰進行加密,公鑰進行解密也是可行的。

那麼HTTPS是怎麼利用RSA進行加解密的呢,咱們從HTTPS鏈接創建過程提及。

2. HTTPS鏈接創建過程

HTTPS主要有如下做用:

  • 1. 驗證服務方身份,如我訪問google.com的時候連的確實就是谷歌服務器
  • 2. 防止數據被劫持,例若有些運營商會給http的頁面插入廣告
  • 3. 防止敏感數據被竊取篡改等

正如openssl的註釋所說這是防止中間人攻擊的惟一方法:

咱們以MDN(https://developer.mozilla.org)的網站爲例,而後用wireshark抓包,觀察HTTPS鏈接創建的過程,以下圖所示:

首先是TCP三次握手,而後客戶端(瀏覽器)發起一個HTTPS鏈接創建請求,客戶端先發一個Client Hello的包,而後服務端響應一個Server Hello,接着再給客戶端發送它的證書,而後雙方通過密鑰交換,最後使用交換的密鑰加行加解密數據。

在Client Hello裏面客戶端會告知服務端本身當前的一些信息,以下圖所示:

包括客戶端要使用的TLS版本,支持的加密套裝,要訪問的域名,給服務端生成的一個隨機數(Nonce)等。須要提早告知服務器想要訪問的域名以便服務器發送相應的域名的證書過來,由於此時尚未發生HTTP請求。

服務端在Server Hello裏面會作一些響應:

服務端選中的加密套裝叫TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,這一串的意思是:

(1)密鑰交換使用ECDHE

(2)證書籤名算法RSA

(3)數據加密使用AES 128 GCM

(4)簽名校驗使用SHA256

接着服務給客戶端發來了4個證書:

第一個證書的公用名(common name)就是咱們當前訪問的域名developer.mozilla.org,若是公用名是*.mozilla.org的話那麼這個證書便能給mozilla.org的全部二級子域名使用。第二個證書是第一個證書的簽發機構(CA)的證書,它是Amazon,也就是說Amazon會用它的私鑰給developer.mozilla.org進行簽名。依此類推,第三個證書會給第二個證書籤名,第四個證書會給第三個證書籤名,而且咱們能夠看到第四個證書是一個根(Root)證書。

一個證書裏面會有什麼東西呢,咱們能夠展開第一個證書看一下,以下圖所示:

證書包含三部份內容:tbsCertificate(to be signed certificate)待簽名證書內容、證書籤名算法和CA給的簽名。也就是說CA會用它的私鑰對tbsCertificate進行簽名,並放在簽名部分。爲何證書要簽名呢?簽名是爲了驗證身份。

3. 身份驗證

咱們先來看一下tbsCertificate裏面有什麼內容,以下圖所示:

它裏面包括了證書的公鑰、證書的適用公用名、證書的有效期還有它的簽發者等信息。Amazon的證書也具有上述結構,咱們能夠把Amazon證書的公鑰拷出來,以下圖所示:

中間有一些填充的數字,用灰色字表示。能夠看到N一般是一個很大的整數(二進制2048位),而e一般爲65537.

而後咱們用這個CA的公鑰對mozilla.org的證書籤名進行解密,方法和上面的相似:

取解密後的數字decrypted的十六進制的末64位,即爲二進制256位的SHA哈希簽名。接下來咱們手動計算一下tbsCertificate的SHA256哈希值,方法是在wireshark裏面把tbsCertificate導出一個原始二進制文件:

而後再使用openssl計算它的哈希值,以下所示:

liyinchengs-MBP:https liyincheng$ openssl dgst -sha256 ~/tbsCertificate.bin
SHA256(/Users/liyincheng/tbsCertificate.bin)= 5e300091593a10b944051512d39114d56909dc9a504e55cfa2e2984a883a827d

咱們發現手動計算的哈希值和加密後的證書裏的哈希值一致!說明只有知道了Amazon私鑰的人才能正確地對mozilla.org的證書籤名,由於公私鑰是惟一匹配的。所以咱們驗證了第一個證書mozilla.org確實是由第二個證書Amazon簽發的,使用一樣的方式,咱們能夠驗證Amazon是由第三個簽發的,第三個是由第四個根證書籤發。而且第四個證書是根證書,它是內置於操做系統的(經過Mac的keychain工具能夠查看):

假如Hacker經過DNS欺騙之類的方式把你訪問的域名指向了他的機器,而後他再僞造一個證書。可是因爲根證書都是內置於操做系統的,因此它改不了簽名的公鑰,而且它沒有正確的私鑰,只能用本身的私鑰,因爲公私鑰不配對,很難保證加解密後的信息一致。或者直接把瀏覽器拿到的證書搬到他本身的服務器?這樣再給瀏覽器發的證書即是如出一轍,可是因爲他不知道證書的私鑰,因此沒法進行後續的操做,所以這樣是沒有意義的。

這個就是HTTPS可以驗證身份的原理。

另一個例子是SSH,須要手動驗證簽名是否正確,例如經過打電話或者發郵件等方式告知服務器的簽名,與本身算的證書的簽名是否一致,若是一致說明證書沒有被篡改過(如證書的公鑰沒有被改成Hacker的公鑰):

上面展現的即是本身手動計算的值,拿這個值和以前的值進行比較是否相等即可知發過來的證書是否沒被修改過。

那麼,爲何不直接使用RSA的密鑰對進行加密數據?由於RSA的密鑰對數值太大,不太合適頻繁地加解密數據,因此須要更小的密鑰,另外一個緣由是服務端沒有瀏覽器或者客戶端的密鑰,沒法向瀏覽器發送加密的數據(不能用本身的私鑰加密,由於公鑰是公開的)。因此須要進行密鑰交換。

4. 密鑰交換

密鑰交換的方式有兩種RSA和ECDHE,RSA的方式比較簡單,瀏覽器生成一把密鑰,而後使用證書RSA的公鑰進行加密發給服務端,服務再使用它的密鑰進行解密獲得密鑰,這樣就可以共享密鑰了,它的缺點是攻擊者雖然在發送的過程當中沒法破解,可是若是它保存了全部加密的數據,等到證書到期沒有被維護之類的緣由致使私鑰泄露,那麼它就可使用這把私鑰去解密以前傳送過的全部數據。而使用ECDHE是一種更安全的密鑰交換算法。以下圖所示,雙方經過ECDHE進行密鑰交換:

ECDHE的全稱是Elliptic Curve Diffie–Hellman key Exchange橢圓曲線迪非-赫爾曼密鑰交換,它是對迪非-赫爾曼密鑰交換算法的改進,這個算法的思想以下圖所示:

爲了獲得共享祕鑰K,甲用它的私鑰計算一個數g ^ a,發送給乙,乙的私鑰爲b,乙便獲得K = g ^ a ^ b,同時發送g ^ b給甲,甲也獲得了K = g ^ b ^ a。這個應該比較好理解,而引入橢圓曲線加密可以提升破解難度。

5. 橢圓曲線加密

如今的證書的簽名算法有兩種,RSA和新起的EC,以下圖所示,google.com即是使用的ECC證書:

咱們上面討論的即是RSA,破解RSA的難點在於沒法對公鑰的N進行質數分解,若是你能對證書的N拆成兩個質數相乘,即可推算出證書的私鑰,可是在當前的計算能力下是不可能的。而ECC的破解難點在於找到指定點的係數。

以下圖所示,有一條橢圓曲線方程:y ^ 3 = x ^ 2 + ax + b:

給定一個起點G(x, y),如今要計算點P = 2G的座標,其過程是在G點上作一條線與曲線相切於-2G,作-2G相對於x軸的反射便獲得2G點。爲了計算3G的座標,以下圖所示:

鏈接2G與G與曲線相郊於-3G,再作反射獲得3G,同理計算4G即是鏈接G與3G再作反射。若是最後一個點和起點的連線垂直於x軸,說明全部的點已用完。

EC的難點在於給定起點G和點K:

K = kG

想要獲得k(k足夠大)是一件很困難的事情。這個k即是私鑰,而K = kG即是公鑰。ECC是怎麼加解密數據的呢?

假設要加密的數據爲m,把這個點看成x座標獲得在曲線上的一個點M,取定一個隨機數r,計算點C1 = rG,C2 = M + rK,把這兩個點即是加密後的數據,發給對方,對方收到後使用私鑰k進行解密,過程以下:

M = C2 - rK = C2 - rkG = C2 - rkG = C2 - kC1

經過上面的計算便能還原獲得M. 而不知道私鑰k的人是沒法解密的。更多細節可見medium的這篇文章《ECC elliptic curve encryption》。

這樣咱們便理解了ECC的原理,那麼怎麼利用ECC進行密鑰交換呢?

6. ECC密鑰交換

原理很簡單,以下圖所示:

以前交換的是兩個冪次方的數,如今變成交換兩個曲線上的點。

而曲線方程是規定好的,例如Curve X25519使用的曲線方程爲:y^2 = x^3 + 486662x^2 + x,在密鑰交換裏面會指定所使用的曲線方程,以下圖所示:

mozilla.org所使用的曲線方程爲secp256r1,這個也是比較流行的一個,它的參數比Curve X25519大不少。密鑰交換也使用了證書的私鑰進行簽名保證交換的密鑰不會被人篡改,只是這裏的私鑰是mozilla自已的私鑰。

也就是說從鏈接創建到如今都是明文傳輸的。接下來雙方發送Change Cipher Spec的包通知接下來的包都按照以前約定好的方式進行加密。至此整個安全鏈接創建完畢。

7. HTTPS證書的應用

那麼是誰在作HTTPS加密呢?服務端一般是Nginx、Apache這些反向代理服務器作的,而具體的業務服務器不須要處理,客戶端一般是瀏覽器等作的加解密,Chrome是使用boringSSL這個庫,fork自openssl。

咱們能夠經過let’s encrypt能夠申請免費的TLS證書,每3個月須要手動續,證書分爲3種:DV、OV、EV,DV適用於我的,OV和EV須要身份審覈,EV最高端。EV證書會在瀏覽器的地址欄顯示證書的企業名稱:

可是新版的Chrome彷佛把這個去掉了,因此咱們打開medium的控制檯能夠看到一個提示:

As part of an experiment, Chrome temporarily shows only the lock icon in the address bar. Your SSL certificate with Extended Validation is still valid.

另外咱們能夠用用openssl生成一個自簽名證書,執行如下命令:

openssl req -x509 -nodes -sha256 -days 365 -newkey rsa:2048 -keyout test.com.key -out test.com.crt

便會獲得兩個文件,test.com.crt是證書,test.com.key是證書的私鑰,以下圖所示:

而後把這兩個文件給nginx使用便能使用https訪問,以下代碼所示:

server {
        listen       443;
        server_name  test.com;
        ssl on;
        ssl_certificate    test.com.crt;
        ssl_certificate_key    test.com.key;
     }複製代碼

能夠把這個證書添加到系統證書裏面,這樣瀏覽器等便能信任,或者直接使用mkcert工具一步到位。

8. 客戶端證書

還有一種證書叫客戶端證書,一樣須要向CA機構申請一個客戶端證書,和服務端TLS證書不同的地方是,服務端證書一般是和域名綁定的,而客戶端證書能夠給本地的任意可執行文件進行簽名。簽名驗證算法和上文討論 的TLS證書一致。爲何可執行文件須要簽名呢,由於若是不簽名的話,系統會攔截安裝或者運行,如Mac雙擊一個未簽名的dmg包的提示:

直接不讓你運行了,而windows也有相似的提示:

而windows是會給一個警告:

而當咱們運行一個已簽名的exe文件將會是正常的提示,如Chrome的提示:

綜上本文主要討論了對稱加密和非對稱加密的原理,並介紹瞭如何利用RSA對證書籤名的檢驗以驗證鏈接服務器的身份,怎麼利用ECC進行數據加密和密鑰交換,介紹了下怎麼生成和使用HTTPS證書,並介紹了下客戶端證書。相信看完本篇會對HTTPS的加解密有一個較爲全面的瞭解,以前也寫過一篇介紹HTTPS的,本篇補充了更多的細節內容。

相關文章
相關標籤/搜索