EP.03網路系列

HTTPS 是怎麼加密的?
TLS 握手完全解析

對稱加密、非對稱加密、憑證鏈——理解 HTTPS 安全的完整原理。 從「為什麼需要加密」開始,到 TLS 握手的每一步,一次全部說清楚。

Joseph Chen 2026 14 min read HTTPS · TLS · SSL · 加密 · 憑證

「你知道 HTTPS 比 HTTP 安全,但你說得出為什麼嗎?面試問到『HTTPS 的加密原理』,你會嗎? 這篇從最基本的『為什麼需要加密』開始,到 TLS 握手的每一步,全部說清楚。」

HTTPS 是現代 Web 的基礎設施。不管你是前端、後端還是全端,理解 TLS 的運作原理, 能讓你看懂瀏覽器的紅色警告、知道憑證過期的影響,以及在面試中自信地回答安全性問題。

HTTP 的問題:明信片寄信

HTTP 傳輸就像用明信片寄信——中間任何人都能看到內容。 你在咖啡廳用 HTTP 登入某個網站,同一個 WiFi 上的任何人都能截獲你的帳號密碼。 這不是理論上的威脅,是真實發生的攻擊:中間人攻擊(Man-in-the-Middle Attack)

HTTP 封包明文範例(任何中間節點都能看到)

HTTP 登入請求(明文傳輸)
POST /login HTTP/1.1
Host: example.com
Content-Type: application/json

{"username": "joseph", "password": "mypassword123"}

← 任何位於網路路徑上的節點(路由器、WiFi AP、ISP)
  都能完整看到這份內容,包含你的密碼。
👁️

竊聽(Eavesdropping)

攻擊者讀取你的帳密、信用卡號、私訊內容

✏️

篡改(Tampering)

攻擊者修改傳輸中的內容,注入惡意程式碼

🎭

偽裝(Spoofing)

攻擊者假裝是你的銀行,你以為自己在登入真網站

HTTPS 解決了這三個問題

機密性(Confidentiality)

加密傳輸,攔截也看不懂

完整性(Integrity)

資料被篡改立刻被發現

身份驗證(Authentication)

憑證確認你真的在跟台大醫院講話


加密的兩種方式

要理解 HTTPS,你必須先搞懂兩種加密方式的差別:對稱加密和非對稱加密。 它們各有優缺點,TLS 聰明地把兩者結合在一起。

對稱加密:同一把鑰匙

就像保險箱——你用鑰匙鎖,對方用同一把鑰匙開。加解密速度非常快(AES 幾乎沒有效能負擔)。 問題只有一個:你怎麼安全地把鑰匙給對方?如果通訊本來就不安全,你傳鑰匙的過程也不安全。

對稱加密概念
原文 + 密鑰 → 密文
密文 + 同一把密鑰 → 原文

Alice: "你好" + key123 → "Xf7#@!" → 傳給 Bob
Bob:  "Xf7#@!" + key123 → "你好" ✅

問題:Alice 怎麼把 key123 安全地傳給 Bob?
如果傳輸過程被攔截,密鑰就曝光了。

非對稱加密:公鑰加密,私鑰解密

Bob 有一個特殊的信箱:任何人都能投信進去(公鑰),但只有 Bob 能開(私鑰)。 Alice 把訊息用 Bob 的公鑰加密,傳給 Bob,只有 Bob 能解。攻擊者攔到密文?沒有私鑰,算不出來。

非對稱加密概念
Bob 公開:公鑰(Public Key)← 任何人都能拿
Bob 保密:私鑰(Private Key)← 只有 Bob 有

Alice 加密:訊息 + Bob 的公鑰 → 密文
Bob 解密:密文 + Bob 的私鑰 → 原文 ✅
被攔截的攻擊者:密文 + ??? → 無法解密(沒有私鑰)

對稱加密(Symmetric)

速度快(AES-256 幾乎零負擔)
適合大量資料傳輸
金鑰分發問題:如何安全地傳鑰匙?

常見演算法:AES-128, AES-256, ChaCha20

非對稱加密(Asymmetric)

公鑰可以公開,不怕被截獲
解決金鑰分發問題
速度慢(比對稱加密慢 100–1000 倍)

常見演算法:RSA-2048, ECDSA, ECDH

TLS 的聰明做法:兩者混用

非對稱加密解決「金鑰分發問題」,安全地協商出一個臨時的對稱密鑰(Session Key); 之後用對稱加密傳輸實際資料。安全性 + 效能兼顧。


TLS 握手:HTTPS 的核心

HTTPS = HTTP + TLS(Transport Layer Security)。TLS 握手的目的是: 在開始傳資料之前,安全地協商出一個「只有你和伺服器知道」的對稱密鑰, 然後用這把密鑰加密後續的所有通訊。

TLS 1.3 握手步驟(簡化版)

TLS 1.3 握手流程
1. Client Hello
   瀏覽器:「我支援 TLS 1.3,我的隨機數是 [Random-C],
            我支援這些加密套件(e.g. AES-256-GCM)」

2. Server Hello + Certificate + Key Share
   伺服器:「好,用 TLS 1.3,我的隨機數是 [Random-S],
            這是我的憑證(公鑰在裡面),
            這是我的 DH Key Share(Diffie-Hellman 公開參數)」

3. Client 驗證憑證 + 計算共同密鑰
   瀏覽器:「驗證憑證有效(由可信的 CA 簽發),
            用 DH 算法計算出 Session Key
            (只有我和伺服器知道這把 key)」

4. Client Finished
   瀏覽器:「握手完成,之後用 Session Key 加密通訊」

5. 之後全部用對稱加密(Session Key)傳輸
   → 快速(非對稱加密慢,對稱加密快)
   → 安全(Session Key 從未以明文傳輸過)

Diffie-Hellman:公開頻道上的秘密

這是非對稱加密最神奇的地方——你和伺服器可以在公開頻道上協商出一個只有你們知道的秘密, 即使有人全程監聽,也算不出那個秘密。

DH 的顏色比喻(直覺理解)

公開的底色:黃色(所有人都知道)
Alice 加上自己的秘密色:藍色 → 混出「青色」公開傳出去
Bob 加上自己的秘密色:紅色 → 混出「橙色」公開傳出去
Alice 拿到 Bob 的橙色,加上自己的藍色 → 混出「棕色」
Bob 拿到 Alice 的青色,加上自己的紅色 → 也混出「棕色」
攻擊者只看到黃色、青色、橙色,無法還原棕色(數學上極難反推)

實際上是基於離散對數難題(ECDH),「棕色」就是 Session Key。

前向保密(Forward Secrecy)

TLS 1.3 強制使用 ECDH 的暫時密鑰——每次握手都產生新的 Session Key, 握手完成後立刻丟棄。即使私鑰未來被洩漏,過去的通訊紀錄也無法被解密。

0-RTT(TLS 1.3 新特性)

再次連線到同一個伺服器時,可以重用上次的加密參數, 把握手的 1 RTT 降到 0 RTT,第一個請求和資料一起送出。 代價:無法防止重放攻擊(Replay Attack),適用於讀取操作。


SSL 憑證:誰說你是你?

你說你是台大醫院,但我怎麼知道你真的是台大醫院?你出示衛生署核發的執照(憑證)。 衛生署(CA,Certificate Authority)我信任,所以透過它簽發的執照,我也信任你的身份。

憑證鏈(Chain of Trust)

瀏覽器內建了一份「根 CA 清單」(Root CA Store),這份清單裡的機構是被作業系統或瀏覽器廠商預先信任的。 你的網站憑證不需要直接由根 CA 簽發,只要能追溯到信任的根 CA 即可。

憑證鏈結構
根 CA(Root CA)
  ← 瀏覽器/OS 內建信任(Google、Microsoft、Apple 都有自己的根 CA 清單)
  └── 中間 CA(Intermediate CA)
       ← 由 Root CA 簽發,根 CA 不直接簽發網站憑證(安全考量)
       └── 你的憑證(example.com)
            ← 由中間 CA 簽發,裡面包含你的公鑰與域名

驗證過程:
瀏覽器收到 example.com 憑證
  → 憑證是由「Let's Encrypt 中間 CA」簽的,我信任嗎?
  → 中間 CA 是由「ISRG Root X1」(根 CA)簽的,我信任嗎?
  → ISRG Root X1 在我的根 CA 清單裡 ✅
  → 整條鏈可信,憑證有效

憑證裡面有什麼?

域名(Subject)example.com(或 *.example.com)
公鑰伺服器的公鑰,用於 DH 交換
有效期限發行日 ~ 到期日(Let's Encrypt 是 90 天)
簽發機構(Issuer)哪個 CA 簽的(如 Let's Encrypt)
CA 的數位簽章用 CA 私鑰簽名,確保憑證未被篡改
SANs(可選)Subject Alternative Names,一張憑證涵蓋多個域名

Let's Encrypt:免費憑證改變了一切

以前 SSL 憑證很貴(每年幾千塊),導致許多小網站不願意部署 HTTPS。 2016 年 Let's Encrypt 開始提供免費、自動化的 SSL 憑證,這件事加速了 HTTPS 的全面普及。 現在全球超過 60% 的網站使用 Let's Encrypt 憑證。

使用 certbot 申請 Let's Encrypt 免費憑證
# 安裝 certbot(以 Ubuntu + Nginx 為例)
sudo apt install certbot python3-certbot-nginx

# 申請憑證並自動設定 Nginx
sudo certbot --nginx -d example.com -d www.example.com

# certbot 會自動:
# 1. 向 Let's Encrypt 驗證你擁有這個域名(HTTP-01 挑戰)
# 2. 下載憑證到 /etc/letsencrypt/live/example.com/
# 3. 修改 Nginx 設定,啟用 HTTPS
# 4. 設定自動更新 Cron job(憑證每 90 天到期)

# 手動測試自動更新
sudo certbot renew --dry-run

常見的 HTTPS 相關攻擊

HTTPS 不是銀彈。以下三種攻擊是工程師面試常考、實務常見的安全漏洞,理解它們才能知道如何防禦。

🎭

攻擊 1:中間人攻擊(MITM)

攻擊者用偽造的憑證冒充你的伺服器,建立兩條 TLS 連線:一條到你,一條到真伺服器。 所有流量經過攻擊者中繼,雙方都以為在安全通訊。

瀏覽器的防禦:憑證驗證。攻擊者的假憑證不是由可信 CA 簽發,瀏覽器會顯示紅色警告。看到警告請不要繼續!
⬇️

攻擊 2:SSL Strip(降級攻擊)

攻擊者把你和伺服器之間的 HTTPS 連線降級為 HTTP。 你的瀏覽器以為在用 HTTP(位址列無鎖頭),實際上在跟攻擊者通訊。

解法:HSTS(HTTP Strict Transport Security)
# Nginx 設定 HSTS Header
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# 瀏覽器收到這個 Header 後,記住:
# 「這個網站接下來 31536000 秒(1 年)內只能用 HTTPS」
# 即使你輸入 http://,瀏覽器也自動改成 https://
# 攻擊者無法再插入降級中間人

攻擊 3:憑證過期

Let's Encrypt 憑證每 90 天到期。過期後瀏覽器顯示安全警告,用戶無法正常訪問, Google 等搜尋引擎也會降低排名。這是一個完全可以自動化預防的問題。

設定自動更新(certbot)
# certbot 安裝後通常自動設定 Cron job 或 systemd timer
# 手動確認自動更新是否正常運作
sudo certbot renew --dry-run

# 或手動加入 Cron(每天凌晨 2 點檢查更新)
0 2 * * * /usr/bin/certbot renew --quiet

TLS 1.2 vs TLS 1.3

EP.01 HTTP 文章裡提到過 TLS 握手的 RTT 成本。現在你已經理解握手的細節, 就能真正看懂為什麼 TLS 1.3 更快:它把握手從 2 RTT 降到 1 RTT, 少了一個來回。

比較項目TLS 1.2TLS 1.3
握手往返次數2 RTT1 RTT
支援的加密套件多(含弱加密,如 RC4、3DES)少但全部是強加密
前向保密(Forward Secrecy)可選(不強制)強制(每次握手新密鑰)
0-RTT 重連不支援支援(適用於讀取操作)
舊版相容廣泛支援(IE 11+)現代瀏覽器均支援
現狀仍廣泛使用,但應遷移推薦使用

實務提醒

Nginx 設定 ssl_protocols TLSv1.2 TLSv1.3; 可以同時支援兩者。 現代 CDN(Cloudflare、Vercel)預設啟用 TLS 1.3,瀏覽器支援率超過 95%。 如果你的系統不需要支援超舊的環境,可以只保留 TLS 1.3。

本篇重點回顧

🔓HTTP 是明文傳輸,任何中間節點都能竊聽、篡改、偽裝。HTTPS = HTTP + TLS 解決了這三個問題。
🔑對稱加密速度快,非對稱加密安全。TLS 混用兩者:非對稱交換金鑰,對稱加密傳資料。
🤝TLS 握手用 DH 算法讓雙方在公開頻道協商出只有彼此知道的 Session Key,中間人全程監聽也算不出來。
📜SSL 憑證由 CA 簽發,建立信任鏈(Root CA → 中間 CA → 你的憑證)。Let's Encrypt 提供免費自動化憑證。
🛡️HSTS 防止 SSL Strip 降級攻擊。certbot 自動更新防止憑證過期。面試要能說出 MITM 的防禦原理。
TLS 1.3 比 1.2 少一次 RTT 往返,強制前向保密,加密套件全部是強加密——這是應該遷移的理由。

HTTPSTLSSSL加密憑證網路安全面試EP.03