基礎
対応する OSI の階層
OSI参照モデルと TCP/IP モデルでの位置づけは以下のとおりです。
- OSI参照モデル:セッション層(第 5 層) に分類(トランスポート層のTCPとアプリケーション層の間に位置)
- TCP/IPモデル:セッション層が存在しないため、アプリケーション層に分類
HTTP を TLS で保護したプロトコルが HTTPS 、FTP を TLS で保護したプロトコルが FTPS です。
役割
- サーバー(およびクライアント)の認証:通信相手が本物であることを証明する
- 通信の暗号化:第三者による盗聴を防ぐ(公開鍵で暗号化したデータはペアの秘密鍵でのみ復号できる)
- 改ざんの検出:通信データが途中で変更されていないことを保証する(データ完全性)
TLS 1.3 では、公開鍵暗号(公開鍵で暗号化、秘密鍵で復号)はデータの暗号化に使われません。
- 証明書の鍵ペア:署名の生成(秘密鍵)と検証(公開鍵)にのみ使う
- 鍵交換(ECDHE):公開値を送り合い、共有秘密は各自が計算して導く(通信路上は流れない)
- データの暗号化:共有秘密から導出した共通鍵で行う(AES-GCM など)
TLS 1.3 は暗号化に公開鍵暗号を使いませんが、公開鍵 / 秘密鍵の役割は以下のとおりです。
- 暗号化:公開鍵で暗号化 → 秘密鍵で復号
- 署名:秘密鍵で署名 → 公開鍵で検証
必要ファイル
- 秘密鍵(Private Key /
.key,.pem) サーバー側で保管する鍵。データの復号やデジタル署名の生成に使用する -
証明書署名要求(CSR: Certificate Signing Request /
.csr) 認証局(CA)に証明書の発行を申請するためのデータ。公開鍵や組織情報(ディスティンギッシュネーム)が含まれる - SSL/TLS 証明書(Server Certificate /
.crt,.pem) 認証局のデジタル署名が施された証明書。公開鍵を内包する -
中間証明書(Intermediate Certificate) ルート認証局とサーバー証明書の間を鎖(証明書チェーン)として繋ぐ証明書。現在の Web サービスでは中間認証局から証明書が発行されるのが一般的である
秘密鍵から SSL/TLS 証明書を作成する手順
- サーバーで秘密鍵を作成する
openssl genrsa -out server.key 2048 - 秘密鍵からCSR(証明書署名要求)を作成する
openssl req -new -key server.key -out server.csr※ CSR には公開鍵が含まれますが、秘密鍵自体は含まれない
- 認証局(CA)へ CSR を提出し、デジタル署名を受ける
- 認証局から発行された証明書(
.crt)を受け取る - Web サーバー(Apache / Nginx 等)に秘密鍵・証明書・中間証明書を設定する
※ テスト用証明書(オレオレ証明書)を自己署名で作成する例:
openssl x509 -req -signkey server.key -in server.csr -out server.crt -days 365
SSL/TLS 通信の仕組み
概要
- ハンドシェイク(鍵交換・認証):
- クライアントがサーバーに接続を要求(ClientHello。自分の DH 公開値を含む)
- サーバーが応答(ServerHello。自分の DH 公開値を含む)。双方が共有秘密を計算して鍵交換が完了し、以降のハンドシェイクはそこから導出したハンドシェイク用の鍵で暗号化される
- TLS 1.3 では、サーバー証明書など秘匿が必須でないものも含めてハンドシェイクの後半を暗号化し、プライバシーを高めている
- サーバーは SSL/TLS 証明書を送信し、ハンドシェイク全体に署名する(CertificateVerify)
- クライアントは端末に保持している
信頼されたルート認証局の公開鍵を使って、証明書の正当性(署名およびチェーン)を検証し、サーバーの署名も検証する
- データ通信(暗号化通信):
- ハンドシェイクの完了後、共有秘密から導出したデータ通信用の
共通鍵で通信データを暗号化・復号する
- ハンドシェイクの完了後、共有秘密から導出したデータ通信用の
鍵交換(ECDHE 鍵交換)の詳細
本ドキュメントは TLS 1.3 を前提とします。TLS 1.3 では鍵交換が (EC)DHE に一本化されているため、ECDHE 鍵交換だけをまとめます。
ECDHE とは
Elliptic Curve Diffie-Hellman Ephemeral の略で、「楕円曲線ディフィー・ヘルマン鍵交換(使い捨て型)」と訳されます。
- Elliptic Curve(楕円曲線):DH の計算を楕円曲線上で行う。同じ安全性をより短い鍵で実現できる
- Ephemeral(その場限り):接続ごとに新しい鍵ペアを作り、使い終わったら捨てる。これが前方秘匿性の源になる
DH(Diffie-Hellman 鍵交換)とは
盗聴されうる通信路上で、秘密の値を直接送らずに、両者が同じ秘密の値を共有する方式です。ペンキの混色にたとえると分かりやすくなります。
- 両者が共通の色(公開パラメータ)を決める
- それぞれが自分だけの秘密の色を混ぜ、その混合物を相手に渡す(これが公開値)
- 受け取った混合物に、さらに自分の秘密の色を混ぜる
最終的に両者は同じ色(共有秘密)になりますが、盗聴者は混合物から元の色を分離できません。数学的には 離散対数問題 の困難さに基づいています。ECDHE はこれを楕円曲線上で行うもので、楕円曲線離散対数問題 が土台になります。
前方秘匿性(Forward Secrecy)
ECDHE では、鍵ペアが接続ごとの使い捨てです。そのため、後からサーバーの秘密鍵が漏れても、記録されていた過去の通信は復号できません。この性質を前方秘匿性と呼び、TLS 1.3 では全接続でこれが保証されます。
ECDHE の基本の流れ
- クライアントとサーバーがそれぞれ、その場限りの鍵ペアを作り、公開部分を交換する
- DH の計算で、両者が同じ共有秘密を導き出す(共有秘密は通信路を一度も流れない)
- サーバーは、このやりとり全体に証明書の秘密鍵で署名し、クライアントが証明書の公開鍵で検証する(なりすまし防止)
共有秘密から通信用の鍵へ
共有秘密は、そのままでは暗号化に使いません。
- 共有秘密とハンドシェイクのハッシュから、HKDF(鍵導出関数)で用途別の鍵を作る
- 作った鍵で、AES-GCM や ChaCha20-Poly1305 などの共通鍵暗号によりデータを暗号化・復号する
- ハンドシェイク用の鍵と、データ通信用の鍵(アプリケーション鍵)は別々に導出される
- 鍵は方向別にも分かれる(クライアント → サーバー用と、サーバー → クライアント用)
- 双方が同じ入力から同じ手順で導出するので、鍵そのものは通信路上を流れない
ECDHE で署名が必要になる理由
ECDHE では、共有秘密を DH の計算で作るので、サーバーの秘密鍵は共有秘密の導出には使われません。
そのままでは、偽のサーバーでも DH の計算はできてしまい、中間者攻撃を防げません。そこで、サーバーが秘密鍵で署名して本人であることを示します。
ECDHE の流れ(TLS 1.3)
- ClientHello(クライアント → サーバー)
- クライアントの乱数、対応する暗号スイート、対応する署名アルゴリズムなど
key_share拡張:クライアントがその場で作った DH 鍵ペアの公開値(使用する曲線を推測して、最初から送る)
- ServerHello(サーバー → クライアント)
- サーバーの乱数、選んだ暗号スイート
key_share拡張:サーバーがその場で作った DH 鍵ペアの公開値
- 鍵の導出(ハンドシェイク鍵):ここで双方が DH の計算で同じ共有秘密を導く。これとここまでのやりとりのハッシュから、HKDF(鍵導出関数)でハンドシェイク用の共通鍵を作る。以降のメッセージはすべて暗号化される
- EncryptedExtensions(サーバー → クライアント):暗号スイート選択以外の追加設定(拡張)
- Certificate(サーバー → クライアント):サーバー証明書(チェーン)。クライアントは次の点を検証する
- 証明書チェーンをたどり、信頼されたルート CA の署名まで確認する
- 有効期限、失効状態、ホスト名の一致を確認する
- CertificateVerify(サーバー → クライアント)
- ここまでのハンドシェイク全体のハッシュに、証明書の秘密鍵で署名したもの(ここが署名)
- クライアントは、証明書の公開鍵でこの署名を検証する
- Finished(サーバー → クライアント):ここまでのやりとり全体に対する MAC(HMAC)。クライアントは改ざんがなかったことを確認する
- Finished(クライアント → サーバー):クライアント側の同様の MAC。サーバーも改ざんがなかったことを確認する
- 鍵の導出(アプリケーション鍵):ハンドシェイク全体のハッシュから、HKDF で実際のデータ通信用の共通鍵を作り、暗号化通信に移る
補足:上記は流れを理解しやすくするための簡略版です。HelloRetryRequest、セッション再開、0-RTT などは省略しています。
手順 6. の署名の意味
この署名によって、DH 公開値は「証明書の持ち主が、この接続のために出したもの」と確かめられます。署名の対象は、双方の乱数と DH 公開値を含むハンドシェイク全体の記録(トランスクリプト)です。過去の署名を使い回されるリプレイ攻撃を防げます。
なお、クライアント側には署名がありません。通常クライアントの認証は求められないためです。クライアントが本物かどうかを確かめたい場合は、サーバーが CertificateRequest を送り、クライアントが Certificate / CertificateVerify を返す、クライアント証明書による相互認証になります。
まとめ
- DH:秘密を送らずに、両者が同じ秘密を作る仕組み。
- ECDHE:DH を楕円曲線上で、接続ごとの使い捨て鍵で行う方式。前方秘匿性を持つ。
- 署名(CertificateVerify):DH だけでは相手の本人性を保証できないため、サーバーが証明書の秘密鍵でハンドシェイク全体に署名してなりすましを防ぐ。
認証局の分類
- パブリック認証局(公開認証局): ブラウザや OS にデフォルトでルート証明書が組み込まれている信頼された第三者機関(Let’s Encrypt, DigiCert等)
- プライベート認証局(自己認証局): 社内 Web システムや開発環境などで独自に構築・運用する認証局
OpenSSL
SSL/TLSプロトコルの実装および、暗号化・鍵作成・証明書管理などを行うための標準的なオープンソース・ツールキットです。
暗号化方式およびハッシュアルゴリズム
現代の SSL/TLS(TLS 1.3)では、目的ごとに異なる暗号技術を組み合わせて利用します。
RSA / ECC
- RSA:素因数分解の困難性を利用した公開鍵暗号方式。主にサーバーの「認証(署名)」に使用される
- ECC(楕円曲線暗号):RSAより短い鍵長で同等以上の安全性を実現できる方式(ECDSAなど)
HMAC / SHA-256
- HMAC (Hash-based Message Authentication Code):秘密鍵とハッシュ関数を組み合わせてデータの改ざんを検知する仕組み
- SHA-256: Cryptographic Hash(暗号学的ハッシュ関数)の一種。HMACの内部アルゴリズムやデジタル署名の生成に使われる
AES
- AES (Advanced Encryption Standard):米国標準規格の共通鍵暗号方式。実際のデータ通信の暗号化に使用される(現在では認証付き暗号である AES-GCM が標準的)
ワイルドカード証明書
- 1 枚の証明書で同一ドメインの任意のサブドメイン(
*.example.com)を保護できる証明書(例:app.example.com,api.example.com) - 注意:単体ドメイン(
example.com)とwww.example.comの両方を保護したいだけであれば、ワイルドカード証明書を使わなくても SANs(Subject Alternative Names) 機能により1枚の通常証明書で対応可能
AWSへの導入
AWS環境でSSL/TLS証明書を利用する場合、AWS Certificate Manager (ACM) を使うことで証明書の無料発行および自動更新が可能。自前で取得した Let’s Encrypt 等の証明書を ACM にインポートして利用することもできる。
英語表現・用語比較
- Certificate:(名詞)証明書 ※SSL証明書は通常 Certificate と呼ぶ
- Certification:(名詞)証明、認証行為、または資格認定(Qualification)
- Certificate Authority (CA):認証局
- Authentication:認証(本人であるかを確認すること)
- Authorization:認可(権限を与えること)
- Confidentiality:機密性(許可された者だけが情報にアクセスできること)
- Confidential:(形容詞)機密の、秘密の
- Cipher / Cryptography:
- Cipher:暗号記号、暗号化アルゴリズムそのもの(例: Cipher Suite)
- Cryptography:暗号学、暗号技術全般