# HTTPS 流程

<figure><img src="https://2356031413-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M0u4DAqfidGmTt67qrG%2Fuploads%2F7zWb5QHE1SNdQpMtq1nt%2F%E6%88%AA%E5%9C%96%202024-07-13%20%E4%B8%8B%E5%8D%8810.39.28.png?alt=media&#x26;token=780b8689-d3cf-40c9-bf81-a583a8d449d3" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2356031413-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M0u4DAqfidGmTt67qrG%2Fuploads%2F58zI9R71hw59GmEj7fbB%2F%E6%88%AA%E5%9C%96%202024-07-14%20%E4%B8%8A%E5%8D%889.53.26.png?alt=media&#x26;token=7ccb10b2-24e0-4194-addf-898ba41987c9" alt=""><figcaption><p><a href="https://blog.bytebytego.com/p/how-does-https-work-episode-6">https://blog.bytebytego.com/p/how-does-https-work-episode-6</a></p></figcaption></figure>

可參考原始碼：<https://github.com/chromium/chromium/blob/main/net/socket/ssl_client_socket_impl.cc#L474>

接著看 Wireshark 實際發送封包之流程

<figure><img src="https://2356031413-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M0u4DAqfidGmTt67qrG%2Fuploads%2FxR3hJOtLtCgzfo1JFqac%2F%E6%88%AA%E5%9C%96%202024-07-14%20%E4%B8%8A%E5%8D%889.52.23.png?alt=media&#x26;token=e014c364-d836-469d-a08c-e7d9b4f82323" alt=""><figcaption></figcaption></figure>

HTTPS 的交握步驟詳細如下：

* **ClientHello**：
  * 客戶端生成一個隨機數 `random-client`，並將其連同支持的TLS版本、密碼套件（cipher suites）、壓縮方法和可選擴展等信息發送到服務器端。
  * 傳遞內容：
    * **支持的TLS版本**：表示客戶端支持的TLS協議版本（例如TLS 1.2或TLS 1.3）。
    * **密碼套件**：包括客戶端支持的加密算法、鑰匙交換算法、MAC算法等的列表。
    * **擴展**：例如SNI（Server Name Indication）擴展，用於支持多域名的HTTPS。
* **ServerHello**：
  * 服務器生成一個隨機數 `random-server`，並選擇TLS版本、密碼套件，並將其連同服務器的公鑰證書一併回傳給客戶端。
  * 傳遞內容：
    * **公鑰證書**：服務器的數字證書，包含服務器的公鑰和由可信任的證書頒發機構（CA）簽名的證書。
    * **密碼套件選擇**：服務器從客戶端提供的列表中選擇一個共同支持的密碼套件。
* **客戶端回應**：
  * **描述**：客戶端收到服務器的`ServerHello`消息後，保存`random-server`和公鑰，然後生成一個`premaster secret`，並用服務器的公鑰加密後發送給服務器。
  * **技術細節**：
    * **premaster secret**：一個隨機生成的值，用於生成會話密鑰。此值僅在這次會話中使用。
    * **加密**：使用服務器的公鑰加密`premaster secret`，保證傳輸過程中的安全。
* **服務器解密**：
  * **描述**：服務器使用其私鑰解密客戶端傳來的`premaster secret`，此時雙方都擁有了`random-client`、`random-server`和`premaster secret`這三個關鍵要素。
  * **技術細節**：
    * **私鑰解密**：服務器使用其私鑰解密`premaster secret`，保證只有服務器能夠獲取此值。
    * **會話密鑰生成**：雙方使用`random-client`、`random-server`和`premaster secret`通過協商好的算法生成會話密鑰（`session keys`）。
* **建立安全通道**：

  * **描述**：安全通道建立後，雙方開始使用會話密鑰加密通信內容，保證傳輸的機密性和完整性。
  * **技術細節**：

    * **Change Cipher Spec**：通知對方接下來的通信將使用新協商的密碼套件。

    * **Finished**：雙方交換加密的`Finished`消息，確認握手過程無誤並開始安全通信。

  > `session key`: 是 TLS/SSL 最後協商得出的共同密鑰，用来進行後續所有封包的對稱式加密。

可將以下檔案導入 Wireshark 查看

{% file src="<https://2356031413-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M0u4DAqfidGmTt67qrG%2Fuploads%2FaIeL9MFSa0atWttu3kPz%2Fhttps-flow.pcapng?alt=media&token=75390b6b-5d3a-4f36-bee0-5d232aca06d2>" %}

***

***

## **PKI 系統（Public Key Infrastructure）**

公鑰基礎設施（PKI）是一套管理數字證書和公私鑰對的技術和規範。PKI 系統的主要組成部分和功能如下：

1. **證書頒發機構（CA, Certificate Authority）**：
   * CA 是一個受信任的實體，負責頒發和管理數字證書。它驗證申請者的身份並簽署數字證書，確保證書的真實性和有效性。
2. **註冊機構（RA, Registration Authority）**：
   * RA 是 CA 的代理，負責接收證書申請，驗證申請者的身份，並將已驗證的申請轉發給 CA。
3. **數字證書**：
   * 數字證書包含持有者的公鑰、持有者的身份信息、CA 的簽名和其他相關信息。證書用來驗證持有者的身份並確保通信的安全性。
   * 常見的證書格式是 X.509。
4. **密鑰生成和管理**：
   * PKI 系統負責生成、分發、存儲和管理密鑰對。密鑰管理包括密鑰的備份、恢復、更新和撤銷。

以 AWS 為例，類似以下流程：

```
  User (You)        AWS (RA)                CA (Amazon Trust Services)
     |                  |                               |
     |  Request Cert    |                               |
     |----------------->|                               |
     |                  |   Validate Domain (DNS/Email) |
     |                  |------------------------------>|
     |                  |                               |
     |                  |  Issue Cert                   |
     |                  |<------------------------------|
     |                  |                               |
     |   Use Cert       |                               |
     |<-----------------|                               |
     |                  |                               |

```

電腦預設會裝有 CA 憑證

<figure><img src="https://2356031413-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M0u4DAqfidGmTt67qrG%2Fuploads%2Fu5IKSFv8cJR0S8R9d4ws%2F%E6%88%AA%E5%9C%96%202024-07-14%20%E4%B8%8A%E5%8D%8810.48.49.png?alt=media&#x26;token=88b55425-a70f-4ddb-ab5a-e027dd1e3da5" alt=""><figcaption></figcaption></figure>

### **自己當 CA 並幫其他網站簽發 HTTPS 證書之技術步驟**

#### 1. 生成自己的 CA 的密鑰對

```sh
sh複製程式碼# 生成一個 2048 位的 RSA 私鑰，用於 CA
openssl genpkey -algorithm RSA -out ca_private_key.pem -pkeyopt rsa_keygen_bits:2048

# 從私鑰中提取公鑰，生成 CA 的公鑰證書
openssl req -new -x509 -key ca_private_key.pem -out ca_cert.pem -days 3650 -subj "/CN=My CA"
```

這會生成一個 CA 的私鑰 `ca_private_key.pem` 和一個自簽名的 CA 公鑰證書 `ca_cert.pem`。

#### 2. 幫其他伺服器生成密鑰對

```sh
# 生成一個 2048 位的 RSA 私鑰，用於伺服器
openssl genpkey -algorithm RSA -out server_private_key.pem -pkeyopt rsa_keygen_bits:2048

# 從私鑰中提取公鑰
openssl rsa -pubout -in server_private_key.pem -out server_public_key.pem
```

#### 3. 創建為了簽發其他 HTTPS 伺服器證書的 CSR（Certificate Signing Request）

CSR 包含伺服器的公鑰和身份信息，並用私鑰簽名。

```sh
openssl req -new -key server_private_key.pem -out server.csr -subj "/CN=www.example.com"
```

#### 4. 使用 CA 簽署伺服器的 CSR

CA 驗證伺服器的身份後，簽署 CSR 並生成數字證書。

```sh
openssl x509 -req -in server.csr -CA ca_cert.pem -CAkey ca_private_key.pem -CAcreateserial -out server_cert.pem -days 365
```

即會生成伺服器的數字證書 `server_cert.pem`。

#### 5. 配置伺服器

將數字證書 `server_cert.pem` 和私鑰 `server_private_key.pem` 配置到伺服器，準備進行 SSL/TLS 。
