跳轉到

9.1 TLS 與 HTTPS 的工作原理#

概念說明#

TLS(Transport Layer Security)是瀏覽器網址列那把鎖背後的協定:你在 HTTPS 網站輸入的密碼、信用卡號,全程受它保護。TLS 是一場精心編排的「密碼學交響樂」,把本書的零件全部動員:

需求 TLS 使用 本書章節
協商出對稱金鑰 ECDHE(暫態橢圓曲線 DH) 7.1、7.3
驗證伺服器身分 X.509 憑證 + RSA/ECDSA 簽章 6.2、6.3
加密應用資料 AES-GCM 或 ChaCha20-Poly1305 4.1~4.3
訊息完整性與防竄改 AEAD 認證標籤 6.1
金鑰派生 HKDF(以 HMAC 為積木) 6.1、8.1

TLS 1.3 交握步驟#

  1. ClientHello:客戶端送出支援的加密套件清單、隨機數、以及直接附上自己的 ECDHE 公鑰(key share,省一個往返)。
  2. ServerHello + Certificate:伺服器選定套件、回覆自己的 ECDHE 公鑰、送出憑證鏈,並以憑證私鑰對整個交握簽章(CertificateVerify)——證明「我確實持有這個網域的私鑰」。
  3. 雙方各自計算:ECDH 共享祕密 → HKDF 派生出一組對稱金鑰(加密金鑰、MAC 用的 AEAD 金鑰、IV,且伺服器端與客戶端各一組)。
  4. EncryptedExtensions / Finished:從這裡開始所有訊息都已加密;Finished 訊息含交握全程的 HMAC,任何中間竄改都會被偵測。
  5. 應用資料:每筆記錄用 AEAD 加密,序號納入 nonce 派生,確保 nonce 唯一。

安全特性:

  • 前向保密(PFS):ECDHE 金鑰每次連線全新,日後伺服器私鑰外洩也解不了過去的流量。
  • 1-RTT 交握(TLS 1.3 甚至有 0-RTT 恢復模式,但 0-RTT 資料可被重播,需謹慎使用)。
  • 演算法裁剪:TLS 1.3 刪除了 MD5、SHA-1、CBC 模式、RSA 金鑰交換、靜態 DH——只留「已知安全」的少數組合,大幅壓縮組態出錯空間。

Python 觀察(讀取真實網站憑證)#

import socket, ssl, hashlib

hostname = "www.example.com"
ctx = ssl.create_default_context()      # 載入系統 CA 信任庫、自動驗證鏈
with socket.create_connection((hostname, 443), timeout=10) as sock:
    with ctx.wrap_socket(sock, server_hostname=hostname) as s:
        cert = s.getpeercert()
        print("主體:", cert["subject"])
        print("簽章演算法:", cert["signatureAlgorithm"])
        print("SAN:", cert.get("subjectAltName"))
        print("TLS 版本:", s.version(), "套件:", s.cipher())
        # 憑證指紋(pinned certificate 常用)
        der = s.getpeercert(binary_form=True)
        print("SHA-256 指紋:", hashlib.sha256(der).hexdigest()[:32])

安全性分析與常見破口#

  • 信任錨的弱點:整條鏈賴在「系統 CA 信任庫」(6.3 節);企業代理、惡意根憑證都能變成合法中間人。憑證透明化(CT)公開記錄所有簽發以供監督。
  • 降級攻擊與協定棄用:TLS 1.0/1.1、RC4、3DES、CBC 套件皆已被淘汰;伺服器組態務必「只開 TLS 1.2+(最好僅 1.3)+ AEAD 套件」。SSL Labs 的線上評分是常用的體檢工具。
  • 0-RTT 重播:TLS 1.3 的早期資料不具防重播性,應用層必須自己處理(如只允許冪等請求)。
  • 應用層洩漏:TLS 保護「傳輸」,不保護日誌、快取、Cookie 儲存——Secure/HttpOnly/SameSite 屬性、HSTS(強制 HTTPS)都是補鏈條的措施。

練習#

  1. 用上面的程式檢視五個不同網站的憑證:統計它們的簽章演算法(RSA-2048? ECDSA-P256?)與金鑰交換群(s.cipher() 與 OpenSSL 的 -tls1_3 輸出可輔助)。
  2. 用 openssl s_client -connect example.com:443 -tls1_3 並讀取交握輸出,比對本節的五個步驟各對應哪幾行。
  3. 查閱 RFC 8446 §2 與附錄,列出 TLS 1.3 移除的加密套件類別,並對每一類各寫一句「為什麼移除」(提示:MAC-then-Encrypt 的填充側頻道、靜態金鑰無前向保密、弱雜湊)。