[Server] TLS/SSL憑證(Certificate)指南 – 常用指令|製作CSR

SSL基本指令 | CSR 製作與設定 | 憑證檔案標準編碼格式 | SSL進階指令 | SSL安裝 | 交叉認證

Intro

Public key certificate - 公開金鑰認證 - Wikipedia

認證原理

Chain_Of_Trust

  • 中英文通用名詞:
    • Root certificate:根憑證 (CA:TRUE)
    • Intermediate certificate:中介憑證 / 中繼憑證 (CA:TRUE)
    • End-entity / leaf certificate:終端實體憑證

工具指令

詳細指令的可以參考: The Most Common OpenSSL Commands

申請憑證流程概念:

自產 Server Key 生成 CSR > 上傳至 CA (憑證機構/組織),基於該 CSR 簽署產出憑證,提供下載 > 設定至 Web Server

SSL 基本指令

快速產生自簽 Root CA 憑證(Self-Signed)

  • 一併產生新的 Private Key

    $ openssl req -x509 -nodes -new \
    -days 3650 -sha256 \
    -newkey rsa:4096 -keyout root-ca.key \
    -out root-ca.crt
  • 沿用 Private Key (用於憑證輪替/續期)

    $ openssl req -x509 -nodes -new \
    -days 3650 -sha256 \
    -key root-ca.key \
    -out root-ca-new.crt

執行時會進入互動模式讓你填寫組織與 CN 資訊。

拆分步驟,產生 CSR 與自簽 Root CA 憑證(Self-Signed)

1. 產生 Private Key

$ openssl genrsa -out root-ca.key 4096

密碼保護模式(如用於正式環境 Root CA): openssl genrsa -aes256 -out root-ca.key 4096

2. 產生 CSR/REQ (certificate signing request)

$ openssl req -new -key root-ca.key -out root-ca.csr

執行時會進入互動模式 (Interactive Mode) 讓你填寫組織與 CN 資訊。

若需要加入 Subject Alternative Name (SAN) 多網域等額外資訊,或想避免互動模式以利自動化部署,可撰寫 CSR 設定檔,並透過 -config 參數帶入檔案。

3. 產生自簽署 Root CA 憑證

指令 x509 可以用來將 CSR 產製出 Certificate (憑證),而為了簽署成 CA Certificate 會需要定義 extensions(宣告為 CA 權限,並透過與 CSR 相同的私鑰進行自簽署,即成為 Root CA)

延伸屬性(X509 Extensions)指定方式:

  • 方法 A:直接動態指定內容(擺脫檔案路徑依賴)

    $ openssl x509 -req -days 3650 -sha256 \
    -extfile <(printf "basicConstraints=critical,CA:TRUE\nkeyUsage=critical,cRLSign,keyCertSign\nsubjectKeyIdentifier=hash\nauthorityKeyIdentifier=keyid:always,issuer") \
    -in root-ca.csr -signkey root-ca.key -out root-ca.crt

    Extension 直接喂 config text,以將 certificate 定義為 CA 與設定相關 flags

  • 方法 B:指定來自系統內建的 openssl.cnf(若作業系統預設支援)

    $ openssl x509 -req -days 3650 -sha256 \
    -extfile /etc/ssl/openssl.cnf -extensions v3_ca \
    -in root-ca.csr -signkey root-ca.key -out root-ca.crt

    以上表示去讀取 /etc/ssl/openssl.cnf[v3_ca] 區塊的設定檔
    Linux 完整發行版(如 Ubuntu/CentOS)預設支援此區塊

完整三層式憑證鏈自簽方法:從根憑證到終端部署

1. 產生中間憑證 (Intermediate CA) 的 Private Key 與 CSR

$ openssl genrsa -out intermediate-ca.key 4096
$ openssl req -new -key intermediate-ca.key -out intermediate-ca.csr

2. 使用 Root CA 簽署中間憑證 (Intermediate CA)

$ openssl x509 -req -CAcreateserial -days 1825 -sha256 \
  -CA root-ca.crt -CAkey root-ca.key \
  -extfile <(printf "basicConstraints=critical,CA:TRUE\nkeyUsage=critical,cRLSign,keyCertSign\nsubjectKeyIdentifier=hash\nauthorityKeyIdentifier=keyid:always,issuer") \
  -in intermediate-ca.csr -out intermediate-ca.crt

中間憑證本質上也是 CA(需要有核發別人的權力),因此在簽署時,必須再次注入 CA 的相關延伸屬性(如 CA:TRUE)。

3. 產生終端憑證 (End-Entity Certificate) 的 Private Key 與 CSR

$ openssl genrsa -out server.key 4096
$ openssl req -new -key server.key -out server.csr

4. 使用中間憑證 (Intermediate CA) 簽署終端憑證 (End-Entity Certificate)

$ openssl x509 -req -CAcreateserial -days 365 -sha256 \
  -CA intermediate-ca.crt -CAkey intermediate-ca.key \
  -in server.csr -out server.crt

CSR 製作與設定

生成CSR時需輸入Owner資訊如下:

Country Name (2 letter code) [XX]:  TW
State or Province Name (full name) []:  Taiwan
Locality Name (eg, city) [Default City]:  Taipei
Organization Name (eg, company) [Default Company Ltd]: YIDAS Co., Ltd
Organizational Unit Name (eg, section) []: IT
Common Name (eg, your name or your server's hostname) []: code.yidas.com
Email Address []:myintaer@gmail.com

後續出現的 Extra Attributes(如 challenge password)非必填,可以直接按 Enter 略過

Common Name (CN) 欄位宣告定義

Common Name 是憑證的主體名稱。依據不同的應用場景,設定方式如下:

  1. 單網域 (Single Domain)
    適用於單一特定的完整網域名稱 (FQDN)。
code.yidas.com
  1. 多網域 (Multi-Domain)
    現代資安標準(如 Chrome、Golang HTTPS 規範)要求,不論是單網域、多網域或萬用網域,皆必須將網域綁定於 SAN (Subject Alternative Name) 延伸屬性中,現代瀏覽器已不再依賴 CN 做為網域校驗依據。

    CSR 設定含 SAN 多網域:Certificate(CSR) configuration file
    Multi-Domain SSL Setup with “Subject Alternative Names”

  2. 萬用網域 (Wildcard)
    使用星號 (*) 允許匹配該階層底下的所有子網域。

*.yidas.com

萬用字元 * 僅能匹配當前階層的子網域(如 www.yidas.com),不包含主網域本身 (yidas.com)。實務上建議在 SAN 中將主網域與萬用網域一併列入。

從 Certificate (憑證) 反向還原並匯出為 CSR

利用指令從憑證中複製所有主體身分資訊(Subject/CN),並提供對應的 Private Key(私鑰)來對這份 CSR 進行數位簽署(蓋章驗證):

$ openssl x509 -x509toreq -in root-ca.crt -signkey root-ca.key -out root-ca.csr

憑證檔案標準編碼格式

一般為兩種,分Binary以及Text:

DER (Distinguished Encoding Rules)

  • 檔案內容: 二進位格式
  • 副檔名: .der, .cer

PEM (Privacy Enhanced Mail)

  • 檔案內容: 文字格式 (Base64 with BEGIN & END)
  • 副檔名: .pem, .cert

PEM Wiki: https://en.wikipedia.org/wiki/Privacy-Enhanced\_Mail

副檔名.crt並未定義歸類,一般兩種格式都有混用

憑證檔案其他格式

P7B / PKCS#7

  • 檔案內容: PEM編碼格式 (RFC 2315)
  • 副檔名: .p7b, .p7c, .keystore
  • 說明: 檔案只會包含憑證與中繼憑證,不會包含私密金鑰。主要用來對訊息簽章或加解密。

PKCS#8

  • 檔案內容: PEM編碼格式 (RFC 5958, RFC 5208)
  • 副檔名: .key, .pkcs8.key
  • 說明: 檔案主要包含私密金鑰,且可為一組密碼保護內容

PFX / PKCS#12 (predecessor of PKCS#12)

  • 檔案內容: 二進位格式 (RFC 7292)
  • 副檔名: .pfx, .p12, pkcs12
  • 說明: 檔案中同時包含憑證、中繼憑證、私密金鑰,且為一組密碼保護內容。
# 查看 P12 憑證內容
$ openssl pkcs12 -in mycert.p12 -nodes -passin pass:"password" | openssl x509 -noout -text

# 解包全部轉出至單檔 PEM (全部 X.509 憑證 + PKCS#8 Key)
$ openssl pkcs12 -in example.p12 -out bundle.pem -nodes
# 解包轉出 PKCS#8 Key
$ openssl pkcs12 -in example.p12 -out private-key.pem -nocerts -nodes
# 解包轉出 X.509 終端憑證
$ openssl pkcs12 -in example.p12 -out certificate.pem -clcerts -nokeys

SSL進階指令

檢視 CSR

openssl req -text -noout -verify -in CSR.csr

檢視 CRT (PEM & DER)

openssl x509 -noout -text -in cert.pem

# 檢視DER格式證書
openssl x509 -text -noout -inform DER -in cert.der

# 顯示全部憑證鏈(View full-chain)
openssl crl2pkcs7 -nocrl -certfile full-chain.pem | openssl pkcs7 -print_certs -text -noout

# 檢視Fingerprint
openssl x509 -noout -fingerprint -sha256 -inform pem -in [cert.pem]
openssl x509 -noout -fingerprint -sha1 -inform pem -in [cert.pem]
openssl x509 -noout -fingerprint -md5 -inform pem -in [cert.pem]

可由CA:FALSE欄位辨識憑證是否為終端憑證 Subject Key Identifier為目前憑證指紋、 Authority Key Identifier為上層憑證指紋

檢視與下載目標 Web Server 所提供的憑證

# 顯示 server 提供的 fullchain 憑證資料包含 PEM 內容 (-servername 代表實際訪問使用的 SNI,不填等同於直接用 server IP 訪問)
$ echo | openssl s_client -showcerts -servername example.com -connect example.com:443

# 基於 fullchain 憑證資料,利用 awk 指令工具抓出每張憑證區段並儲存至檔案
$ echo | openssl s_client -showcerts -servername example.com -connect example.com:443 2>/dev/null |
awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/ { print }' > full-chain.pem

# 基於 fullchain 憑證資料,利用 x509 text 檢視,但只會抓第一張終端憑證顯示
$ echo | openssl s_client -showcerts -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -text

# SMTP 支援 SNI
$ echo | openssl s_client -showcerts -starttls smtp -servername mail.example.com -connect mail.example.com:587 2>/dev/null | openssl x509 -noout -text

# FTP Server 尚不支援 TLS SNI,加參數無效果
$ echo | openssl s_client -showcerts -starttls ftp -connect example.com:21 2>/dev/null | openssl x509 -noout -text

驗證

$ openssl verify cert.pem

# 驗證包含中繼憑證
$ openssl verify -untrusted intermediate-cert.pem cert.pem

# 驗證是否為CA簽發
$ openssl verify -CAfile ca-cert.pem -untrusted intermediate-cert.pem cert.pem

# 驗證一把 key 是否配對到一張憑證 (各自取出公鑰再比較)
$ openssl x509 -in certificate.pem -pubkey -noout > cert_pubkey.pem
$ openssl pkey -in privatekey.pem -pubout > key_pubkey.pem
$ diff cert_pubkey.pem key_pubkey.pem

憑證格式轉換

# DER to PEM
openssl x509 -inform der -in certificate.cer -out certificate.pem

# PEM to DER
openssl x509 -outform der -in your-cert.pem -out your-cert.cer

# to PFX(PKCS#12)
openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.cert -certfile CACert.cert

SSL安裝

SSL提供商檔案(TWCA多中繼憑證為例):

root.cer //根憑證檔
server.cer //伺服器憑證檔(網域憑證)
uca_1.cer //中繼憑證檔1
uca_2.cer //中繼憑證檔1

其中,中繼憑證若為多個如上例,則將中繼憑證倒序合併至單檔:

cat uca_2.cer uca_1.cer > uca.cer

目前我尚未看過有人將Root CA也加入Chain

另外我方會有當時拿去申請憑證的CSR及其Pricate Key:

self-ssl.key // 所謂Server.key,HTTPS Server設定所需
self-ssl.csr // 由Private Key產生之CSR用於上傳申請憑證

Nginx SSL安裝

Configuring HTTPS servers - SSL certificate chains

不同於Apache,中繼憑證是可以直接Bundle至網域憑證中:

cat uca.cer server.cer > full-chained.cer

server {
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     full-chained.cer;
    ssl_certificate_key server.key;
    ...
}

憑證檔常態目錄:/etc/pki/tls/

注意:Nginx若沒有設定SSL憑證路徑,則HTTPS連線會自動被中斷

Apache SSL安裝

Apache SSL/TLS Strong Encryption: How-To Apache SSLCertificateChainFile Directive

Apache的中繼憑證是獨立設定的。

SSLEngine On
SSLCertificateFile /etc/ssl/server.cer
SSLCertificateKeyFile /etc/ssl/server.key
SSLCertificateChainFile /etc/ssl/uca.cer

交叉認證 - cross-certification

Wiki: 憑證鏈和交叉認證

  • 原理上主要是在 X.509 信任鍊終端/中繼憑證上設多個簽發參照值(Authority Key Identifier),讓憑證可以一對多向上對應到不同張CA憑證來達到多條合法的憑證鏈
  • 而不同的CA憑證具有相同的主題Subject Key Identifier與公鑰,其中透過交互認證簽發的CA憑證會有Authority Key Identifier再做對應,
  • 交互認證簽發的CA憑證應用上會一併由 Server 提供,讓 Client 可以走這條信任鍊提高對應到local根憑證的可能。

Cross-certification_diagram


延伸文章

Leave a Reply

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