Friday, March 29, 2024

ECC證書和RSA證書

HTTPS 通過 TLS 層和證書機制提供了內容加密、身份認證和數據完整性三大功能,可以有效防止數據被監聽或篡改,還能抵禦 MITM(中間人)攻擊。TLS 在實施加密過程中,需要用到非對稱密鑰交換和對稱內容加密兩大算法。

對稱內容加密強度非常高,加解密速度也很快,只是無法安全地生成和保管密鑰。在 TLS 協議中,應用數據都是經過對稱加密後傳輸的,傳輸中所使用的對稱密鑰,則是在握手階段通過非對稱密鑰交換而來。常見的 AES-GCM、ChaCha20-Poly1305,都是對稱加密算法。

非對稱密鑰交換能在不安全的數據通道中,產生只有通信雙方才知道的對稱加密密鑰。目前最常用的密鑰交換算法有 RSA 和 ECDHE:RSA 歷史悠久,支持度好,但不支持 PFS(Perfect Forward Secrecy);而 ECDHE 是使用了 ECC(橢圓曲線)的 DH(Diffie-Hellman)算法,計算速度快,支持 PFS。要了解更多 RSA 和 ECDHE 密鑰交換的細節,可以閱讀 Cloudflare 的這篇文章

只有非對稱密鑰交換,依然無法抵禦 MITM 攻擊,還得引入身份認證機制。對於大部分 HTTPS 網站來說,服務端一般通過 HTTP 應用層的帳號體系就能完成客戶端身份認證;而瀏覽器想要驗證服務端身份,需要用到服務端提供的證書。

瀏覽器會在兩個步驟中用到證書:1)證書合法性校驗。確保證書由合法 CA 簽署,且適用於當前網站;2)使用證書提供的非對稱加密公鑰,完成密鑰交換和服務端認證。

證書合法性校驗的原理,簡單總結如下:

根據版本號、序列號、簽名算法標識、發行者名稱、有效期、證書主體名、證書主體公鑰信息、發行商唯一標識、主體唯一標識、擴展等信息,生成 TBSCertificate(To Be Signed Certificate)信息;
簽發數字簽名:使用 HASH 函數對 TBSCertificate 計算得到消息摘要,再用 CA 的私鑰進行加密,得到簽名;
校驗數字簽名:使用相同的 HASH 函數對 TBSCertificate 計算得到消息摘要,與使用 CA 公鑰解密簽名得到內容相比較;

可以看到校驗證書需要同時用到簽名和非對稱加密算法:目前必須使用 SHA-2 做為證書籤名函數(沒有打 XP SP3 補丁的 IE6 不支持);目前一般使用 RSA 算法對 TBSCertificate 進行非對稱加密。可以通過 openssl 工具來查看證書籤名算法:

$ openssl x509 -in chained.pem -noout -text | grep 'Signature Algorithm'
Signature Algorithm: sha256WithRSAEncryption

大部分 CA 都有證書鏈,瀏覽器對於收到的多級證書,需要從站點證書開始逐級驗證,直至出現操作系統或瀏覽器內置的受信任 CA 根證書。

瀏覽器還需要校驗當前訪問的域名是否存在於證書 TBSCertificate 的 Common Name 或 Subject Alternative Name 字段之中。

在 RSA 密鑰交換中,瀏覽器使用證書提供的 RSA 公鑰加密相關信息,如果服務端能解密,意味着服務端擁有證書對應的私鑰,同時也能算出對稱加密所需密鑰。密鑰交換和服務端認證合併在一起。

在 ECDHE 密鑰交換中,服務端使用證書私鑰對相關信息進行簽名,如果瀏覽器能用證書公鑰驗證簽名,就說明服務端確實擁有對應私鑰,從而完成了服務端認證。密鑰交換和服務端認證是完全分開的。

可用於 ECDHE 數字簽名的算法主要有 RSA 和 ECDSA,也就是目前密鑰交換 + 簽名有三種主流選擇:

RSA 密鑰交換(無需簽名);
ECDHE 密鑰交換、RSA 簽名;
ECDHE 密鑰交換、ECDSA 簽名;

內置 ECDSA 公鑰的證書一般被稱之為 ECC 證書,內置 RSA 公鑰的證書就是 RSA 證書。由於 256 位 ECC Key 在安全性上等同於 3072 位 RSA Key,加上 ECC 運算速度更快,ECDHE 密鑰交換 + ECDSA 數字簽名無疑是最好的選擇。由於同等安全條件下,ECC 算法所需的 Key 更短,所以 ECC 證書文件體積比 RSA 證書要小一些。

RSA 證書可以用於 RSA 密鑰交換(RSA 非對稱加密)或 ECDHE 密鑰交換(RSA 非對稱簽名);而 ECC 證書只能用於 ECDHE 密鑰交換(ECDSA 非對稱簽名)。

並不是所有瀏覽器都支持 ECDHE 密鑰交換,也就是說 ECC 證書的兼容性要差一些。例如在 Windows XP 中,使用 ECC 證書的網站只有 Firefox 能訪問(Firefox 的 TLS 自己實現,不依賴操作系統);Android 平台中,也需要 Android 4+ 才支持 ECC 證書。

好消息是,Nginx 1.11.0 開始提供了對 RSA/ECC 雙證書的支持。它的實現原理是:分析在 TLS 握手中雙方協商得到的 Cipher Suite,如果支持 ECDSA 就返回 ECC 證書,否則返回 RSA 證書。

也就是說,配合最新的 Nginx,我們可以使用 ECC 證書為現代瀏覽器提供更好的體驗,同時老舊瀏覽器依然會得到 RSA 證書,從而保證了兼容性。這一次,魚與熊掌可以兼得。

參考文章:《開始使用 ECC 證書》

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.