🧭 Webサーバ構築からTLS通信が成立するまで
はじめに
この記事は以下のような人に向けて書いています。
-
「TLS/SSLの流れを図解で整理したい」
-
「‘CAが公開鍵に署名する’とはどういう意味?」
-
「ハッシュ値・署名・秘密鍵の関係が混乱している」
私が情報処理安全確保支援士の試験勉強をしていて、内容が混乱しやすかった部分ですね。「Webサーバ構築~TLS通信の成立」まで一気通貫で流れを理解できるので、ぜひ最後まで読んで下さい!
🌐 1. HTTPサーバの構築(出発点)
まず、普通のHTTPサーバを立ち上げます。
ここでは例としてNginxを使用します。
sudo apt install nginx
sudo systemctl start nginx
この時点ではポート80でHTTP通信ができます。
ただし、通信は平文。パスワードもCookieもそのまま流れてしまいます。
💬 「安全なHTTPS通信にしたい!」
→ そこで登場するのがTLS(旧SSL)です。
🔑 2. 鍵ペア(公開鍵・秘密鍵)の作成
TLSでは、サーバが自分専用の鍵ペアを持つことから始まります。
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr
-
server.key:秘密鍵(外部には絶対出さない) -
server.csr:証明書署名要求(CSR:Certificate Signing Request)
CSR(証明書署名要求)には何が入っている?
実際にserver.csrを中身を覗くと、こんな情報が入っています👇
Subject:
CN = www.example.com
O = Example Inc.
C = JP
Public Key:
Algorithm = RSA
Public-Key = (2048 bit)
Modulus: ab34fe...
Exponent: 65537
Extensions:
subjectAltName = DNS:www.example.com, DNS:example.com
つまり:
「この公開鍵は www.example.com のものですよ」
と主張する申請データです。
🏢 3. 認証局(CA)への証明書発行依頼
次に、CSRを認証局(CA)に送ります。
(例:Let’s Encrypt, DigiCert, GlobalSignなど)
CAは以下を確認します:
- ドメインの所有者が本当に申請者か?
- 公開鍵が改ざんされていないか?
- 会社情報が正しいか?
検証方法(認証レベル)は以下の3タイプがあります:
| 種類 | 検証内容 | 表示例 |
|---|---|---|
| DV(Domain Validation) | ドメイン所有確認 | 一般的なWebサイト |
| OV(Organization Validation) | 組織の実在性も確認 | 企業サイト向け |
| EV(Extended Validation) | 法的実在性・住所も確認 | 銀行や金融機関など |
🧮 4. CAがサーバの公開鍵に署名する(ここが核心)
ここからが「証明書が信頼される」ための肝。
🧾 (1) 署名対象データ(tbsCertificate)の生成
CAはCSRの内容をもとに、以下のデータ構造を組み立てます:
Version: 3
Serial Number: 12345678
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=GlobalSign CA
Subject: CN=www.example.com
Validity: Not Before=2025-01-01, Not After=2026-01-01
Subject Public Key Info: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...
Extensions:
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
subjectAltName = DNS:www.example.com
この「証明書の本体」を tbsCertificate(to be signed certificate) と呼びます。
ここにはサーバの公開鍵も含まれています。
🔢 (2) ハッシュ化(SHA-256)
次に、CAはこのtbsCertificateをハッシュ化します。
Hash = SHA256(tbsCertificate)
例: 8A3B2F9E7C2B1D6F8E91A4D7C0...
この値は証明書内容の「要約」であり、
内容が1ビットでも変わるとまったく違うハッシュ値になります。
🔏 (3) CAの秘密鍵でハッシュ値を暗号化(署名生成)
CAは、**自分専用の秘密鍵(ca.key)**で上記ハッシュ値を暗号化します:
Signature = Encrypt_CA_PrivateKey(Hash)
これがいわゆる「電子署名」です。
つまり:
🔹 CAが自分の秘密鍵で「この内容に間違いありません」と保証する印。
🔹 復号には、CAの公開鍵(ルート証明書)を使う。
📜 (4) 証明書として組み上げる
最終的なデジタル証明書の構造:
Certificate {
tbsCertificate ← サーバ情報・公開鍵など
signatureAlgorithm ← SHA256withRSA
signatureValue ← CAの秘密鍵で暗号化したハッシュ値
}
PEM形式(人間が読む形)ではこんな感じ👇
-----BEGIN CERTIFICATE-----
MIIDZTCCAk2gAwIBAgIQB5z4j...
(略)
-----END CERTIFICATE-----
🧠 検証の仕組み(クライアント側)
ブラウザなどのクライアントは次のように検証します:
-
証明書本体を再びSHA-256でハッシュ化
→
Hash1 = SHA256(tbsCertificate) -
証明書内の署名をCAの公開鍵で復号
→
Hash2 = Decrypt_CA_PublicKey(signatureValue) -
両者が一致すれば「改ざんなし」「信頼できる」と判断。
📈 図で見ると
[Server CSR]
↓ 送信
[CA]
├─ ① tbsCertificate構築
├─ ② SHA-256ハッシュ化
├─ ③ CA秘密鍵で署名
└─ ④ 証明書として発行
↓
[Server Certificate(公開鍵+署名)]
📦 5. サーバへ証明書を配置
CAから発行された証明書を受け取り、サーバに配置します:
/etc/ssl/private/server.key ← 秘密鍵
/etc/ssl/certs/server.crt ← サーバ証明書
/etc/ssl/certs/ca_bundle.crt ← 中間CA証明書
Nginx設定例:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/private/server.key;
ssl_trusted_certificate /etc/ssl/certs/ca_bundle.crt;
}
⚙️ 6. クライアントがアクセス(TLSハンドシェイク開始)
ユーザがブラウザで https://www.example.com にアクセスすると、
ブラウザとサーバ間で以下のやり取りが始まります👇
| ステップ | 内容 | 使用技術 |
|---|---|---|
| ① ClientHello | クライアントがサポート可能なTLSバージョンや暗号スイートを送信 | — |
| ② ServerHello | サーバが使用する暗号スイートを選択し、証明書を送る | サーバ証明書 |
| ③ 証明書検証 | ブラウザがCA公開鍵で署名を検証(信頼確認) | PKI(公開鍵基盤) |
| ④ 鍵交換 | 共通鍵を生成し、サーバ公開鍵で暗号化して送信 | RSA / ECDHE |
| ⑤ Finished | 共通鍵が共有され、通信開始 | — |
🔐 7. 共通鍵による暗号化通信(HTTPS)
ここまでで安全に共通鍵が共有されました。
以降はAESなどの共通鍵暗号方式で、
HTTP通信(リクエスト/レスポンス)が暗号化されて行われます。
ブラウザ → 暗号化済みHTTPリクエスト → サーバ
サーバ → 暗号化済みHTTPレスポンス → ブラウザ
🧱 8. 信頼の連鎖(Chain of Trust)
最終的に、信頼は次のように階層構造で伝わります。
[Root CA 公開鍵] (ブラウザ内蔵)
↓ 署名
[中間CA 証明書]
↓ 署名
[サーバ証明書(あなたのサイト)]
ブラウザはRoot CAを信頼しているため、
その署名に連なるサーバ証明書も自動的に信頼します。
これが「信頼の連鎖(Chain of Trust)」。
✅ まとめ:全体フロー
🏁 結論
| フェーズ | 内容 | キーとなる要素 |
|---|---|---|
| 鍵ペア生成 | 公開鍵・秘密鍵の準備 | RSA / ECDSA |
| 証明書申請 | CSR送信 | ドメイン所有確認 |
| 署名生成 | CAの秘密鍵でtbsCertificateを署名 |
SHA256 + RSA |
| TLSハンドシェイク | 証明書検証+共通鍵共有 | PKI + Diffie-Hellman |
| 通信 | 共通鍵暗号化 | AES-GCM / ChaCha20 |
💡 つまり:
TLS通信の「安全性」は、
① 鍵ペアによる暗号化技術(RSA/ECDHE)と
② CAの署名による信頼性(PKI)
この2つが噛み合うことで成立しているのです。