From: 011netservice@gmail.com Date: 2025-06-08 Subject: self-signed X.509 certificate 的安全問題. File: CodeHelper\Certificate\self-signed-security.txt 歡迎來信交流, 訂購軟體需求. #### self-signed X.509 certificate 的安全問題 使用自簽的 X.509 憑證(self-signed X.509 certificate)在某些情境下是可接受的,但也存在一些潛在的安全問題。以下是主要的風險與考量: 自簽憑證的安全問題 1. **缺乏信任鏈(Trust Chain)** - 自簽憑證不是由受信任的憑證授權中心(CA)簽發,因此瀏覽器或作業系統預設不會信任它。 - 使用者會看到安全警告,可能導致信任問題或中斷連線。 2. **容易遭受中間人攻擊(MITM)** - 攻擊者可以偽造一個自簽憑證並冒充伺服器,若使用者忽略警告並接受該憑證,就可能被攔截資料。 3. **無法撤銷(No Revocation Mechanism)** - 自簽憑證通常不會搭配 CRL 或 OCSP,因此一旦私鑰洩漏,無法有效撤銷憑證。 4. **憑證管理困難** - 在大型系統中,手動管理和分發自簽憑證會變得複雜且容易出錯。 5. **不符合合規要求** - 某些產業(如金融、醫療)有明確規範要求使用受信任的 CA 簽發的憑證。 自簽憑證的適用情境 - **內部測試環境** - **開發階段** - **封閉網路中的內部服務** - **自建 PKI 系統中,作為根憑證使用** 安全建議 - 若必須使用自簽憑證,建議: - 使用強加密(如 2048-bit RSA 或 ECC) - 設定合理的有效期限(例如 1 年) - 僅在受控環境中使用 - 將憑證預先安裝到信任的憑證存儲中(例如企業內部設備) #### 如何產生 self-signed X.509 certificate 使用 OpenSSL 生成自簽憑證 1. 產生私鑰(Private Key) openssl genrsa -out myserver.key 2048 會產生一個 2048-bit 的 RSA 私鑰,儲存在 `myserver.key`。 2. 產生憑證簽署請求(CSR) openssl req -new -key myserver.key -out myserver.csr 會提示你輸入一些資訊,例如: - Country Name (TW) - State or Province Name - Locality Name - Organization Name - Common Name(例如:`example.com` 或 `localhost`) 3. 使用私鑰簽署 CSR,產生自簽憑證 openssl x509 -req -days 365 -in myserver.csr -signkey myserver.key -out myserver.crt 會產生一個有效期為 365 天的自簽憑證 `myserver.crt`。 產出檔案 1. myserver.key:私鑰 2. myserver.csr:簽署請求(可選) 3. myserver.crt:自簽憑證 - 若用於 HTTPS,可將 `.key` 和 `.crt` 配置到 Web 伺服器(如 Nginx、Apache)。 - 若用於本地開發,可將憑證匯入瀏覽器或作業系統的信任憑證庫中。 #### 如何產生 有效截止日期為指定的日期的 self-signed X.509 certificate 可以使用 `openssl` 指定自簽憑證的「有效截止日期」, 方法是透過 `-enddate` 參數來控制。 不過,`openssl x509` 本身不直接接受日期格式作為輸入,而是透過 `-days` 指定從現在起的有效天數。 若要指定一個**明確的截止日期**(例如:2025-12-31),你需要先計算從今天到那天的天數,然後將這個數字傳給 `-days` 參數。 假設今天是 2025-06-08,你想讓憑證有效到 2025-12-31: # 使用 Linux/macOS 的 date 指令 days=$(( ( $(date -d 2025-12-31 +%s) - $(date +%s) ) / 86400 )) 計算出從今天到 2025-12-31 的天數。 產生自簽憑證 openssl req -x509 -newkey rsa:2048 -keyout my.key -out my.crt -days $days -nodes - 產生 RSA 私鑰(2048-bit) - 產生自簽憑證,有效期為 `$days` 天 - 不加密私鑰(`-nodes`) 檢查憑證有效期 openssl x509 -in my.crt -noout -dates 會顯示: notBefore=Jun 8 00:00:00 2025 GMT notAfter=Dec 31 00:00:00 2025 GMT ``` #### C# 版本的 days=$(( ( $(date -d 2025-12-31 +%s) - $(date +%s) ) / 86400 )) # 使用 Linux/macOS 的 date 指令 days=$(( ( $(date -d 2025-12-31 +%s) - $(date +%s) ) / 86400 )) 計算出從今天到 2025-12-31 的天數。 C# 版本的 days=$(( ( $(date -d 2025-12-31 +%s) - $(date +%s) ) / 86400 )) 邏輯如下: using System; class Program { static void Main() { // 指定截止日期 DateTime endDate = new DateTime(2025, 12, 31); // 取得今天的日期(不含時間) DateTime today = DateTime.Today; // 計算天數差 int days = (endDate - today).Days; Console.WriteLine($"距離 {endDate:yyyy-MM-dd} 還有 {days} 天"); } } - `DateTime.Today`:取得今天的日期(時間為 00:00:00) - `new DateTime(2025, 12, 31)`:建立指定的截止日期 - `TimeSpan.Days`:取得兩個日期之間的天數差