Web技術(三):TLS 1.2/1.3 加密原理(AES-GCM + ECDHE-ECDSA/RSA)

前言

前篇博客:圖解HTTP中談到,HTTP/1.1 協議默認是以明文方式傳輸數據的,這就帶來三個風險:竊聽風險、僞裝風險、篡改風險。HTTP 協議自身沒有加密機制,但可以通過和 TLS (Transport Layer Security) / SSL (Secure Socket Layer) 的組合使用,加密 HTTP 的通信內容,藉助 TLS / SSL 提供的信息加密功能、完整性校驗功能、身份驗證功能保障網絡通信的安全,與 TLS / SSL 組合使用的 HTTP 被稱爲 HTTPS(HTTPSecure),可以說 HTTPS 相當於身披 SSL / TLS 外殼的 HTTP。
HTTPS協議分層模型
近幾年,網絡安全問題越來越受重視,國內外各大互聯網公司比如Google、Baidu、Facebook等,都在不謀而合地開始大力推行 HTTPS,爲鼓勵全球網站的 HTTPS 實現,一些互聯網公司都提出了自己的要求:

  • Google 已調整搜索引擎算法,讓採用 HTTPS 的網站在搜索中排名更靠前;
  • 從 2017 年開始,Chrome 瀏覽器已把採用 HTTP 協議的網站標記爲不安全網站;
  • 蘋果要求 2017 年 App Store 中的所有應用都必須使用 HTTPS 加密連接;
  • 當前國內炒的很火熱的微信小程序也要求必須使用 HTTPS 協議;
  • 新一代的 HTTP/2 協議的支持需以 HTTPS 爲基礎。

因此,我們要開發網絡應用,也應該跟上全網 HTTPS 的潮流,使用 HTTPS 協議爲我們的數據安全上一把鎖。前一篇博客已經詳細介紹了 HTTP 協議,下面重點介紹網絡安全通信協議 TLS / SSL。

一、TLS 加密原理

SSL(Secure Socket Layer) / TLS(Transport Layer Security) 是獨立於 HTTP 的協議,所以不光是 HTTP 協議,其他運行在應用層的 SMTP 和 Telnet 等協議均可配合 SSL / TLS 協議使用,可以說 SSL / TLS 是當今世界上應用最爲廣泛的網絡安全技術。

Netscape 開發了原始的 SSL 協議,SSL 1.0 因爲存在嚴重的安全缺陷從未公開發布,SSL 2.0於 1995年發佈,但其中仍包含許多安全缺陷,於是在1996年發佈了SSL 3.0。隨着加密與解密安全攻防戰的博弈,SSL 協議的安全性逐漸滿足不了需求,SSL 2.0 在 2011 年被RFC 6176棄用,SSL 3.0 於 2015 年被RFC 7568棄用。

TLS 1.0 在 1999 年發佈於RFC 2246中,TLS 1.0 和 SSL 3.0 之間的差異並不顯著(TLS 1.0 等同於 SSL 3.1),改名主要是爲了和Netscape撇清關係(SSL協議由Netscape主導開發),表示一個新時代的來臨(TLS協議由 IETF 進行標準化)。

隨着網絡攻擊技術的發展,TLS 加密算法也需要進行升級,TLS 1.1 於 2006 年在RFC 4346中定義,TLS 1.2 於 2008 年在RFC 5246中定義,並於2011年在RFC 6176中完成優化,最新版本的TLS 1.3 於 2018 年在RFC 8446中定義。早在2018年10月,蘋果、谷歌、微軟和Mozilla就聯合宣佈,將在2020年3月棄用TLS 1.0和TLS 1.1(當你讀到本篇博客時,TLS 1.0和TLS 1.1 已經被棄用),由於 TLS 1.3 才發佈沒多久,未來幾年內 TLS 1.2 將成爲網絡安全協議的主流(HTTP/2協議便使用TLS 1.2+版本作爲安全加密層)。
SSL/TLS協議發佈時間與網站支持率對比

1.1 TLS 信息加密

早在幾千年前,人們就有了對信息加密的需求和實踐,最初人們只是將完整信息隱藏,後來將字符進行移位變換處理以隱藏原來的意思(可以參考博客:諜戰中的古典密碼學)。隨着上世紀計算機的誕生和數學的進步,將有效信息編碼爲二進制數據,並對這些二進制數據進行數學運算處理的現代密碼學獲得了飛速發展(可以參考博客:區塊鏈中的現代密碼學)。

現代密碼學根據密鑰不同,可以分爲對稱密鑰加密法和非對稱密鑰加密法,二者區別對比如下:

類別 對稱密鑰加密法 非對稱密鑰加密法
特點 加密和解密使用相同的的密鑰 加密和解密使用成對的公鑰和私鑰,
可以使用公鑰解密私鑰解密(信息加密),
也可以使用私鑰加密公鑰解密(數字簽名)
優點 加密和解密的效率高(比非對稱加密效率高几百倍),適合大數據量加解密 不需要交換密鑰,安全性更強,還可用於身份認證
缺點 雙方需要交換密鑰,密鑰的安全無法保證 加密和解密的效率低(只有對稱加密效率的幾百分之一),不適合大數據量加解密
常用算法 DES、3DES、IDEA、AES RSA、DSA、ECC、Diffie-Hellman

從上面的對比可以看出,Web的數據量還是比較大的,對Web數據信息進行加密適合選擇對稱密鑰加密法。但對稱密鑰加密法有個缺陷,通信雙方需要交換密鑰,密鑰的安全沒法得到保證,這就需要藉助非對稱密鑰加密法來交換密鑰了。TLS 也正是採用類似的策略,通過非對稱密鑰加密法來交換會話密鑰,通過對稱密鑰加密法來加密信息。
TLS混合密鑰加密過程
我們先看對Web信息加密使用的對稱密鑰加密法,按照加密方式不同可以將對稱密碼分爲兩大類:序列密碼(流密碼) 和分組密碼(塊密碼),二者的區別對比如下:

類別 序列密碼 / 流密碼 分組密碼 / 塊密碼
特點 以最小單位比特作爲一次加解密的操作元素,採用設計好的算法對明文數據流進行加密與解密操作 將明文分爲若干長度固定的組塊(長度不足的組塊按特定格式填充),以每個組塊作爲一次加解密的操作元素,採用設計好的算法對明文數據組塊進行加密與解密操作
優點 速度快,便於硬件實現,錯誤傳播較輕 統計特性優良,修改敏感
缺點 統計混亂不足,修改不敏感 速度慢,錯誤傳播嚴重
常用算法 WEP、RC4、ChaCha20 DES、3DES、IDEA、AES

流密碼算法是以“一次性密碼本“爲雛形演變出來的加密算法,一次性密碼本算法很重要的一個特性就是密鑰使用的”一次性“,流密碼算法安全性的關鍵也在於絕不第二次使用相同的密鑰,這就需要能產生大量的隨機數。流密碼使用僞隨機數發生器產生一次性密鑰流,可以說流密碼的安全性取決於僞隨機數發生器的性能,高性能的僞隨機數發生器(一個硬件模塊)也可以構建出強度較高的流密碼算法。我們一般使用的計算機並沒有專門提供高性能的僞隨機數發生器硬件模塊,所以使用流密碼算法的比較少(流密碼算法便於硬件實現,一般在專門設計有僞隨機數發生器的平臺上使用),更常用的是分組密碼算法。

分組密碼的每個組塊加解密類似於流密碼,每個組塊的長度可以作爲衡量加密強度的一個指標,現在一般採用128位、192位、256位的組塊長度(需要平衡加密強度與加密效率,隨着處理器計算能力提升也會同步提升加密強度)。DES(Data Encryption Standard)是1977年美國聯邦信息處理標準(FIPS)種所採用的一種對稱密碼(3DES是其三重加密增強版),目前已能在短時間內被破解。現在推薦使用的對稱加密算法是AES(Advanced Encryption Standard),該算法是在2001年通過全世界範圍內公開競爭方式選拔出來的,Rijndael 算法最終力壓羣雄被美國國家標準技術研究所(NIST)選定爲AES標準。

分組密碼的關鍵特性是每個組塊都使用不同的組塊密碼,這些組塊密碼可以有相關性,也即後一組的密碼可以通過前一組的密碼迭代而來(分組密碼靠迭代關係降低了對僞隨機數發生器的性能需求)。根據分組密碼迭代方式的不同,產生了多種不同的分組密碼模式,常見的有五種模式ECB、CBC、CFB、OFB、CTR。這五種分組密碼模式就不一一介紹了,這裏主要介紹兩種常用的模式:CBC(Cipher Block Chaining mode)和CTR(Counter mode),二者的主要區別對比如下:
CBC與CTR分組密碼模式對比

類別 CBC(Cipher Block Chaining mode) CTR(Counter mode)
特點 首先將明文分組與前一個密文分組進行XOR異或運算,然後再進行加密;加密第一個分組時,使用一個隨機產生的初始化向量 IV(Initialization Vector)來代替前一個密文分組 每個分組對應一個逐次累加的計數器,並通過對計數器加密生成分組密碼;最終的密文分組是通過將計數器加密得到的密鑰流與明文分組進行XOR異或運算得到的
優點 明文的重複排列不會反映在密文中,支持並行解密 支持並行加解密運算,不需要填充
缺點 加密不支持並行運算,密文分組包含某些錯誤比特時會影響後續所有的分組解密 主動攻擊者反轉密文分組中的某些比特時會引起明文分組對應比特位的反轉

在早期的TLS / SSL版本中主要使用 AES CBC 進行信息加密,後來 AES CTR 支持並行加解密的優勢逐漸凸顯,被TLS 1.2 及之後的版本選用,TLS / SSL 各版本支持的信息加密算法如下:
TLS信息加密算法
TLS 1.3版本增強安全性的同時對協議進行了簡化,刪除了對不安全加密算法的支持,對於分組密碼只支持AES GCM(Galois-MAC + CTR Mode)和AES CCM(CBC-MAC + CTR Mode ),這兩種加密算法實際上都是AES CTR,只是在此基礎上增加了MAC(Message Authentication Code)用來驗證數據完整性,這部分在下文介紹。

1.2 TLS 完整性校驗與認證加密

我們在博客:哈希算法能用來幹啥?中介紹了Hash散列算法能用來進行數據完整性校驗,Hash散列函數最常見的使用場合是以緊湊的方式表示並比較大量數據,主要是基於Hash函數的以下特點:

  • 能將任意長度的輸入快速轉化爲定長輸出;
  • 具備單向性,從哈希值不能反向推導出原始數據;
  • 對輸入數據非常敏感,幾乎無法找到兩條散列相同的消息;

因此對信息數據經過Hash函數計算後的散列值可稱爲消息摘要(Message Digest)或消息指紋(Message Fingerprint),所使用的Hash函數也稱爲消息摘要函數,常見的安全Hash算法(Secure Hash Algorithms)如下:
SHA算法分類
從上圖可以看出MD5、SHA-1 已經不再安全,現在用的比較多的是SHA-256、SHA-512等,SHA-3算法(和AES一樣,也是通過全球範圍內公開競爭方式實現標準化的)因爲發佈時間較晚,且目前 SHA-2 尚未被攻破,因此SHA-2仍是主流(比特幣中使用的便是SHA-256),TLS 1.2及更新的版本使用 SHA-256/384 取代了之前的MD5 / SHA-1。

使用Hash散列值可以實現數據完整性檢查,能夠辨別出“篡改”,但無法辨別出“僞裝”。假如將消息密文與對應的散列值一起發送,攻擊者可以同時修改密文和對應的散列值,接收端仍然能通過消息完整性校驗。怎麼才能保證Hash散列值不被篡改呢?一個簡單的思路就是對散列值進行加密後發送,使用密鑰加密後的散列值稱爲消息認證碼(Message Authentication Code)。密文與對應的MAC一起發送,由於攻擊者不知道密鑰,即便修改密文也沒法生成合法的MAC,也就能保證散列值不被篡改(前提是密鑰沒泄露),接收方可以同時辨識出數據的“篡改”和“僞裝”。
MAC工作原理
消息認證碼MAC有兩個輸入數據:消息和密鑰,輸入的消息可以是明文也可以是密文,輸入的密鑰可以是分組密碼、流密碼、公鑰密碼等,MAC算法中至少包含一種散列算法以便獲取消息的散列值。根據選用的輸入密鑰Key類型和MAC算法,消息認證碼MAC可以有不同的實現方式,比如:

  • HMAC(Hash-MAC):使用SHA-2之類的單向Hash函數實現,根據使用散列函數的不同可細分爲HMAC-MD5、HMAC-SHA1、HMAC-SHA256/384等;
  • CMAC(CBC-MAC):使用AES之類的分組密碼實現,並採用CBC模式將消息全部加密,由於CBC模式最後一個分組會受到整個消息和密鑰的雙重影響,因此可以將它用作MAC;
  • GMAC(Galois-MAC):使用AES之類的分組密碼實現,但與CMAC不同的是,GMAC在計算散列值時使用了Galois有限域的加法和乘法運算,可以充分利用並行處理獲得更高的效率;
  • Poly1305:使用ChaCha20之類的流密碼實現;

我們先看下TLS / SSL 各版本使用了哪些數據完整性校驗算法:
TLS數據完整性算法
在TLS 1.2版本之前採用HMAC-MD5、HMAC-SHA1作爲數據完整性校驗算法,前面已經介紹過MD5和SHA1 已經不再安全,因此TLS 1.3 刪除了對HMAC算法的支持。TLS 1.3僅支持AEAD來校驗數據完整性,這個AEAD是什麼呢?

**AEAD(Authenticated Encryption with Associated Data)**全稱關聯數據認證加密,認證加密是一種將對稱密碼加密和消息認證碼相結合,同時滿足機密性、完整性和認證功能的機制。AEAD包含對稱加密和MAC計算兩部分,根據二者的先後順序可以將AEAD分爲Encrypt-then-MAC、Encrypt-and-MAC、MAC-then-Encrypt 三種方法:
認證加密方法
既然AEAD是對稱加密算法與MAC計算的組合,TLS 1.3 支持的AEAD算法有三種:AES-CCM、AES-GCM、ChaCha20-Poly1305。最後一種流密碼認證加密算法一般需要硬件上提供一個僞隨機數發生器,前兩個分組密碼認證加密算法使用場景比較多,舉例如下:

AEAD算法 AEAD方法 優缺點對比 使用場景舉例
AES-CCM
(AES-CTR + CBC-MAC)
Encrypt-and-MAC 受限於CBC模式特性,不能充分發揮並行處理的優勢 TLS 1.2/1.3、IPsec、WLAN WPA2、BT LE等
AES-GCM
(AES-CTR + Galois-MAC)
Encrypt-then-MAC 可以充分利用並行處理提高效率 TLS 1.2/1.3、IPsec、WLAN WPA3、SSH等

AES-GCM認證加密算法可以充分利用並行處理提高效率,也是TLS 1.2/1.3 優先推薦的認證加密算法,下面簡單介紹下GCM認證加密過程(圖片取自博客:什麼是 AES-GCM加密算法):
AES-GCM認證加密過程
爲了更直觀瞭解AES-GCM加密算法的效率,下面給出幾種對稱加密與完整性校驗算法的性能對比圖示(只找到以AES-128-CBC-SHA1爲參考的對比圖,但SHA1已不再安全):
幾種對稱加密與完整性校驗算法性能對比
從上面的對比圖可以看出,AES-128-GCM-SHA256和AES-256-GCM-SHA384的運算效率明顯高於其它對稱加密與完整性校驗算法,AES-GCM認證加密算法的並行處理優勢還是挺明顯的,這也是TLS 1.2/1.3 優先推薦使用AES-GCM認證加密算法的原因。

1.3 TLS 報文結構

TLS (Transport Layer Security)協議是由TLS 記錄協議(TLS Record Protocol)和TLS 握手協議(TLS Handshake Protocol)這兩層協議疊加而成的,位於底層的TLS 記錄協議負責進行信息傳輸和認證加密,位於上層的TLS 握手協議則負責除加密以外的其它各種操作,比如密鑰協商交換等。上層的TLS 握手協議又可以分爲4個子協議,TLS 協議的層次結構如下圖所示:
TLS協議的層次結構
前面已經介紹了TLS 協議的認證加密算法,這裏先介紹TLS 記錄協議的報文結構,每一條TLS 記錄以一個短標頭起始,標頭包含記錄內容的類型(或子協議)、協議版本和長度,消息數據緊跟在標頭之後,如下圖所示:
TLS記錄報文
TLS記錄報文的字段可以用如下數據結構定義:

enum {
change_cipher_spec (20),
alert (21),
handshake (22),
application_data (23)
} ContentType;

struct {
uint8 major;
uint8 minor;
} ProtocolVersion;

struct {
ContentType type;
ProtocolVersion version;
uint16 length; /* 最大長度爲2^14(16 384)字節 */
opaque fragment[TLSPlaintext.length];
} TLSPlaintext;

瞭解了TLS 記錄報文結構,前面也介紹了認證加密過程,下面以AES-GCM爲例,看看密文(消息明文AES-CNT加密而來,當不需要對消息加密時,此處保持明文即可)和MAC(將序列號、標頭等附加信息與密文一起通過Galois-MAC計算而來)是如何添加進TLS 記錄報文的:
TLS認證加密記錄報文
上圖中的幾個字段作用如下:

  • 序列號:任一端都有自身的序列號並跟蹤來自另一端TLS記錄的數量,能確保消息不被重放攻擊;
  • 標頭:將標頭作爲計算GMAC輸入的一部分,能確保未進行加密的標頭不會遭受篡改;
  • nonce:在加密通信中僅使用一次的密鑰,比如前面介紹過的 IV(Initialization Vector)或CTR初始值。

握手是TLS協議中最精密複雜的部分,我們後面再介紹。回到開頭介紹信息加密時對稱密鑰加密與非對稱密鑰加密的優缺點對比,對稱密鑰加密雖然比較高效,TLS 1.3 優先推薦的AES-GCM認證加密算法也能同時保證通信消息的機密性、完整性、真實性,但共享密鑰的交換是個問題,非對稱密鑰加密法正好能彌補這個不足,作爲通信雙方傳遞共享密鑰的加密算法,下面介紹TLS 的共享密鑰是如何交換的。

1.4 TLS 密鑰交換

早在DES對稱加密法誕生前,共享密鑰的交換就一直是個難題,在沒有良好解決方案之前靠專人面對面傳遞共享密鑰(還記得碟戰中的密碼本麼)。直到1976年,共享密鑰交換的難題被sun公司的高級工程師迪菲和斯坦福大學電子系教授黑爾曼兩人解決,他們提出的共享密鑰交換方案被命名爲Diffie–Hellman key exchange,這也是非對稱公私密鑰加密系統誕生的基礎。

Diffie–Hellman是如何實現共享密鑰交換的呢?答案自然來自於數學,他們兩人花了兩年多時間找到了一種難以逆轉的單向函數:取模運算(modular arithmetic),單向函數或不可逆函數的特點就是正向計算結果唯一、逆向運算結果不確定(比如 11 * 9 = 8 (mod 13)正向計算結果唯一,但問你“在模等於13的體系中,什麼數乘以9後餘數爲8?”,這個問題顯然不能逆運算,所以“模運算”就是一個單向函數,前面介紹的單向散列函數內部也用到了模運算)。非對稱密鑰加密原理和Diffie–Hellman密鑰交換原理在博文:區塊鏈中的現代密碼學中已經有過簡單介紹,再將該博文中關於Diffie–Hellman密鑰交換原理的介紹展示如下:
DH密鑰交換過程

明白了模運算,我們就能知道它是怎麼用來傳遞鑰匙的了,過程如下:

  1. 愛麗絲和鮑勃兩個人都約定使用Gx mod P函數(G、P要求是質數,比如G = 7、P = 101);
  2. 愛麗絲隨便想出一個數A(比如A = 3),鮑勃也隨便想出一個數B(比如B = 6);
  3. 他們兩個人分別把自己想出來的這個數,代入函數Gx mod P計算一下,比如愛麗絲算完等於α,鮑勃算完等於β;
  4. 兩人把計算結果告訴對方,直接打電話也行,寫信也行,反正是不怕被伊芙偷聽的。原因剛剛說過:因爲伊芙偷聽到的只不過是模運算的結果,而這個結果是不可逆的,所以就算伊芙知道結果,也沒法倒推出之前的值;
  5. 等愛麗絲和鮑勃都得到對方的結果之後,愛麗絲再做一次βA mod P運算(也即GA·B mod P),鮑勃做一次αB mod P運算(也即GA·B mod P);
  6. 這兩個人算完後,他們將得到完全一樣的結果(按上例取值的結果是45),這個相同的結果就可以當作他們的鑰匙。整個過程沒人傳遞過鑰匙,但雙方都拿到了同樣的鑰匙。對竊聽者伊芙來說,她偷聽到的只是模運算的結果,因爲這種運算是不可逆的,所以伊芙偷聽了也白聽。

從上面Diffie–Hellman密鑰交換過程可知,愛麗絲與鮑勃各自生成兩個參數A + α、B + β,相互發送其中一個參數(α 和 β)到對端,再經過計算,就可以得到共享密鑰了。最開始兩人還需要約定計算函數(Gx mod P),因此還需要兩個參數 G + P(可以稱爲域參數,對於Web通信常由服務器選取域參數併發送給客戶端)來約定初始條件,而DH密鑰交換的安全性在很大程度上也取決於這兩個域參數的質量。

DH密鑰交換過程中,由服務器向客戶端提供三個參數(兩個域參數和一個計算結果),客戶端向服務器提供一個計算結果,有些場景下兩個域參數以靜態方式被嵌入到服務器和客戶端的證書中,這就可能導致DH密鑰交換的結果是一直不變的共享密鑰,就無法具備前向保密(指即便在密鑰泄露的情況下,也不能拿泄露密鑰解密之前截獲的密文)的能力。要想具備前向保密能力,就需要每次交換的共享密鑰都不一樣,也就要求DH密鑰交換中的兩個域參數每次都是臨時生成且不重複的,具備這種特性的DH稱爲DHE (Ephemeral Diffie-Hellman),DHE也是TLS 1.2/1.3 支持的密鑰交換方案。

通過DHE密鑰協商方案,就可以實現對稱加密中共享密鑰的交換,有了共享密鑰,通信雙方就可以使用認證加密技術進行安全通信了嗎?假如主動攻擊者在密鑰交換前冒充對端,與通信雙方分別完成密鑰交換,並進行正常的認證加密通信,通信雙方可能是難以察覺的,這就帶來了信息泄露和被篡改的風險,這種攻擊也稱爲中間人攻擊(Man-In-The-Middle attack),MITM攻擊過程圖示如下:
DHE密鑰協商遇中間人攻擊
我們該如何應對中間人攻擊呢?最主要的就是要確認通信對端的身份,前面介紹過的消息認證碼MAC具有身份認證的功能(只能確認密鑰持有者的身份),主動攻擊者不知道密鑰所以沒法生成合法的MAC,我們可以借鑑這種思路嗎?顯然是不能的,正因爲沒有共享密鑰才需要DHE密鑰協商,有了密鑰自然就不需要DHE密鑰協商了。

1.5 TLS 數字簽名

還記得博文:區塊鏈中的現代密碼學中提到的數字簽名嗎?非對稱密鑰加密法正向使用(公鑰加密 + 私鑰解密)可以用來加密信息,逆向使用(私鑰加密 + 公鑰解密)可以作爲數字簽名。該特性主要得益於公私密鑰對的一個性質:公鑰加密的信息私鑰能夠解密,私鑰加密的信息公鑰也能夠解密,公鑰對外公開任何人都可以持有,私鑰則只有本人持有

這就意味着任何想向私鑰持有者(比如Alice)發送敏感信息的一方(比如Bob),只要獲取到Alice的公鑰,就可以使用該公鑰加密敏感信息後將密文發送給Alice,該密文只有私鑰持有者Alice能解密。Alice如果想對外發佈一個聲明,爲了防止別人以自己的名義僞造該聲明,可以使用自己的私鑰將該聲明加密後,將密文發佈給目標人羣,任何人都可以使用Alice的公鑰來解密該聲明,確認該聲明確實由Alice本人發佈,別人無法僞造,Alice也無法否認。非對稱密鑰加密法正向和逆向使用的示意圖示如下:
TLS信息加密與數字簽名
最早發明的非對稱密鑰加密法是RSA加密法,RSA的誕生也得益於Diffie、Hellman兩人發表的非對稱公私密鑰加密系統的概念。在DH密鑰交換方案發布的第二年,Ron Rivest、Adi Shamir、Leonard Adleman三人就實現了首個非對稱公私密鑰加密算法:RSA加密法,該加密算法的實現同樣離不開不可逆的單向函數 — 模運算。

RSA加密法的實現原理已經在博文:區塊鏈中的現代密碼學中簡單介紹過了,再將該博文中RSA加密法實現原理展示如下:
RSA加密法實現原理

  1. 愛麗絲展示出來的公開鑰匙,是通過兩個比較大的素數p和q相乘得到的一個更大的數N得到的。p和q具體是多少,愛麗絲只要自己知道就行,千萬不要告訴別人,而乘積N是公開的,誰都可以知道;
  2. 凡是要給愛麗絲髮消息的人,都需要用N來加密,加密的過程依然用的是模運算,而且模就是N。整個數學過程會保證這個模運算不可逆,所以伊芙就算知道N也沒用;
  3. 愛麗絲解密時就不需要N了,而是要用到p和q的具體值,而這兩個值別人都不知道,只有愛麗絲自己知道。具體來說,愛麗絲私下做的另一個模運算中的模,並不是剛剛我們說的N,而是另外一個值(p-1) x (q-1),這個公式中就必須要知道p和q到底是多少纔行。至於爲什麼是(p-1) x (q-1),數學原理會保證這樣操作能算出一把新鑰匙,這把新鑰匙就是愛麗絲自己的私鑰,用這把私鑰一定可以解出原文。

從上面的過程可以看到,RSA加密法公私鑰的安全性取決於P、Q的選取和保密,公鑰E 和 公共模數N 是對外公開的,外界在知道N 和E 的情況下,是沒法進行質因數分解反求出P 和Q 的,特別在N 比較大的情況下。也就是說,RSA加密法的安全強度是跟N 的長度直接相關的,1024位長度的N (也即RSA-1024)已經被證明不安全了,目前TLS 1.2/1.3 推薦使用N 的長度大於2048位。下面給出一份粗略對比不同類型加密算法的安全強度位數與安全級別的列表供參考(表中數據是2012年統計的,隨着計算機性能提升,攻擊手段更強了,安全強度自然也要隨時間提升):
密碼強度推薦
前面介紹了TLS 1.2/1.3 目前推薦的對稱密鑰加密法安全強度爲AES-128,與此安全級別差不多的RSA加密法與DHE密鑰交換算法的安全強度爲RSA-3248和DHE-3248,對應安全級別的單向散列函數的安全強度爲SHA-256/384。上表還列舉出一個橢圓曲線加密法,該算法屬於哪一類呢?

橢圓曲線加密法ECC (Elliptic-Curve Cryptography)是最近備受關注的一種非對稱公私密鑰加密算法(可以參考博文:橢圓曲線密碼算法),從上面的安全強度位數對比中可以看出:

  • ECC所需的密鑰長度比RSA短很多(RSA-3248與ECC-256安全級別相當),這就減少了密鑰存儲和傳輸的要求;
  • ECC利用有限域上的橢圓曲線運算進行加解密的計算量比RSA利用指數運算進行加解密的計算量小很多,這就提高了公私鑰加解密的效率,密鑰越長RSA指數運算量越大,ECC帶來的效率提升越明顯。

因此,ECC還是有取代RSA的潛力的,不過ECC更多的是作爲一種數學運算工具來升級現有的非對稱密鑰加密算法,比如 ECDHE(= DHE + ECC) 就是使用ECC在有限域上的橢圓曲線運算取代DHE在有限域(Galois Field)上的指數運算,大幅縮短密鑰長度並降低計算量。

反應快的朋友可能會提出一個疑問:RSA算法既然可以同時支持信息加密與數字簽名,客戶端直接使用服務器端提供的RSA公鑰將共享密鑰加密後發給服務器,服務器只有使用自己的RSA私鑰才能解密,這不就可以解決對稱加密中共享密鑰交換的問題,而且不需要DHE密鑰協商了嗎?

單靠RSA加密法確實也可以實現共享密鑰的交換,但RSA加密法有個缺點,由於服務器公鑰更新並不方便,所以服務器公鑰與私鑰一般會保持多年不變,一旦RSA私鑰泄露或者被破解(隨着計算機性能提升,安全強度低的舊密碼可以被破解),之前截獲的消息就可以解密了,攻擊者就可以利用這點長期記錄所有加密流量,等待有朝一日獲得RSA私鑰後解密過去記錄的所有加密信息,也就是說RSA並不支持前向保密性,也因此TLS 1.3 不再單獨使用RSA進行共享密鑰交換。

TLS 1.3 支持的具有前向保密性的密鑰交換方案都是“DHE + 數字簽名”的組合,DHE負責密鑰協商,數字簽名負責驗證通信對端的身份。我們很自然就能想到"DHE + RSA"的密鑰協商和身份驗證方案,這也是TLS 1.3 支持的方案之一。這套方案有改進空間嗎?

前面介紹的EC (Elliptic-Curve)橢圓曲線數學工具就派上用場了,使用橢圓曲線(Elliptic-Curve)運算取代DHE中有限域(Galois Field)上的指數運算,就可以將DHE密鑰協商算法的安全性提升、計算量減小,升級爲ECDHE(Elliptic-Curve Diffie–Hellman Ephemeral)密鑰協商方案。數字簽名算法可以藉助ECC實現升級嗎?

RSA數字簽名算法並不適合用橢圓曲線運算升級,NIST(美國國家標準技術研究所)於1991年將DSA(Digital Signature Algorithm)用於數字簽名標準(DSS: Digital Signature Standard),DSA算法跟DHE採用了類似的數學工具:有限域中的離散對數概念(想了解DSA原理,可參考博文:DSA-數據簽名算法),跟DHE和RSA有相近的安全強度,由於DSA是專門爲數字簽名設計的算法(標準DSA算法不能用於數據加密),因此在數字簽名方面比RSA效率跟高一些。

由於DSA跟DHE採用了類似的數學工具,都是基於有限域中的指數運算(利用有限域中的離散對數運算非常困難的特性,來保證破解的難度),因此也可以使用橢圓曲線運算取代DSA中有限域上的指數運算,將DSA數字簽名算法的安全性提升、計算量減小,升級爲ECDSA (Elliptic Curve Digital Signature Algorithm)。

類別 DHE RSA DSA ECC
特點 利用在有限域中求解離散對數的困難度保證安全性 利用對大數進行質因數分解的困難度保證安全性 利用在有限域中求解離散對數的困難度保證安全性 利用在橢圓曲線上求解離散對數的困難度保證安全性
優點 可以安全的進行密鑰協商,支持前向保密性 既可以用於信息加密,又可以用於數字簽名 進行數字簽名的效率比RSA更高 有更強的安全性,更短的密鑰長度,更高的計算效率
缺點 無法驗證通信對端的身份,需要配合數字簽名算法使用 不支持前向保密性 不能用於信息加密,支持率不如RSA 更多的是作爲一種數學工具,跟其它的公私鑰加密方案配合使用
算法升級 藉助ECC提供的數學工具升級爲ECDHE - 藉助ECC提供的數學工具升級爲ECDSA -

TLS 1.2/1.3支持的密鑰協商與身份驗證算法如下:
TLS各版本支持的密鑰協商與身份驗證算法
從上圖可以看出,TLS 1.3 優先推薦的密鑰協商與身份驗證算法是ECDHE-ECDSA,考慮到ECC普及度暫時還不如RSA,同時提供了對ECDHE-RSA、DHE-RSA的支持。
TLS各種密鑰交換算法性能對比

1.6 TLS 密碼套件

前面已經介紹了TLS 使用到的認證加密算法、完整性校驗算法、密鑰協商算法、數字簽名算法等,這些算法都是要配合使用的(單獨使用無法保證信息安全傳輸),各類算法相互組合可以形成一套套加密方案。TLS 握手階段,服務器與客戶端需要協商都使用哪些加密算法,如果逐個協商顯然效率較低,TLS將可用的加密算法組合爲一個個密碼套件,服務器與客戶端只要協商一種密碼套件,就確定了整個加密方案中用到的所有加密算法,能提高通信效率。

TLS密碼套件主要由密鑰交換方法、身份驗證方法、密碼定義(包括對稱加密算法、安全強度、認證與分組模式)以及可選的MAC或PRF算法組合而成(如果沒有采用AEAD認證加密方案,則需提供MAC消息認證碼,若採用AEAD則不再需要單獨指定MAC),圖示如下:
TLS密碼套件格式
下面給出幾個密碼套件示例:
密碼套件組合示例
上表中的PRF(Pseudo Random Function)指的是僞隨機函數,不管是對稱密鑰非對稱密鑰的生成都離不開隨機數,隨機數質量的好壞決定了加密法的安全強度,真正的隨機數很難獲取,更常用的是通過算法實現的僞隨機數。

從TLS 1.2起,所有的算法套件都需要明確指定它們的PRF,一般僞隨機函數PRF由一個密鑰secret、一顆種子seed、一個唯一標籤label 構成(引入種子和標籤便於每次生成不同的僞隨機數,而密鑰secret可以重用)。PRF的生成主要使用了Hash算法,所以密碼套件中的PRF字段是以散列函數強度來描述的(比如SHA-256),PRF的計算過程簡單展示如下:

P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
					   HMAC_hash(secret, A(2) + seed) +
					   HMAC_hash(secret, A(3) + seed) + ...
// A(i) 函數定義如下:
A(1) = HMAC_hash(secret, seed)
A(2) = HMAC_hash(secret, A(1))
...
A(i) = HMAC_hash(secret, A(i-1))

// PRF則是結合標籤和種子對 P_hash 的封裝:
PRF(secret, label, seed) = P_hash(secret, label + seed)

1.7 TLS 網絡攻防

技術是在解決問題的過程中進步的,網絡安全也是在網絡攻擊中逐漸提高的,前面介紹的每種加密方案都是爲了解決當前加密方案遇到的問題而誕生的,比如MAC是爲解決消息可能被篡改或僞造的問題產生的、DHE是爲了解決共享密鑰交換問題發明的、DSA是爲了解決通信對端可能僞裝身份的問題產生的。

我們已經介紹了TLS 加密方案中用到的所有加密算法,這套加密方案能擋住幾乎所有的網絡攻擊嗎?我們來回顧下整個信息安全傳輸流程:

  1. 服務器與客戶端分別獲取對方的公鑰;
  2. 服務器與客戶端之間通過密鑰協商算法(比如ECDHE)進行共享密鑰的協商,首先由服務器選取域參數確定雙方的計算函數,包括服務器生成的一個隨機數,一起使用自己的私鑰對其進行數字簽名(比如ECDSA / RSA)後發送給客戶端;
  3. 客戶端收到服務器發來的消息,使用服務器公鑰驗證通過後保存備用,自己再生成一個隨機數使用自己的私鑰對其進行數字簽名後發送給服務器,服務器與客戶端通過ECDHE密鑰協商算法就可以計算出雙方後續使用的共享密鑰;
  4. 服務器與客戶端之間使用協商好的共享密鑰,對後續的消息進行認證加密(比如AES-GCM),只要共享密鑰不泄露,攻擊者很難解密出傳輸的消息明文。

看起來整個過程挺安全,密鑰協商過程解決了共享密鑰交換的問題,數字簽名可以確認通信對端的身份,認證加密算法可以保證通信內容的機密性、完整性、真實性,看似無懈可擊時回到起點,審視下初始條件或假設。這裏的初始條件是我們已經獲得了通信對端的公鑰,但這個公鑰確實是通信對端的嗎?攻擊者可以讓你獲得的是他僞造的公鑰嗎?
ECDHE數字簽名遇中間人攻擊
還拿中間人攻擊舉例,當客戶端與服務器互相發送公鑰C 和公鑰S 時,攻擊者截獲這兩個公鑰,自己再生成兩對兒公私鑰A和B,分別冒充客戶端和服務器的通信對端分別與他們交換公鑰、協商共享密鑰、認證加密通信,這樣攻擊者就可以獲知共享密鑰解密後續所有的消息。這又回到了前面介紹DHE密鑰協商時遇到的攻擊者僞裝成通信對端的問題,數字簽名確認通信對端身份的作用沒有發揮出來,問題出在哪呢?

再回顧整個過程不難發現,問題就出在公鑰的交換上,我們無法確認我們獲得的公鑰確實是通信對端的公鑰,這也是數字簽名無法解決的問題。也就說是,要正確使用數字簽名,前提就是用於驗證簽名的公鑰必須屬於真正的通信對端。該如何確認自己得到的公鑰是合法的呢?

公鑰不怕泄露,唯一擔心的就是被篡改僞造。生活中我們想判斷一則消息是否真實可信,常常會看是否有權威機構或個人爲其背書,我們想確認自己得到的公鑰是否真實合法,也可以引入權威第三方對其簽名,經過可信第三方簽名的公鑰可以稱爲證書。客戶端與服務器在交換公鑰階段,改爲交換由可信第三方簽名的證書,就能保證自己獲得的公鑰是真實可信的嗎?

假如攻擊者也獲得了一個由可信第三方簽名的證書,豈不是像前面直接交換公鑰遇到的問題一樣。很顯然,證書裏面不止包含通信對端的公鑰,還應有身份標識信息。證書系統是如何工作的?TLS 握手協議都做了哪些工作?我們在下一篇博客:TLS 1.2/1.3 握手協議與性能優化中介紹。

更多文章:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章