SSL/TLS 証明書って結局なんだっけ？

# はじめに
初心に立ちかえるって結構大事ですよね。
大事だけど、新しいことの方が面白いしかっこいいしイケてるし、ついついおざなりにしてしまいがち。
Cloud やら AI やらが普及してから世の中が便利になりすぎたなと感じる今日この頃、なんか当たり前になってるけどそもそもこれってどうなってるんでしたっけ、という疑問が日々湧いてくるので少しずつ消化しようと思ったのが本記事投稿のきっかけ。

# SSL/TLS の概要
超ざっくりいうとこんな感じ。
- プロトコルの一種
- 暗号化（Encryption）、認証（Authentication）、データ完全性（Integrity）を実現
- これにより HTTPS 通信が実現

具体的にどのような流れになっているかは以下2つの記事がわかりやすかったのでリンクだけ貼り付けて割愛し、個人的に気になっていた SSL/TLS 証明書について。

https://qiita.com/jkr_2255/items/62d8d15d206c60f37d30
https://qiita.com/musenmai/items/43929eb9f6f31908fd51

# SSL/TLS 証明書
サーバーにインストールして使用する。証明書は以下の情報を持っている。
①Web サイト所有者の情報
②送信情報の暗号化に必要な鍵
③証明書発行者の署名データ

### 証明書の種類
証明書には「サービスの提供者が誰なのか」を登録する必要があり、証明書を通じて利用者は確認をすることができる。
つまり、**「そのドメインの持ち主が正当な運営元なのか（実在するのかなど）」** が確認できるということ。
加えて、**「そのドメイン所有者が紐づけたサーバーに正しくアクセスできているのか」** ということも確認できる。
※ここで注意したいのが、 **証明書はドメインと通信先のサーバーが一致することを担保するものであり、サイト内容の合法性などを担保するものではない**ということ。

大きく以下3種類あり、それぞれ認証の強度と手続き法が異なる。

- **ドメイン認証（DV: Domain Validation）**
    - ドメイン所有権のみを確認（AWS の ACM はこれ）
    - 発行が迅速で安価
- **企業認証（OV: Organization Validation）**
    - 企業情報（会社名や所在地）の確認を含む
    - 商業目的の Web サイトに適している
- **拡張認証（EV: Extended Validation）**
    - 最も厳格な検証プロセス
    - ブラウザのアドレスバーに企業名が表示され、緑色になる

では具体的にどのようにして証明書の検証をしているのか。

### サーバー証明書の検証の流れ
上記で貼った記事の通り **Server Certificate** のタイミングで、サーバーは認証局に発行してもらったサーバー証明書をクライアントに送る。
そしてこの時、サーバー証明書の検証に必要となる中間証明書やルート証明書も一緒に送る。
※**サーバー証明書 < 中間証明書 < ルート証明書** のような関係性になっており、それぞれ下位の証明書の身元を保証できる（ルート証明書は最上位なので自分で自分を保証するため自己署名証明書と呼ばれる）

例えば `qiita.com` というドメインの証明書を確認すると、`qiita.com` のサーバー証明書のほか、以下のように Amazon の中間証明書、ルート証明書が確認できる。

![Screenshot 2025-02-01 at 11.05.36 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1131391/a6d07376-b4b8-69d2-650a-8f486ce0588c.png)


つまり、証明書は確かにあるみたいだけど、それ発行した人の身元は大丈夫そ？ということを確認している。
このようにして発行元を遡って検証した信頼関係を **「証明書チェーン（トラストチェーン）」**
と呼ぶ。

### 証明書の検証法
証明書には、「証明書の有効期限」、「サーバーのドメイン名」、「公開鍵」、「ハッシュ関数」、「発行者情報」などが含まれる。

![Screenshot 2025-02-01 at 11.10.17 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1131391/1dc15493-9ac7-2131-9223-09372018e394.png)


これらを使用してざっくり以下の流れで検証する。

1. サーバーは「証明書の有効期限」、「サーバーのドメイン名」などの情報をハッシュ化し、更に秘密鍵で暗号化した「署名データ」（ `Certificate` ）を合わせて送信
1. クライアントは受け取った公開鍵（ `Public Key` ）で署名データを複合
    1. ハッシュ値が得られる
1. クライアントは「証明書の有効期限（ `Expires On` ）」、「サーバーのドメイン名（ `Common Name(CN)` ）」などの情報（ハッシュ化も暗号化もされていない）を、受け取ったハッシュ関数（以下画像の `Certificate Signature Algorithm` ）を使用してハッシュ化
1. 2と3の内容が一致することを確認

![Screenshot 2025-02-01 at 11.20.34 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1131391/d668468c-2955-3238-7766-200ce2fabd73.png)

### ルート証明書の検証法
ルート証明書の検証のみ少し特殊。
なぜなら自己署名のため、もしも怪しい認証局だった場合でも自分で保証されてしまうため。

ではどのように防止するかというと、Chrome などの Web ブラウザや OS にはあらかじめルート証明書がインストールされており、その証明書と証明書チェーンによって遡ったルート証明書が一致することをもって、ルート証明書が正しいものであることを検証する。

以下は `qiita.com` から遡ったルート証明書。

![Screenshot 2025-02-01 at 11.59.37 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1131391/408a6b7c-44a0-e807-1097-87bd20079907.png)

そして以下は Chrome にインストールされているルート証明書。

![Screenshot 2025-02-01 at 12.01.36 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1131391/91c3ccaf-9bbe-bfca-fb80-18e837bdeb12.png)

これらの署名データが一致するため、 `qiita.com` から遡ったルート証明書が正しいものであることが検証される。


# おわりに
今までなんとなーくで使っていた言葉や概念がクリアになった。
新しい技術も良いけど、たまにはこうやって立ちかえるのも大事だなと感じた、、、