讓你一文掌握 CA 證書

在網路環境中,資料安全是每個開發者和使用者都會關注的核心問題。 HTTPS(HyperText Transfer Protocol Secure)是一種基於加密傳輸的網路協議,是應用層保護通訊安全、防止資料被竊聽和篡改的主要手段。

在許多第一線企業,例如騰訊、阿里、字節等,許多應用強制要求使用 HTTPS 協定進行通信,Kubernetes 也提倡透過 HTTPS 協定進行通信。那麼,為什麼建議透過 HTTPS 協定而非 HTTP 協定?這源自於二者的核心差異:


HTTP 協定以明文方式傳輸數據,在網路中傳輸時可能遭受竊聽、篡改或冒充攻擊,安全性較低,有資料外洩風險;
HTTPS 協定基於 HTTP 協定增加了 SSL 安全層,透過加密通道傳輸數據,安全性更高。
通常,HTTPS 協定主要實現以下兩類功能:

資料傳輸加密: 透過 HTTPS 傳輸的資料始終以加密形式存在,確保資訊安全;
身份認證: HTTPS 支援單向認證和雙向認證。單向認證用於驗證服務端的真實性,雙向認證則同時驗證服務端和用戶端的合法性。
在實際的企業應用中,HTTPS 的使用方式主要包括:

利用 HTTPS 的資料加密能力,啟用單向認證驗證服務端的合法性,客戶端認證則採用其他方式,例如 Bearer 認證。 miniblog 專案採用的正是這種方式;
利用 HTTPS 的資料加密能力,同時透過雙向認證驗證服務端和客戶端的合法性。
由於 CA 認證和 HTTPS 認證流程經常在面試中被考察,同時 miniblog 在啟用 HTTPS 服務時需要理解相關內容。接下來,本課程將對這兩部分進行詳細介紹。
一、什麼是 HTTPS?
HTTPS 是 HTTP(超文本傳輸協定)的安全版本。它透過在 HTTP 和傳輸層之間加入 SSL/TLS(安全通訊端層/傳輸層安全協定)來確保通訊安全。相較於 HTTP,HTTPS 增加了三項核心功能:

資料加密:透過加密技術,確保通訊內容不會被第三方竊聽;
身份驗證:透過伺服器憑證驗證伺服器身份,防止中間人攻擊;
校驗資料是否在傳輸過程中被竄改。

使用 HTTPS 後,資料從客戶端到伺服器的整個過程都被加密保護,只有通訊雙方才能解碼資料。
二、認識 CA 證書
CA 憑證的內容較多,可從以下四個面向掌握 CA 憑證相關知識:

CA 憑證相關名詞;
CA 憑證簽發流程;
CA 證書認證流程;
CA 憑證簽發實戰。
1. CA 憑證相關名詞
CA 憑證涉及眾多名詞,以下整理了一些核心名詞,供參考:

(1) CA: 數位憑證認證機構(Certificate Authority,簡稱 CA),是負責發放和管理數位憑證的權威機構,作為受信任的第三方,承擔公鑰體系中公鑰合法性檢驗的職責;
(2) CA 證書: CA 證書是由 CA 簽發的數位證書,其格式可能有所不同,目前最常使用的是 X.509 證書格式;

(3) 公鑰與私鑰: 公鑰(Public Key)和私鑰(Private Key)是一對金鑰,透過特定演算法產生。公鑰是金鑰對中公開的部分,通常用於加密會話金鑰、驗證數位簽章或加密需透過對應私鑰解密的資料;私鑰則是非公開的部分;

(4) 加密演算法: 可以使用多種加密演算法對資料進行加密。常見的加密演算法包括以下兩類:

(5) 對稱加密: 只有一個金鑰進行加密和解密,金鑰相同且加解密速度較快。典型的對稱加密演算法包括 DES 和 AES 等;
(6) 金鑰以成對形式出現(公鑰和私鑰),公鑰和私鑰互為匹配,且無法透過公鑰推導出私鑰,反之亦然。公鑰用於加密時需透過私鑰解密,私鑰用於加密時需透過公鑰解密。與對稱加密相比,其速度較慢。典型非對稱加密演算法包括 RSA 和 DSA 等。

(7) X.509 證書編碼格式: X.509 證書可能採用不同的編碼規則。目前編碼格式主要包括以下兩種:

PEM(Privacy Enhanced Mail): 文字格式,文件後綴為 .pem,以 -----BEGIN XXXXXX----- 開頭,-----END XXXXXX----- 結尾,內容為 BASE64 編碼。多用於 Apache 和 UNIX 伺服器;
DER(Distinguished Encoding Rules): 二進位格式,檔案後綴為 .der,不可讀。多用於 Java 和 Windows 伺服器。
(8) X.509 憑證檔案後綴:X.509 憑證的檔案後綴不一定是 .pem 或 .der,以下是常見類型:

CRT(.crt): 代表 Certificate,意為證書,常見於 UNIX 系統,可能採用 PEM 或 DER 編碼,大多數為 PEM 編碼;
CER(.cer): 代表 Certificate,意為證書,常見於 Windows 系統,可能採用 PEM 或 DER 編碼,大多數為 DER 編碼;
KEY(.key): 通常存放公鑰或私鑰,雖非 X.509 證書,但其編碼格式可能為 PEM 或 DER;
CSR(.csr): Certificate Signing Request,即憑證簽署請求。 CSR 不是證書,而是向權威證書頒發機構申請簽署證書的請求,主要包含一個公鑰及附加資訊。在產生申請時,會同時產生一個私鑰,需自行妥善保管,無需提交給 CA 機構。
需要特別注意的是,如果憑證檔案的後綴是.pem 或.der,在檔案名稱中應體現文件所屬類別,例如:server-key.pem 表示私鑰文件,server-crt.pem 表示憑證檔案。

為了更了解 CA 相關內容,接下來將以 CA 的簽發流程為主線,在介紹流程的同時,闡述相關概念,CA 的認證流程其實也是 HTTPS 的認證流程。

2. CA 憑證的簽發流程
CA 憑證認證流程如下圖所示:
上圖所示的流程解釋如下:

(1) 服務端向第三方機構 CA 提交公鑰、組織資訊、個人資訊(如網域名稱)等內容並申請認證(無需提交私鑰);

(2) CA 透過線上、線下等多種手段驗證申請者提供資訊的真實性,例如確認組織是否存在、企業是否合法、是否擁有網域的所有權等;

(3) 若資訊審核通過,CA 會發給申請者認證文件(證書):

憑證包含以下資訊:申請者的公鑰、組織資訊和個人資訊、簽發機構 CA 的資訊、憑證有效期限、憑證序號等明文訊息,同時也包含一個簽章;
簽章的產生演算法:首先,使用雜湊函數計算明文資訊的資訊摘要,然後,採用 CA 的私鑰對資訊摘要進行加密,產生的密文即為簽章。
(4) 客戶端向服務端發出請求後,服務端返回服務端的憑證檔案;
(5) 用戶端讀取服務端憑證中的明文訊息,並使用相同的雜湊函數計算資訊摘要。隨後,利用對應 CA 的公鑰解密簽名資料並對比資訊摘要。如果兩者一致,則可以確認憑證的合法性,即公鑰合法。同時,客戶端也需驗證憑證中的網域資訊、有效期限等內容。客戶端通常內建信任 CA 的根證書(包含公鑰),如果 CA 不被信任,則無法找到對應 CA 的證書,該證書將被判定為非法;

(6) 用戶端產生一個隨機數 R,並用服務端憑證中的公鑰加密後傳送給服務端。服務端使用其私鑰解密取得隨機數 R,隨後雙方使用對稱加密演算法進行資料交換。
3. CA 認證流程
CA 憑證的認證分為單向認證和雙向認證。在實際開發中,可依需求自行選擇:

單向認證:適用於無需在通訊層對使用者身分進行驗證的場景,一般在應用邏輯層保證使用者的合法登入。單向認證也是企業應用中,使用最多的認證方式;
雙向認證:要求通訊雙方相互驗證身分。例如,在企業應用服務之間存在互調關係時,可能需要對通訊雙方進行身份驗證。
(1) 單向認證流程

單向認證流程如下圖所示。
上圖 已經清楚的展示了單向流程的步驟,這裡不再詳解。需要注意的是第 3 步使用的是 CA 機構憑證(根憑證)的公鑰來解密簽章。

透過上述單向認證流程可以看出,整個流程需要以下三個憑證檔案:根憑證、伺服器端公鑰憑證、伺服器端私鑰檔案。

(2) 雙向認證流程

單向認證僅驗證了服務端的身份。如果有人冒充客戶端,該如何因應?此時可以採用雙向認證。

雙向認證 SSL 握手過程與單向認證有所不同,其大部分步驟與單向認證流程相同。但在客戶端成功驗證伺服器後,新增了伺服器驗證客戶端的流程步驟。雙向認證流程如下圖所示。
透過上述雙向認證流程可以看出,整個雙向認證過程需要 5 個憑證檔案:根憑證、伺服器端公鑰憑證、伺服器端私鑰檔案、用戶端公鑰憑證、用戶端私鑰檔案。

4. CA 證書簽發實戰
CA 證書由權威的 CA 機構簽發,其簽發流程較為複雜且費用較高。在後端應用開發中,通常由開發或維運人員自行產生根證書及其私鑰,並扮演 CA 的角色,負責為其他服務端和用戶端簽發證書,此類證書也稱為自簽證書。

在企業應用程式開發中,可以使用 openssl 工具來簽發根憑證、服務端憑證和用戶端憑證。使用 openssl 工具簽發憑證具體包括以下幾個步驟:
簽發根證書和私鑰;
產生服務端憑證;
產生客戶端憑證;
(1) 步驟一:簽發根憑證和私鑰

簽發根憑證和私鑰包括以下 3 步驟操作:產生根憑證私鑰、產生請求檔、產生根憑證。

① 產生根憑證****私鑰

使用以下命令產生根憑證私鑰:
genrsa 子指令主要用於產生 RSA 私鑰。命令列格式:openssl genrsa [args] [numbits]。涉及參數說明如下:

-out file:將產生的私鑰儲存至指定的檔案;
numbits:指定產生私鑰的大小,預設為 2048。
② 產生請求文件

使用證書私鑰產生請求文件,命令如下:
req 子指令主要用於建立憑證要求文件,其命令列格式為:openssl req [options] <infile> outfile。參數說明如下:

-new:建立新的憑證要求檔;
-key file:指定建立憑證要求所使用的私鑰檔案;
-out arg:指定輸出檔路徑;
-subj arg:設定或修改憑證要求中的主體資訊。
證書請求的主體資訊選項說明如下:

CN(Common Name):指定憑證中識別身分的名稱,該名稱必須唯一。通常填寫需要申請 SSL 憑證的網域(domain)或子網域(subdomain);
C(Country): 國家代碼;
ST(State): 州或省;
L(Locality): 城市;
O(Organization): 組織名稱;
OU(Organizational Unit): 組織單位名稱。
③ 產生根證書

執行以下命令產生根證書:

x509 指令主要用於建立和修改 x509 證書,其命令列格式如下:openssl x509 [options] <infile> outfile。參數說明如下:

-in arg:指定輸入文件,預設為標準輸入;
-out arg:指定輸出文件,預設為標準輸出;
-req:指定輸入檔為憑證要求;
-signkey arg:指定用於自簽署的私鑰檔案;
-CA arg:設定 CA 文件,必須為 PEM 格式;
-CAkey arg:設定 CA 私鑰文件,必須為 PEM 格式;
-CAcreateserial:建立序號檔案。
(2) 步驟二:產生服務端憑證

執行以下命令來產生服務端憑證:
在上述指令中,rsa 子指令主要用於處理 RSA 公私鑰檔。命令列格式:openssl rsa [options] <infile> outfile。涉及參數說明如下:

-in arg: 指定輸入檔;
-pubout:指定輸出檔為公鑰,預設為私鑰;
-out arg:指定輸出檔。
(3) 步驟三:產生客戶端憑證

執行以下命令來產生客戶端證書: