Skip to content
~/notes
Go back

SSL/TLS 憑證簡介

10 min read

憑證是什麼?

SSL/TLS 憑證是一種數位證書,用於驗證網站身份,並保護使用者與伺服器之間的通訊安全。它通常由 CA 頒發,負責確認網站的合法性與可被信任程度。

使用憑證的好處

不裝憑證的影響

現在所有主流瀏覽器(Chrome、Safari、Edge)只要遇到 HTTP 網站,都會在網址列強制顯示紅色「不安全」警示,嚴重打擊訪客信任度!

憑證中記載了什麼?

欄位說明
Version(版本)憑證使用的 X.509 版本
Serial Number(序號)每張憑證唯一的編號,用於識別與撤銷
Signature Algorithm(簽名演算法)CA 使用的簽名演算法,例如 sha256WithRSAEncryption
Issuer(簽發者)簽發憑證的 CA
Validity(有效期間)憑證的有效開始與到期時間
Subject(主體)憑證所代表的實體,例如網站、公司名稱、機構等
Subject Public Key Info(主體的公開金鑰資訊)包含演算法(如 RSA、ECDSA)和對應的公鑰
Extensions(延伸欄位)X.509 V3 中新增的欄位
Signature(CA 的簽名)對以上資料的數位簽章,確保憑證沒被竄改
核心安全觀念:公鑰 vs 私鑰

憑證裡面公開記載的是 公鑰(Public Key),任何人都可以查看;而用來解密的 私鑰(Private Key) 必須嚴格保存在伺服器端,絕對不能外洩或發布出來!

憑證在瀏覽器中的資訊
憑證在瀏覽器中的資訊

CA跟瀏覽器是如何保證憑證的有效性?

憑證內容的有效性如何保證?

證書內容的有效性主要以hash跟非對稱加密完成(簽名):

因為hash function在修改文件後會完全不同,可以用來檢查證書有沒有被竄改。private key只會由持有人控制,所以可以用來做身分驗證。

  1. 如何製作簽名

    1. 對憑證內文做Hash
    2. 將Hash後的摘要用Issuer的private key 加密即是簽名
    3. 將簽名附在憑證後面
  2. 如何驗證憑證的簽名

    1. 對憑證用跟簽名時相同的hash function對內文生成摘要A
    2. 用Issuer 的public key對簽名解密產生摘要B
    3. 比對摘要A, B是否吻合
Hashprivate key
保證文件的正確性保證Issuer的身份與不可逃避性
Note

簽名的意義就是幫這個certificate背書,確認它的管理人不會將背後的private key外洩,使得其他人會偽造他的身份。

我們要如何信任 Issuer 簽發的憑證?

要信任某個 Issuer(Ex: Let’s Encrypt, DigiCert, GlobalSign)所簽發的憑證,並不是因為我們個人認識這些 CA,而是因為整個瀏覽器與作業系統建立了一個「信任鏈(Chain of Trust)」與「憑證基礎建設(Public Key Infrastructure, PKI)」來幫我們建立這種信任關係。

因為瀏覽器廠商或是作業系統的審查,我們對CA做出的假設前提有以下幾點:

PKI 信任鏈與根憑證預先信任示意圖

而這整個PKI可以用以下幾點說明:

1. 根憑證(Root Certificate)被預先信任

每個OS或browaer都內建了一組預先信任的根憑證(Trusted Root Certificates)。這些憑證是經過驗證的CA持有的,並由瀏覽器/作業系統廠商預設在系統中。 這些根憑證的private key 都被嚴格保密、不直接簽發最終使用者的憑證,而是用來簽發「中介憑證(Intermediate Certificate)」。

2. 中介憑證(Intermediate Certificate)建立信任鏈

為了安全性考量,root certificate不會直接用來簽署網站憑證,而是先用private key簽出中介憑證,然後中介憑證再去簽發網站的憑證(leaf)。 因此,網站所持有的憑證會附上一串Certificate Chain來證明自己的簽名是來自於被信任的root CA。 舉例來說: 憑證鏈範例:從 Let's Encrypt 的 ISRG Root X1 到中介憑證與網站憑證 最上層的ISRG Root X1就是Let’s Encrypt的其中一個root certificate

3. 驗證過程中使用public key反推簽名

瀏覽器在連線網站時會取得伺服器傳來的憑證鏈,然後一層層檢查:

4. 憑證間可能會互相簽名

新CA在剛開始時,它的root還沒被所有瀏覽器或OS信任。若等所有客戶端更新信任列表可能要很多年。因此,新 CA會請老CA為他的中間憑證交互簽名,新 CA 發出的憑證就能透過這條交互簽名建立的信任鏈,間接被舊系統信任。 舉個例子:Let’s Encrypt 剛推出時,他們的 Root ISRG Root X1還沒被所有OS信任。他們找了已被信任的CA DST Root CA X3來交叉簽名他們的中介憑證。客戶端如果不認識 ISRG,就走 DST 的信任鏈直到找到系統中儲存的root certificate Let's Encrypt 的 ISRG Root X1 與 DST Root CA X3 交叉簽名示意圖

5. CA如何吊銷已存在的憑證

a. CRL(Certificate Revocation List)
b. OCSP(Online Certificate Status Protocol)
c. OCSP Stapling

OCSP Stapling 運作流程示意圖


如何取得憑證

1. 自己簽一個(OpenSSL)

a. 生成一個private key作為root CA

openssl req -x509 -nodes -days 3650 -newkey rsa:4096 \
-keyout rootprivate.key \
-out root.pem

這個指令會生成一個x509的憑證(CSR):

b. 用rootCA簽出

1. 設定簽發出的ext檔
[ v3_ca ]
authorityKeyIdentifier=keyid, issuer
basicConstraints=CA:FALSE
keyUsage=digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName=@alt_names

[alt_names]
DNS.1=www.example.com
DNS.2=example.comserver1.ext
2. 生成伺服器的private key
openssl genrsa -out server1.key 2048
3. 建立CSR
openssl req -new -key server1.key -out server1.csr

並完成憑證的資料填寫

4. 用root private key簽名這個CSR
openssl x509 -req -in server1.csr -CA root.pem -CAkey rootprivate.key \
-CAcreateserial -out server1.crt -days 365 -sha256 -extfile server1.ext
Tip

接下來都可以重複這個步驟直到不斷簽發出以這個root作為信任依據的certificate,直到root到期

c. 加入到 Nginx 的 config 檔

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /path/to/server1.crt;
    ssl_certificate_key /path/to/server1.key;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
    }
}nginx.conf
sudo nginx -t
sudo systemctl reload nginx

d. 加入到系統或瀏覽器信任的root certificate中

不同系統或瀏覽器會有不同作法,例如:

2. 使用Certbot向Let’s Encrypt取得憑證

憑證驗證方式與 ACME 限制

TLS 憑證的常見驗證類型包括:

Let’s Encrypt 只支援 DV,這與它用的ACME 有關。

ACME 是什麼?

ACME(Automatic Certificate Management Environment)是一種自動化協定,由 Let’s Encrypt 推動,用來簡化憑證的申請、驗證與續期流程:

Note

因此 ACME 無法處理需要人工審核與法律文件驗證的 OV / EV 憑證。

DV(Domain Validation,網域驗證)

驗證內容:確認申請者對網域有控制權。

常見挑戰方式(ACME):

憑證內容:

OV / EV(組織驗證與擴充驗證)

這兩種驗證會額外確認申請者的組織身分:

這些流程都需要人力與官方資料驗證,因此無法透過 ACME 協定自動完成。

DV、OV、EV 憑證驗證等級比較示意圖


安裝Certbot

sudo apt update
sudo apt install certbot python3-certbot-nginx

使用 Certbot 申請與安裝憑證

sudo certbot --nginx

Certbot 會自動偵測伺服器設定,並引導你選擇要啟用 HTTPS 的網域,接著自動完成憑證的申請與簽發。

設定自動續期(Let’s Encrypt 憑證有效期只有 90 天)

Certbot 安裝時會自動加上定期任務(cron job)或 systemd timer。

手動測試是否能自動續期:

sudo certbot renew --dry-run

檔案位置

依照上面的 Nginx 設定步驟 就可以把憑證加入到 Nginx 的設定中。

自動化續期技巧

Let’s Encrypt 的免費憑證效期只有 90 天。使用 Certbot 安裝完成後,建議透過命令 certbot renew --dry-run 測試自動續期,確保 Cron job 正常運作,才不會因為憑證過期導致網站斷線

小結


參考資料


Share this post:

Previous Post
ChaCha20-Poly1305 加密演算法介紹