# 收到 TWCA 換證通知後怎麼自己換：找原金鑰、合併新憑證、裝上伺服器、確認換好

> TWCA 換證通知的 zip 只有新憑證，要配上原金鑰才裝得上。照順序走：找伺服器與原金鑰，用 TWCA 工具或 openssl 合併，裝上 Nginx、Apache、IIS、Tomcat，再確認。

原文：https://sheng.page/posts/twca-certificate-notice-without-an-engineer/ · 發布：2026-11-05 · 作者：Sheng

本文整理收到 TWCA 換證通知後，把新憑證換上去的步驟，寫給單位裡沒有專職 IT 的人。通知信附件的 zip 裡只有新憑證，沒有金鑰。開始前要先找到兩樣東西：當初申請時產生的原金鑰，以及能登入放網站那台伺服器的人，缺了其中一樣就裝不上去。

TWCA 10 月 31 日的公告說原中繼憑證要在 11 月 6 日 00:00 前廢止，沒寫時區。11 月 5 日的公告接著寫，預計自 11 月 6 日零時起，廢止序號未符合亂數規範要求的網站憑證，同樣沒寫時區與受影響名單。依 RFC 5280 的路徑驗證規則，憑證被撤銷就驗不過，標準裡沒有寬限期，也沒有向簽發者申請延期的步驟。過了期限還沒換的網站，補救方式和期限前一樣，就是照這篇把新憑證換上去。至於各家瀏覽器多快查到撤銷、警告長什麼樣，公告沒寫，本文也沒測。換證的原因，TWCA 自己的說法是為了讓憑證序號的亂數符合 CA/Browser Forum 規範，並稱不是網站遭入侵或私鑰外洩引發；序號問題與 Bugzilla 紀錄另見〈[去年中華電信，今年 TWCA：中繼憑證 11 月 6 日廢止前該檢查什麼](/posts/twca-intermediate-replacement-what-to-check/)〉。本文資料查核至 2026 年 11 月 5 日 04:26（台北時間），19:30 補查。

更新（2026-11-05 20:15）：補上 TWCA 11 月 5 日公告的網站憑證廢止時程與更新進度，以及金管會的金融業進度。安裝步驟改為連到各家官方文件。資料查核 Claude，精簡 Claude Fable，Codex（gpt-6-astra）二審，Grok 調語氣。

## 通知信在講什麼

網站用 HTTPS 時，伺服器會送一疊憑證給瀏覽器：第一張是站台憑證，後面接簽發它的中繼，一路接到瀏覽器內建信任的根憑證。這一疊就是「憑證鏈」，網址列的鎖頭是這條鏈驗證通過的結果。鏈沒接齊，有的瀏覽器會對同一張憑證報警告，見 nginx〈[Configuring HTTPS servers](https://nginx.org/en/docs/http/configuring_https_servers.html#chains)〉的 SSL certificate chains 一節。

TWCA 這次換的是中間那幾張。部署頁列出的新鏈，由上往下是 TWCA Global Root CA（根憑證）、TWCA CYBER Root CA、TWCA CYBER Root CA G3 Cross Cert、TWCA SSL Certification Authority 或 TWCA EVSSL Certification Authority（依申請類型二選一），最後是你的站台憑證。中繼換了，站台憑證也重簽了一張，這就是 zip 裡的東西。UserGuide 寫：「zip 檔中只有『重新簽發新憑證』，沒有金鑰，不能直接安裝到伺服器。」

為什麼一定要原本的金鑰？憑證裡放的是公鑰，伺服器要拿成對的私鑰才能證明自己是憑證上那個網站。依 UserGuide，TWCA 這次用原本的憑證申請檔（CSR）重簽，所以新憑證對應的還是當初那把私鑰；私鑰在你這邊的哪裡，TWCA 的文件答不了，下一節講怎麼找。

部署頁另外提醒兩件事。有把憑證鏈寫進 App 或主機的，要提早部署新鏈，機制見 Android〈[Network security configuration](https://developer.android.com/privacy-and-security/security-config)〉。新鏈不再支援 clientAuth，也就是伺服器反過來跟瀏覽器要憑證，有用到的要另外向 TWCA 申請 AP 憑證，說明見 Tomcat〈[SSL/TLS Configuration How-To](https://tomcat.apache.org/tomcat-11.0-doc/ssl-howto.html)〉。不確定自家有沒有，問當初做 App 或系統的人。

## 先找三樣東西：伺服器、登入帳號、原本的金鑰

### 伺服器在哪裡

憑證要裝在對外收 HTTPS 的那台機器上，收通知信的個人電腦只是跑工具的地方。那台機器可能在自家機房、主機代管商、雲端帳號裡，或是外包廠商架的。通知信寄給原申請人，zip 檔名是統一編號，先問當初是誰申請的；再看網站每月付費給誰。網域 DNS 指向誰的機器也是線索，沒有網域後台帳號就跳過。Tomcat 這類程式若排在 Apache 或 IIS 後面，處理 SSL 的是前面那台，Tomcat 文件有寫。網站前面若有 CDN 或負載平衡器終止 TLS，瀏覽器看到的是它的憑證。受影響的 TWCA 憑證可能在這一層、在後面的來源站，或兩邊都有。這兩段連線差在哪裡，見 Cloudflare〈[SSL/TLS concepts](https://developers.cloudflare.com/ssl/concepts/)〉。不確定有沒有這一層就先往下做，「伺服器是哪一種」那節有時看得出來。

### 誰能登入

TWCA 的工具在你自己的電腦上跑，合併出新檔；把新檔裝上去要有人能登入伺服器：Windows 要遠端桌面或 IIS 管理員的權限，Linux 要有 SSH 帳號加上改設定、重啟服務的權限。單位裡沒人有這些，先找當初的管理員、外包廠商或代管商。若由外包維護，先確認對方是否仍有管理權限。這一步沒解，憑證檔準備得再齊也裝不上。先告訴主管，再決定要不要繼續準備檔案。

### 原本的金鑰

UserGuide 接受三種檔案，手上有哪一種就用哪一種：

- `.key`（有時是 `.pem`）：當初產生 CSR 時一起產生的金鑰檔。
- `.pfx` 或 `.p12`：IIS、Windows 常見，檔案裡必須含原本的金鑰。
- `.jks` 或 `.keystore`：Java、Tomcat 的金鑰庫，同樣必須含原本的金鑰。

去哪裡找，看伺服器種類：

- Nginx：請能登入的人在伺服器上（不是收信的電腦上）打 `grep -r ssl_certificate_key /etc/nginx/`，那一行指著的檔就是私鑰。
- Apache：設定裡 `SSLCertificateKeyFile` 指著的檔就是私鑰。
- IIS：私鑰在 Windows 憑證存放區裡，沒有獨立檔案，要匯出含私鑰的 PFX 並設密碼，步驟見 Microsoft〈[Export a certificate with its private key](https://learn.microsoft.com/en-us/windows-server/identity/ad-cs/export-certificate-private-key)〉（本文沒有 Windows 環境，未實測）；沒人做過就把這份文件交給代管商一起做。
- Tomcat：`server.xml` 裡 `certificateKeystoreFile` 指著的 JKS 或 PKCS12 檔。

幾種常見狀況：

- 手上只有 `.cer` 或 `.crt`：那是憑證檔，沒有私鑰，UserGuide 的錯誤訊息「檔案中找不到私鑰」就是指這個。
- 密碼忘了：UserGuide 要求用 PFX、JKS 的人準備舊檔密碼，`.key` 當初沒設就不用。密碼遺失，UserGuide 說請洽系統管理員，也就是前面找的那些人；OpenSSL 文件裡沒有把忘掉的密碼算回來的步驟。
- 還沒找到、也不確定是不是已經遺失（包括密碼問不到人）：先問管理員或維護廠商，確認新憑證正常運作前，舊檔一律不要刪。
- 確定原金鑰遺失：UserGuide 說本次沿用原金鑰，沒有原金鑰就用不了新憑證，請聯絡 TWCA 客服，改以新金鑰產生的 CSR 重新申請，要時間，越早確認越好。

### 伺服器是哪一種

看原本的檔案類型大致猜得到。UserGuide 把 PFX 對應到 IIS、Windows Server、Exchange 與 F5、FortiGate 等設備，JKS 對應到 Tomcat、WebLogic、WebSphere、JBoss 等 Java 系統，PEM 對應到 Nginx 與 Apache 2.4.8 以上。要從外面看，在自己的電腦打開終端機跑下面這行（`www.example.test` 換成自己的網址），看回應裡有沒有寫伺服器種類：

```bash
curl -sI https://www.example.test/ | grep -i '^server:'
```

實測（curl 8.7.1）：TWCA 官網回 `Server: Apache`，數發部網站回 `server: cloudflare`，中華郵政網站沒有回這個欄位。`cloudflare` 這類值代表前面有 CDN，看不出後面的伺服器；沒有這個欄位也可能是連線本身出錯，`-s` 會把錯誤訊息藏起來。看不出來就回頭問人。

## 路線 A：Windows 電腦加 TWCA 置換工具

這條路是 TWCA 提供的，以下依 UserGuide 整理。本文沒有 Windows 環境，工具本身沒有實測。

準備三樣：通知信的 zip（整包存到電腦，不用解壓縮）、舊的金鑰或憑證檔（上面三種擇一）、舊檔密碼。CertReplaceTool.zip 和 UserGuide 從[部署頁](https://twiddemo.twca.com.tw/acme/replace_cert.html)下載，和通知信的 zip 是兩個不同的檔。CertReplaceTool.zip 完整解壓縮到任一資料夾，雙擊 `CertReplaceTool.exe`。出現「Windows 已保護您的電腦」時，UserGuide 說點「其他資訊」再「仍要執行」。這是 Microsoft SmartScreen 的提示，由來見〈[SmartScreen reputation](https://learn.microsoft.com/en-us/windows/apps/package-and-deploy/smartscreen-reputation)〉。執行前先確認 exe 是從 TWCA 部署頁下載的。UserGuide 表示工具完全在本機執行，不會上傳任何檔案或密碼，這是 UserGuide 的聲明，本文沒有驗證。

畫面由上而下五個步驟：

1. 選通知信的 zip。畫面會顯示統一編號（zip 檔名）、公司名稱、網域、有效期間與簽發 CA，確認是自家網站，不對就停下來聯絡 SSLCC@twca.com.tw。
2. 三擇一選舊檔，輸入舊檔密碼，`.key` 沒密碼可留空；JKS 內的私鑰另有密碼時，轉換中會再跳窗問。輸出 PEM 時工具會檢查金鑰與新憑證是否成對。
3. 根憑證。UserGuide 說系統管理員要求「完整憑證鏈（含根憑證）」時才選，選錯可按「清除」；沒人要求就不用選，伺服器一般不必送根憑證，瀏覽器的信任庫裡就有。
4. 輸出格式與新檔密碼。原本用 PFX 就選 PFX，JKS 就選 JKS，Nginx 和 Apache 選 PEM。PEM 是站台憑證加中繼的單一檔（fullchain），不含金鑰，不需要密碼。PFX 與 JKS 的新檔密碼至少 6 個字元，輸入兩次，可按「同舊檔密碼」，安裝時會用到。PFX 的加密方式由工具決定：舊檔是 PFX 就沿用，舊檔是 `.key` 或 JKS 則「使用與 Windows 預設相同且相容舊版 Windows 的方式」。
5. 存檔位置，預設和 zip 同一資料夾。按「開始轉換」，工具會檢查金鑰與新憑證是否成對、憑證鏈是否完整，產生後重新讀取確認。成功畫面顯示新檔位置、憑證名稱、有效期間與憑證鏈，JKS 的別名（alias）要用畫面上顯示的名稱。

轉換完成後，舊的金鑰、PFX、JKS 保留，確認新憑證正常前不要刪。新檔和密碼交給裝伺服器的人；含私鑰的 PFX 或 JKS 先講好交給誰、怎麼交，不要用公開群組或一般信件寄。

安裝方式 UserGuide 也有寫，四項都在伺服器上做，不是在跑工具的個人電腦上。若是別人登入，就把新檔、密碼和這四項一起交出去：

- IIS：IIS 管理員的「伺服器憑證」匯入新 PFX，再到網站的「繫結」把 https 改用新憑證，匯入 PFX 的步驟見 Microsoft〈[Import a Server Authentication Certificate](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/deployment/import-a-server-authentication-certificate-to-the-default-web-site)〉，HTTPS 繫結的畫面見〈[How to Set Up SSL on IIS](https://learn.microsoft.com/en-us/iis/manage/configuring-security/how-to-set-up-ssl-on-iis)〉。
- Nginx：`ssl_certificate` 改為工具產生的 fullchain.pem，`ssl_certificate_key` 沿用原本的 `.key` 不用換，`nginx -t` 通過後 `nginx -s reload`，實測輸出見下面「Nginx」一節。
- Apache 2.4.8 以上：`SSLCertificateFile` 改為「憑證 CN_fullchain.pem」，`SSLCertificateKeyFile` 不用換，原本若有 `SSLCertificateChainFile` 務必註解掉，這個指令 2.4.8 起已淘汰，見 Apache〈[mod_ssl](https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslcertificatechainfile)〉。
- Tomcat：`server.xml` 裡的 keystore 指向新 JKS 或 PFX，更新密碼後重新啟動，alias 用成功畫面上的名稱，設定項見 Tomcat〈[HTTP Connector](https://tomcat.apache.org/tomcat-11.0-doc/config/http.html)〉。

## 路線 B：沒有 Windows，或想用指令自己做

macOS 內建 LibreSSL（`/usr/bin/openssl`），Linux 多半有 OpenSSL。下面的 openssl 指令在自己的電腦上打：打開終端機，進到一個新的空目錄。改 Nginx 或 Apache 是後面的事，要登入伺服器才做。這一節整理用 OpenSSL 比對金鑰、轉成 PEM、組憑證鏈與做 PFX，JKS 不在實測範圍，需要 JKS 就回路線 A 用 TWCA 的工具。標明「實測」的指令與輸出，是 2026 年 11 月 5 日 03:48 到 04:26 在 macOS（LibreSSL 3.3.6、Homebrew OpenSSL 4.1.0）與 Ubuntu（OpenSSL 3.0.13、nginx 1.24.0）跑出來的；站台憑證與金鑰是測試 CA 簽的模擬檔，TWCA 的中繼憑證是部署頁下載的真檔。

### 先準備：新的工作目錄與備份

正式動手前先做三件事，這是一般做法，沒有逐條實測：

- 開一個新的空目錄放這次的檔案，不要在伺服器現用的憑證目錄裡改。
- 現用的憑證檔、金鑰檔與設定檔各複製一份，記下原本路徑，出問題才換得回去。
- 原金鑰只讀不寫：下面的指令都只讀取它，新產生的檔案一律用新檔名，不覆蓋原檔。

想先演練的，在另一個空目錄用這支腳本產生測試檔：`new.crt`、`server.key`，和一把配錯的 `other.key`。腳本會產生新金鑰，只能在演練目錄裡跑，不要在放原金鑰的目錄執行：

```sh
#!/bin/sh
# Practice files only: a test CA, a test site certificate and keys. Not for production.
set -eu
O="${OPENSSL:-openssl}"
$O req -x509 -newkey rsa:2048 -nodes -keyout root.key -out root.pem -days 30 -subj "/CN=Test Root" 2>/dev/null
$O req -newkey rsa:2048 -nodes -keyout int.key -out int.csr -subj "/CN=Test Intermediate" 2>/dev/null
printf 'basicConstraints=critical,CA:true\nkeyUsage=critical,keyCertSign,cRLSign\n' > ca.ext
$O x509 -req -in int.csr -CA root.pem -CAkey root.key -CAcreateserial -out int.pem -days 30 -extfile ca.ext 2>/dev/null
$O req -newkey rsa:2048 -nodes -keyout server.key -out server.csr -subj "/CN=www.example.test" 2>/dev/null
printf 'subjectAltName=DNS:www.example.test\nextendedKeyUsage=serverAuth\n' > leaf.ext
$O x509 -req -in server.csr -CA int.pem -CAkey int.key -CAcreateserial -out new.crt -days 30 -extfile leaf.ext 2>/dev/null
$O genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out other.key 2>/dev/null
```

實測時在 `mktemp -d` 開出的空目錄執行，跑完多了 `new.crt`、`server.key`、`other.key`、`int.pem`、`root.pem` 等檔案。演練時直接用這些檔名；正式操作時先把通知信的 zip 解開，`new.crt` 改成裡面新憑證的檔名，`server.key` 改成原金鑰的路徑。新憑證的檔名和它是 DER 還是 PEM，TWCA 的文件沒寫，用下一節確認。

### 把要串進憑證鏈的檔案都轉成 PEM

憑證檔有兩種常見編碼：PEM 是文字檔，開頭是 `-----BEGIN CERTIFICATE-----`；DER 是二進位檔。副檔名看不出差別：部署頁的五個 `.cer` 裡，`TWCA CYBER Root CA.cer` 是 DER，其他四個是 PEM；zip 裡那張新憑證是哪一種，TWCA 的文件沒寫（需驗證）。

工具版本不同反應也不同。實測時 OpenSSL 4.1.0 不指定格式也能讀這個 DER 檔，明確指定 `-inform PEM` 才讀不出來；LibreSSL 3.3.6 不加 `-inform DER` 就直接失敗：

```text
unable to load certificate
```

所以「讀得出來」不等於「是 PEM」。要確認是不是 PEM，用 `-inform PEM` 明確指定去讀，讀得出來才是：

```bash
openssl x509 -inform PEM -in new.crt -noout -subject
```

讀不出來，就當 DER 轉一份 PEM，輸出到新檔名，原檔不動：

```bash
openssl x509 -inform DER -in TWCA_CYBER_Root_CA.cer -out TWCA_CYBER_Root_CA.pem
```

這條在 LibreSSL 3.3.6 與 OpenSSL 4.1.0 實測都轉得出來，轉完再用 `-inform PEM` 讀一次確認。所有要串進憑證鏈的檔案，包括 zip 裡的新憑證，都先確認是 PEM 再用。

### 確認原金鑰和新憑證成對

把憑證裡的公鑰和金鑰算出的公鑰各做一次雜湊，比對兩行：

```bash
openssl x509 -in new.crt -noout -pubkey | openssl sha256
openssl pkey -in server.key -pubout | openssl sha256
```

實測輸出（OpenSSL 4.1.0），兩行相同：

```text
SHA2-256(stdin)= 6de5d1f3996c5975abe0fbc2a51080aa3482bb870ceb02ca95cbad48618bd127
SHA2-256(stdin)= 6de5d1f3996c5975abe0fbc2a51080aa3482bb870ceb02ca95cbad48618bd127
```

拿配錯的 `other.key` 算，第二行變成別的值：

```text
SHA2-256(stdin)= 9fbae34166da61daeeedb1cc43b9b201811acce5c5052570efff6bd7028c94d5
```

LibreSSL 3.3.6 只印雜湊、不印前綴，兩行同樣是：

```text
6de5d1f3996c5975abe0fbc2a51080aa3482bb870ceb02ca95cbad48618bd127
```

兩行相同之前，先確認兩條指令都沒有印錯誤訊息：檔案讀不到時，openssl 會印錯誤，後面的 `sha256` 卻照樣對空內容算出一個值，兩邊還會一樣。實測（OpenSSL 4.1.0，兩個檔都不存在）：

```text
Could not open file or uri for loading certificate from missing.crt: No such file or directory
SHA2-256(stdin)= e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Could not open file or uri for loading private key of key from missing.key: No such file or directory
SHA2-256(stdin)= e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
```

`e3b0c442` 開頭的值是空內容的雜湊，看到它就表示前一步失敗，兩行相同也不算成對。兩行不同，表示這把金鑰和 zip 裡的憑證對不上，可能是別的網站的金鑰，或 zip 不是這次通知信的附件。`.key` 有密碼時，`openssl pkey` 會停下來問，輸入時畫面不顯示字是正常的，打完按 Enter，後面問 PFX 密碼時也一樣。

手上只有舊 PFX 的，不必把私鑰取出來。這次換發沿用原金鑰，舊 PFX 裡的憑證和新憑證的公鑰應該相同，比對這兩個就好：

```bash
openssl pkcs12 -in old.pfx -nokeys -clcerts | openssl x509 -noout -pubkey | openssl sha256
openssl x509 -in new.crt -noout -pubkey | openssl sha256
```

第一條會先問 PFX 密碼。實測時用同一把測試金鑰做了一個 `old.pfx`，以 `-passin` 帶入密碼，兩行都是下面這個值（這次演練重新產生了金鑰，所以和上面的雜湊不同）：

```text
SHA2-256(stdin)= ec23ca974da08575800ea508b1ca26bd7ee86b0c97b3b28a5af2ce696d0041e0
```

### 組 fullchain

先看新憑證是誰簽的，決定要接哪一張中繼：

```bash
openssl x509 -in new.crt -noout -issuer
```

印出 TWCA SSL Certification Authority 就接一般 SSL 那張，TWCA EVSSL Certification Authority 就接 EV 那張。後面的順序照已經換好新鏈的網站實際送出的內容排：2026 年 11 月 5 日 03:49 用 `openssl s_client -showcerts` 看 www.twca.com.tw、www.moda.gov.tw、www.post.gov.tw，三站都送 4 張。下面是 www.moda.gov.tw 的實測輸出（OpenSSL 4.1.0，只留 `s:` 與 `i:` 行）：

```text
 0 s:C=TW, ST=Taiwan, L=Taipei, O=Ministry of Digital Affairs, CN=*.moda.gov.tw
   i:C=TW, O=TAIWAN-CA, CN=TWCA SSL Certification Authority
 1 s:C=TW, O=TAIWAN-CA, CN=TWCA SSL Certification Authority
   i:C=TW, O=TAIWAN-CA, CN=TWCA CYBER Root CA G3
 2 s:C=TW, O=TAIWAN-CA, CN=TWCA CYBER Root CA G3
   i:C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA CYBER Root CA
 3 s:C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA CYBER Root CA
   i:C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA Global Root CA
```

第一張是站台憑證。三站都沒送 TWCA Global Root CA 本身，它在瀏覽器的信任庫裡，macOS 的系統根憑證庫就有。所以 fullchain 依序是站台憑證、SSL 或 EVSSL CA、G3 Cross Cert、CYBER Root CA 四張，全部先轉成 PEM。先從部署頁把要用的中繼下載到這個目錄，DER 的照上一節轉成 PEM。下面的檔名是部署頁檔名把空格換成底線、副檔名改成 `.pem`，實際檔名不同就用實際的，輸出用新檔名：

```bash
cat new.crt TWCA_SSL_Certification_Authority.pem TWCA_CYBER_Root_CA_G3_Cross_Cert.pem TWCA_CYBER_Root_CA.pem > fullchain-new.pem
openssl crl2pkcs7 -nocrl -certfile fullchain-new.pem | openssl pkcs7 -print_certs -noout
```

第二條會列出檔案裡每張憑證的 subject 與 issuer。實測時第一張是測試站台憑證，所以 issuer 是 Test Intermediate；正式操作時這裡應該是 TWCA SSL 或 EVSSL Certification Authority，四張依序由下一張簽發：

```text
subject=CN=www.example.test
issuer=CN=Test Intermediate

subject=C=TW, O=TAIWAN-CA, CN=TWCA SSL Certification Authority
issuer=C=TW, O=TAIWAN-CA, CN=TWCA CYBER Root CA G3

subject=C=TW, O=TAIWAN-CA, CN=TWCA CYBER Root CA G3
issuer=C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA CYBER Root CA

subject=C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA CYBER Root CA
issuer=C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA Global Root CA
```

這份清單只說明檔案裡有哪幾張、順序如何，不代表驗證通過，驗證用 `openssl verify`。演練檔只有一張中繼，實測指令與輸出：

```bash
openssl verify -CAfile root.pem -untrusted int.pem new.crt
```

```text
new.crt: OK
```

真的 TWCA 鏈也驗過：Global Root 當信任根，CYBER Root CA（PEM）和 G3 Cross Cert 當中繼，驗 SSL CA 那張，OpenSSL 4.1.0 與 LibreSSL 3.3.6 的實測輸出都是：

```bash
cat TWCA_CYBER_Root_CA.pem TWCA_CYBER_Root_CA_G3_Cross_Cert.cer > untrusted.pem
openssl verify -CAfile TWCA_Global_Root_CA.cer -untrusted untrusted.pem TWCA_SSL_Certification_Authority.cer
```

```text
TWCA_SSL_Certification_Authority.cer: OK
```

驗自己的站台憑證時，把 SSL 或 EVSSL CA 也加進 `untrusted.pem`，最後一個參數換成新憑證，成功時預期會印 `OK`。本文手上沒有真的 TWCA 站台憑證，這一步未實測。

### Nginx

登入伺服器後先找現用的設定在哪一行，下面這行實測時是對測試設定檔跑的，路徑以印出來的為準：

```bash
grep -r ssl_certificate_key /etc/nginx/
```

把 `fullchain-new.pem` 複製到伺服器，更新憑證路徑，私鑰路徑維持指向原檔，下面的路徑只是例子：

```nginx
ssl_certificate     /etc/nginx/ssl/fullchain-new.pem;
ssl_certificate_key /etc/nginx/ssl/server.key;
```

改完先 `nginx -t`。金鑰配錯時，nginx 1.24.0 實測會直接擋下來：

```text
[emerg] ... SSL_CTX_use_PrivateKey(".../other.key") failed (SSL: error:05800074:x509 certificate routines::key values mismatch)
nginx: configuration file .../nginx.conf test failed
```

配對時：

```text
nginx: the configuration file .../nginx.conf syntax is ok
nginx: configuration file .../nginx.conf test is successful
```

`nginx -t` 通過才 `nginx -s reload`，實測 reload 後 error log 只有一行 `signal process started`；沒過就不要 reload，改回備份的設定。nginx 文件提醒私鑰檔要限制權限，但 master process 得讀得到。

### IIS：做一個 PFX

IIS 要的是含私鑰的 PFX。先把三張中繼串成一個檔，再把金鑰、新憑證和中繼包在一起，過程會問新檔密碼：

```bash
cat TWCA_SSL_Certification_Authority.pem TWCA_CYBER_Root_CA_G3_Cross_Cert.pem TWCA_CYBER_Root_CA.pem > intermediates.pem
openssl pkcs12 -export -inkey server.key -in new.crt -certfile intermediates.pem -out new.pfx
```

實測用演練檔跑（`-certfile int.pem`）。OpenSSL 4.1.0 預設的加密方式，用 `openssl pkcs12 -in new.pfx -info -noout` 看，實測輸出的前幾行：

```text
MAC: sha256, Iteration 2048
MAC length: 32, salt length: 16
PKCS7 Encrypted data: PBES2, PBKDF2, AES-256-CBC, Iteration 2048, PRF hmacWithSHA256
```

部分 Windows 版本匯入不了這種 PFX。Microsoft 的疑難排解文件寫，受影響的 Windows 與 Windows Server 不支援以 AES256-SHA256 加密的 PFX，匯入時會出現類似「The password you entered is incorrect」的訊息，因應方式是改用 TripleDES-SHA1，較新的版本兩種都支援；那頁沒有逐一列出受影響的版本，黑暗執行緒的部落格（個人技術 blog，2024 年 5 月 11 日）記錄的是 Windows Server 2012 R2 與 2016。先確認自家 Windows 的版本，匯入出現這個錯誤再改做 3DES 版本：

```bash
openssl pkcs12 -export -inkey server.key -in new.crt -certfile intermediates.pem -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg sha1 -out new-legacy.pfx
```

用演練檔實測做得出來，`-info` 的前幾行：

```text
MAC: sha1, Iteration 2048
MAC length: 20, salt length: 16
PKCS7 Encrypted data: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 2048
```

本文沒有 Windows 可測，兩種 PFX 都沒有實際匯入過；匯入與繫結照路線 A 的 IIS 那條。

反過來，只有含私鑰的舊 PFX、又要給 Nginx 用，才需要把金鑰取出來。`-nodes` 會輸出沒加密的私鑰，所以先限制權限，輸出到新檔名：

```bash
(umask 077; openssl pkcs12 -in old.pfx -nocerts -nodes -out old-key.pem)
```

實測（macOS、OpenSSL 4.1.0）產生的檔案權限是 `-rw-------`，只有自己能讀，算出的公鑰雜湊和原金鑰一樣。取出的金鑰放在限制存取的目錄，用完的副本刪掉；只是要比對成對，用上面「手上只有舊 PFX」那兩行就夠。

### Apache 與 Tomcat

Apache 2.4.8 以上照路線 A 那條改，`SSLCertificateFile` 指向 `fullchain-new.pem`，改完先跑 `apachectl configtest`（見 Apache〈[apachectl](https://httpd.apache.org/docs/2.4/programs/apachectl.html)〉），通過才 reload。Apache 文件寫私鑰檔應只有 root 可讀，見〈[SSLCertificateKeyFile](https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslcertificatekeyfile)〉。Tomcat 支援 PKCS12，使用前要依現場的 Tomcat 與 Java 版本核對 keystore 型別、密碼與 alias，見 Tomcat〈[SSL/TLS Configuration How-To](https://tomcat.apache.org/tomcat-11.0-doc/ssl-howto.html)〉。`server.xml` 的 keystore 型別、密碼與 `certificateKeyAlias` 依〈[HTTP Connector](https://tomcat.apache.org/tomcat-11.0-doc/config/http.html)〉核對，新做的 PFX 不一定有原設定的 alias。Apache 與 Tomcat 本文都沒有跑過，keytool 做 JKS 也沒測。不確定就把新檔、密碼和 alias 交給維護的人，reload 或重啟的指令依各家文件。

## 確認換好了

- 瀏覽器開網站，點網址列的鎖頭，看有效期間是不是新憑證的，這是 UserGuide 給的檢查；沒有鎖頭就跳過，改做下面幾項。
- 到 TWCA 的 SSL 憑證檢測頁輸入網站名稱查一次，[部署頁](https://twiddemo.twca.com.tw/acme/replace_cert.html)有連結。
- 從外面驗證伺服器送出的鏈，並確認網站名稱對得上：`-servername` 只告訴伺服器要哪個網站，`-verify_hostname` 才檢查憑證上的名稱。下面是對 www.moda.gov.tw 的實測指令與輸出，查自己的網站時把三處網址換成自己的網域：

```bash
openssl s_client -connect www.moda.gov.tw:443 -servername www.moda.gov.tw -verify_hostname www.moda.gov.tw </dev/null
```

實測（OpenSSL 4.1.0，2026 年 11 月 5 日 04:26）輸出的最後是：

```text
Verification: OK
Verify return code: 0 (ok)
```

故意把 `-verify_hostname` 換成別的名稱，同一個站回的是：

```text
Verify return code: 62 (hostname mismatch)
```

LibreSSL 3.3.6 對同一站也回 `Verify return code: 0 (ok)`。這幾條指令都沒有檢查撤銷狀態。

- 確認上線的是新憑證：把網站送出的第一張憑證和 zip 裡的新憑證各印出序號比對，www.moda.gov.tw 換成自己的網域，`new.crt` 換成 zip 裡的新憑證：

```bash
openssl s_client -connect www.moda.gov.tw:443 -servername www.moda.gov.tw </dev/null 2>/dev/null | openssl x509 -noout -serial -enddate -issuer
openssl x509 -in new.crt -noout -serial -enddate -issuer
```

數發部網站的實測輸出：

```text
serial=47EA00000009B606E581A8DE645A11FE
notAfter=Dec 16 15:59:59 2026 GMT
issuer=C=TW, O=TAIWAN-CA, CN=TWCA SSL Certification Authority
```

兩條印出的 serial 相同，才表示新憑證真的上線了。Ubuntu 的 nginx 演練裡，網站送出的 serial 和 `new.crt` 實測一致。

- 演練環境（127.0.0.1:8443，以 `-CAfile root.pem` 指定測試根）裡，只放站台憑證、沒放中繼時回 `Verify return code: 21 (unable to verify the first certificate)`，放了 fullchain 回 `0 (ok)`：

```text
 0 s:CN = www.example.test
Verify return code: 21 (unable to verify the first certificate)
```

```text
 0 s:CN = www.example.test
   i:CN = Test Intermediate
 1 s:CN = Test Intermediate
   i:CN = Test Root
Verify return code: 0 (ok)
```

- 網站前面有 CDN 或負載平衡器、由它終止 TLS 的，瀏覽器和 `s_client` 看到的都是前端那張憑證。實測時數發部網站回應標頭的 Server 是 `cloudflare`，就是這種情況。前端連到來源站若另有 HTTPS，來源站用的是不是受影響的憑證要另外查，從外面確認不了兩段。
- App 有綁憑證鏈的，用新版 App 連一次；系統用到 clientAuth 的，照部署頁找 TWCA 問 AP 憑證。這兩種本文沒有測。

## 出錯的時候

錯誤訊息出現的地方有三個：TWCA 工具的畫面、伺服器自己的記錄、瀏覽器顯示給訪客看的頁面，三處的字不一樣，打客服前先弄清楚錯誤出現在哪裡。

工具畫面的訊息，UserGuide 第 5 節有對照：

- 「舊金鑰與 zip 檔內的新憑證不相符」：選到別的網站的金鑰或舊檔，或 zip 不是這次通知信的附件。確認網域相同，或改用伺服器上目前使用中的 PFX、JKS。
- 「舊檔密碼錯誤」：確認大小寫、全形半形，密碼遺失照「原本的金鑰」那節處理，舊檔不要刪。
- 「此金鑰檔有密碼保護」：在「舊檔密碼」輸入 `.key` 的密碼。
- 「檔案中找不到私鑰」：選到憑證檔（`.cer`、`.crt`），沒選到金鑰檔。
- 「舊檔中沒有私鑰」：這個 PFX 或 JKS 只有憑證，改選伺服器上正在使用、含金鑰的那一份。
- 「zip 檔內找不到任何憑證檔」：確認選的是通知信的原始附件。
- 「根憑證與此憑證鏈不符」：步驟 3 選錯檔。

伺服器端的訊息：

- Nginx `key values mismatch`：金鑰與 `ssl_certificate` 檔裡第一張憑證不成對。可能是金鑰配錯（回到「確認原金鑰和新憑證成對」比一次），也可能是 fullchain 的順序排錯，第一張必須是站台憑證。
- `Verify return code: 21`：本次測試裡出現這個碼，是因為伺服器只送了站台憑證、沒送中繼，常見情況是 `ssl_certificate` 還指著舊的單張憑證，或 fullchain 沒組好。其他情況也可能出現同一個碼，要配合完整訊息判斷。
- Nginx 其他 `[emerg]`：`nginx -t` 會印出是哪一個檔，記錄檔位置見 nginx〈[error_log](https://nginx.org/en/docs/ngx_core_module.html#error_log)〉；Apache 的記錄位置見〈[Log Files](https://httpd.apache.org/docs/2.4/logs.html#errorlog)〉。
- Tomcat 啟動時若出現 keystore 密碼或 alias 錯誤，核對 `server.xml` 的 keystore 設定，見 Tomcat〈[SSL/TLS Configuration How-To](https://tomcat.apache.org/tomcat-11.0-doc/ssl-howto.html)〉。IIS 說憑證沒有私鑰，要匯入的是含私鑰的 PFX，見 Microsoft〈[IIS 憑證疑難排解](https://learn.microsoft.com/en-us/troubleshoot/developer/webapps/iis/www-authentication-authorization/troubleshooting-ssl-related-issues-server-certificate)〉。

要給客服或幫忙的人：網域、zip 檔名、伺服器種類與版本、做到哪一步、錯誤訊息的原文、記錄檔裡那幾行；不要附上私鑰、密碼或含私鑰的檔案，SSL Labs 的部署指南要私鑰少給人碰。客服收不收檔案、會不會代裝，TWCA 的文件沒寫，這篇也不猜，打電話時直接問。

## 打客服前寫在同一頁

- 網域與 zip 檔名（統一編號）。
- 網站放在哪、誰能登入、外包廠商或代管商的聯絡方式。
- 原本的金鑰是哪一種檔案、放在哪、有沒有密碼。
- 伺服器或設備的種類與版本。
- 做到哪一步、哪一處出現什麼錯誤訊息（原文）。
- 有沒有 App 綁憑證鏈、有沒有用到用戶端驗證（也就是前面的 clientAuth）。

聯絡 （02）2370-8886 分機 9 或 SSLCC@twca.com.tw 時，已知的直接說，還沒確認的註明還沒確認。

## 還沒釐清的事

- 11 月 6 日 00:00 的時區、要廢止的舊中繼名單與指紋，公告仍沒寫。
- zip 裡新憑證的檔案格式（DER 或 PEM）與檔名，TWCA 文件沒有公開說明，可以用「把要串進憑證鏈的檔案都轉成 PEM」那節的方法確認。
- 在 macOS 或 Linux 執行置換工具的方式，部署頁與 UserGuide 都沒提。
- 還有多少張沒換：TWCA 11 月 5 日公告說，截至當天 10:30，政府、金融及其他產業已有超過 85% 的客戶網站完成更新；金管會說金融機構約有 4,190 筆憑證，當天 14:30 約 95% 完成；數發部的政府端數字仍停在 11 月 2 日晚間的 926 張。民間企業沒有單獨的數字。
- 要廢止的是哪些序號、自己那張在不在裡面，TWCA 11 月 5 日公告沒寫。
- CA 憑證序號事件的完整報告，TWCA 在 [Bugzilla 2087236 Comment 3](https://bugzilla.mozilla.org/show_bug.cgi?id=2087236#c3) 承諾於 11 月 12 日 19:00 UTC 前提交。

## 補充筆記

- 通知信的 zip 只有新憑證，要配上當初產生 CSR 的原金鑰，還要有人能登入伺服器，缺一樣都裝不上。
- 原金鑰的位置看伺服器種類：Nginx 看 `ssl_certificate_key`，Apache 看 `SSLCertificateKeyFile`，IIS 從憑證存放區匯出含私鑰的 PFX，Tomcat 看 `server.xml` 的 keystore。
- 比對公鑰雜湊可確認金鑰和新憑證是否成對，但兩條指令都要沒有錯誤訊息，`e3b0c442` 開頭是空內容的雜湊；fullchain 依序接站台憑證、SSL 或 EVSSL CA、G3 Cross Cert、CYBER Root CA，全部先轉成 PEM。
- 動手前先備份現用檔案，新檔一律用新檔名；Nginx 配錯金鑰會在 `nginx -t` 報 key values mismatch，通過才 reload。Apache、IIS、Tomcat 的安裝本文沒有實測，照 UserGuide 的四條與各家官方文件做。
- 確認時用 `-verify_hostname` 檢查名稱，並比對網站送出的 serial 和新憑證相同；給 IIS 的 PFX 預設是 AES，部分 Windows 版本要 3DES，本文沒有在 Windows 上測。
- 錯誤訊息分工具畫面、伺服器記錄、瀏覽器頁面三處；給客服的資料裡永遠不含私鑰與密碼。

## 延伸閱讀

- [TWCA〈TWCA SSL 憑證更新進度暨憑證廢止公告〉](https://www.twca.com.tw/news_detail/86016103-e8c0-4f4e-806b-654ea2264d04)：2026 年 11 月 5 日的業者公告，更新進度與網站憑證廢止時程是 TWCA 自己的說法。
- [中央社〈TWCA 憑證限期換發 金管會：金融業完成更新進度達 95%〉](https://www.cna.com.tw/news/afe/202611050296.aspx)：2026 年 11 月 5 日，金管會說明金融業的憑證數與進度，新聞轉述。
- [TWCA〈TWCA SSL 更換憑證公告〉](https://ssl.twca.com.tw/news_detail/5f3395bf-bef6-4b40-b922-ceac4b06bf53)：2026 年 10 月 31 日，原中繼憑證 11 月 6 日 00:00 前廢止的一手公告。
- [TWCA〈接軌國際憑證規範 TWCA 全面啟動網站憑證升級更新作業〉](https://twca.com.tw/news_detail/f18a3be8-5513-4ed5-b8f9-c5d468c82aec)：2026 年 11 月 2 日的業者公告，換證原因是 TWCA 自己的說法。
- [TWCA〈TLS/SSL 憑證鏈更新〉部署頁](https://twiddemo.twca.com.tw/acme/replace_cert.html)：新憑證鏈五個檔、clientAuth 提醒、憑證置換工具與 UserGuide 下載、SSL 憑證檢測頁連結。
- [數位發展部新聞稿](https://web.moda.gov.tw/press/press-releases/21226)：2026 年 11 月 2 日，政府機關的憑證數量與當晚進度。
- [nginx〈Configuring HTTPS servers〉](https://nginx.org/en/docs/http/configuring_https_servers.html#chains)：憑證鏈的順序、`ssl_certificate` 與私鑰權限，以及 key values mismatch 的成因。
- [nginx `error_log`](https://nginx.org/en/docs/ngx_core_module.html#error_log)：錯誤記錄的位置與預設值。
- [Apache mod_ssl `SSLCertificateChainFile`](https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslcertificatechainfile)：2.4.8 起淘汰，中繼改放 `SSLCertificateFile`。
- [Apache〈Log Files〉](https://httpd.apache.org/docs/2.4/logs.html#errorlog)：ErrorLog 的位置。
- [Microsoft〈Import a Server Authentication Certificate〉](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/deployment/import-a-server-authentication-certificate-to-the-default-web-site)：在 IIS 管理員的「伺服器憑證」匯入 PFX 的步驟。
- [Microsoft〈How to Set Up SSL on IIS〉](https://learn.microsoft.com/en-us/iis/manage/configuring-security/how-to-set-up-ssl-on-iis)：伺服器憑證與繫結的畫面；[certutil](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/certutil) 的 `-importPFX`；[IIS 憑證疑難排解](https://learn.microsoft.com/en-us/troubleshoot/developer/webapps/iis/www-authentication-authorization/troubleshooting-ssl-related-issues-server-certificate)。
- [Microsoft〈SmartScreen reputation〉](https://learn.microsoft.com/en-us/windows/apps/package-and-deploy/smartscreen-reputation)：「Windows 已保護您的電腦」提示的由來。
- [Apache Tomcat〈SSL/TLS Configuration How-To〉](https://tomcat.apache.org/tomcat-11.0-doc/ssl-howto.html)：JKS 與 PKCS12、alias、clientAuth 的說明。
- [OpenSSL `openssl-pkcs12`](https://docs.openssl.org/master/man1/openssl-pkcs12/)、[`openssl-x509`](https://docs.openssl.org/master/man1/openssl-x509/)、[`openssl-s_client`](https://docs.openssl.org/master/man1/openssl-s_client/)、[`openssl-req`](https://docs.openssl.org/master/man1/openssl-req/)、[format options](https://docs.openssl.org/master/man1/openssl-format-options/)：本文用到的指令。
- [Microsoft〈Can't import an AES256-SHA256-encrypted PFX certificate〉](https://learn.microsoft.com/en-us/troubleshoot/windows-server/certificates-and-public-key-infrastructure-pki/cannot-import-aes256-sha256-encrypted-pfx-certificate)：受影響的 Windows 匯入 AES256-SHA256 PFX 會失敗，因應方式是 TripleDES-SHA1。
- [Microsoft〈Export a certificate with its private key〉](https://learn.microsoft.com/en-us/windows-server/identity/ad-cs/export-certificate-private-key)：從 Windows 匯出含私鑰的憑證。
- [Apache〈apachectl〉](https://httpd.apache.org/docs/2.4/programs/apachectl.html)：`configtest` 設定檢查。
- [Apache Tomcat〈HTTP Connector〉](https://tomcat.apache.org/tomcat-11.0-doc/config/http.html)：keystore 型別、密碼與 `certificateKeyAlias`。
- [OpenSSL〈verification options〉](https://docs.openssl.org/master/man1/openssl-verification-options/)：`-verify_hostname` 等驗證選項。
- [黑暗執行緒〈openssl 匯出 pfx 在 Windows 密碼百敲不過〉](https://blog.darkthread.net/blog/openssl-pfx-windows-issue/)：個人技術 blog，2024 年 5 月 11 日，舊版 Windows 與 AES PFX 的相容問題。
- [SSL Labs〈SSL and TLS Deployment Best Practices〉](https://github.com/ssllabs/research/wiki/SSL-and-TLS-Deployment-Best-Practices)：私鑰保管與憑證鏈完整性。
- [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280#section-6.1.3)：路徑驗證要求憑證在有效期間內且未被撤銷，沒有寬限期。
- [Android〈Network security configuration〉](https://developer.android.com/privacy-and-security/security-config)：App 綁定憑證（pinning）的機制。
- [Cloudflare〈SSL/TLS concepts〉](https://developers.cloudflare.com/ssl/concepts/)：CDN 前端憑證與來源站憑證是兩段連線。
- 〈[去年中華電信，今年 TWCA：中繼憑證 11 月 6 日廢止前該檢查什麼](/posts/twca-intermediate-replacement-what-to-check/)〉：序號熵、Bugzilla 紀錄、從外部檢查伺服器送出的憑證鏈。

> 想法與技術判斷出自 Sheng，和 Claude 一起起草 · 起草 Claude Fable，問題整理與官方文件查詢 Grok，Codex（gpt-6-astra）二審，Claude 補測與修訂，Claude Fable 精簡，Grok 調語氣；標明實測的指令在 macOS（LibreSSL 3.3.6、OpenSSL 4.1.0）與 Ubuntu（OpenSSL 3.0.13、nginx 1.24.0）執行，資料查核至 2026-11-05 04:26；19:30 補查 TWCA 公告與換證進度，指令沒有重跑。