TLS 1.2
概要
TLS 1.2 は、インターネット上の通信を暗号化するプロトコル TLS(Transport Layer Security)のバージョンの一つです。RFC 5246(2008 年 8 月)で標準化されました。前バージョンの TLS 1.1(RFC 4346、2006 年)からの主な改良点として、SHA-256 以上のハッシュアルゴリズムの採用、AEAD(Authenticated Encryption with Associated Data)暗号モードである GCM のサポート、PRF(擬似乱数関数)の柔軟な設定が挙げられます。
2026 年現在、TLS 1.2 はウェブトラフィック全体の約 20% を依然として処理しています。後継の TLS 1.3(RFC 8446、2018 年)への移行が進んでいますが、レガシーシステムや古いクライアントとの互換性のために TLS 1.2 との併用が一般的です。一方、TLS 1.0 と TLS 1.1 は 2021 年に RFC 8996 で正式に非推奨となり、主要ブラウザーからも削除されています。
サーバー管理者にとっては、TLS 1.2 を有効にしつつ TLS 1.3 を優先する構成が現時点での実用的な選択です。ただし TLS 1.2 では暗号スイートの選択肢が多いため、弱い暗号スイートを無効にする設定が不可欠です。
仕組み
TLS 1.2 は 2-RTT ハンドシェイク、AEAD 暗号モード、署名アルゴリズムのネゴシエーションを導入し、TLS 1.1 以前の弱点を解消しました。
TLS 1.2 ハンドシェイク
TLS 1.2 のハンドシェイクは 2-RTT(Round-Trip Time)で完了します。クライアントとサーバーが暗号パラメーターを交渉し、安全な通信チャネルを確立するまでの手順は以下のとおりです。
- ClientHello: クライアントがサポートする TLS バージョン、暗号スイート一覧、ランダム値を送信する
- ServerHello: サーバーが使用する暗号スイートを選択し、ランダム値とともにクライアントに返す
- Certificate: サーバーが証明書チェーンを送信する
- ServerKeyExchange: ECDHE や DHE を使用する場合、サーバーが鍵交換パラメーターを送信する
- ServerHelloDone: サーバーからのメッセージ送信完了を通知する
- ClientKeyExchange: クライアントが鍵交換パラメーターを送信する
- ChangeCipherSpec + Finished: 双方が暗号化通信への切り替えを確認し、ハンドシェイクが完了する
TLS 1.3 では 1-RTT ハンドシェイクに簡素化されており、接続確立が高速になっています。TLS 1.2 の 2-RTT は、高レイテンシの環境では体感速度に影響する場合があります。
TLS 1.1 からの改良点
TLS 1.2 で導入された主要な変更は RFC 5246 のセクション 1.2 に記載されています。
PRF の改善が最も大きな変更です。TLS 1.1 以前の PRF は MD5 と SHA-1 を組み合わせた固定構成でした。TLS 1.2 では PRF のハッシュアルゴリズムを暗号スイートごとに指定可能になり、SHA-256 がデフォルトとして採用されました。SHA-1 は 2017 年に Google が衝突攻撃(SHAttered)を実証し、暗号学的なハッシュ関数としての安全性が否定されています。
AEAD 暗号モードのサポートが追加されました。AES-GCM は暗号化と認証を一体化した方式であり、CBC モードで必要だった別途の HMAC 計算が不要です。CBC + HMAC の構成は BEAST 攻撃(2011 年)や Lucky Thirteen 攻撃(2013 年)の対象になりましたが、AEAD ではこれらの攻撃手法が構造的に成立しません。
署名アルゴリズムのネゴシエーションが導入されました。signature_algorithms 拡張により、クライアントとサーバーが受け入れ可能な署名ハッシュアルゴリズムの組み合わせを交渉できるようになりました。TLS 1.1 以前ではこの交渉機構がなく、使用する署名ハッシュが暗黙的に決まっていました。
TLS 1.2 と TLS 1.3 の比較
TLS 1.3 は TLS 1.2 のセキュリティと性能をさらに向上させた後継バージョンです。両者の主な違いを整理します。
ハンドシェイクの往復回数は、TLS 1.2 が 2-RTT であるのに対し TLS 1.3 は 1-RTT です。TLS 1.3 では 0-RTT 再接続もサポートしていますが、リプレイ攻撃のリスクがあるため用途は限定されます。
暗号スイートの選択肢は、TLS 1.2 では数十種類存在し安全性の低いものも含まれますが、TLS 1.3 では 5 つに限定されすべて AEAD + Forward Secrecy を備えています。
鍵交換について、TLS 1.2 では RSA 静的鍵交換が可能ですが、TLS 1.3 では ECDHE のみとなり Forward Secrecy が必須です。RSA 鍵交換ではサーバーの秘密鍵が漏洩すると過去の全通信を復号できるため、TLS 1.3 ではこの方式が廃止されました。
ハンドシェイクメッセージの暗号化について、TLS 1.2 では ServerHello 以降のほとんどが平文で送信されますが、TLS 1.3 では ServerHello 以降の大部分が暗号化されます。証明書情報が暗号化されるため、通信経路上の第三者が接続先のサーバー証明書を観察できなくなります。
設定例
Nginx と Apache で TLS 1.2 と TLS 1.3 を併用し、安全な暗号スイートのみを有効にする構成を示します。
Nginx
Nginx で TLS 1.2 と TLS 1.3 を併用する設定例です。TLS 1.2 では安全な暗号スイートのみを明示的に列挙します。
server {
listen 443 ssl;
server_name example.com;
ssl_protocols TLSv1.2 TLSv1.3;
# TLS 1.2 用: ECDHE + AEAD のみ
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
# TLS 1.2 ではサーバー側優先順位を使用
ssl_prefer_server_ciphers on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
}
ssl_protocols に TLSv1 や TLSv1.1 を含めないことが重要です。これらは RFC 8996 で非推奨となっており、主要ブラウザーも接続を拒否します。
Apache
Apache での設定例です。
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLProtocol -all +TLSv1.2 +TLSv1.3
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
</VirtualHost>
SSLProtocol -all +TLSv1.2 +TLSv1.3 は、まず全プロトコルを無効にしてから TLS 1.2 と TLS 1.3 のみを有効にする書式です。
構成に迷った場合は Mozilla SSL Configuration Generator(ssl-config.mozilla.org)で対象のサーバーソフトウェアとバージョンを選択すると、推奨設定を自動生成できます。
確認方法
openssl でサーバーの TLS 1.2 対応状況を確認するには次のコマンドを使います。
# TLS 1.2 で接続を試行
openssl s_client -connect example.com:443 -servername example.com -tls1_2 </dev/null 2>/dev/null | grep -E "Protocol|Cipher"
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Protocol に TLSv1.2 が表示されれば、サーバーが TLS 1.2 をサポートしています。Cipher 行にはネゴシエートされた暗号スイートが表示されます。
TLS 1.2 のみでの接続可否と TLS 1.3 のサポート状況を比較する場合は次のように確認します。
# TLS 1.3 で接続を試行
openssl s_client -connect example.com:443 -servername example.com -tls1_3 </dev/null 2>/dev/null | grep -E "Protocol|Cipher"
接続に失敗する場合、そのバージョンのプロトコルがサーバー側で無効になっています。
TLS 1.0 や TLS 1.1 が意図せず有効になっていないかを確認するには次のコマンドを使います。
# TLS 1.0 が無効であることを確認(接続失敗が期待値)
openssl s_client -connect example.com:443 -servername example.com -tls1 </dev/null 2>&1 | grep -i "alert\|error"
外部の視点からも確認したい場合は、Labee Dev Toolbox の SSL Cert API を使うと、外部の視点から見た結果を取得できます。
curl "https://labee.dev/api/ssl-cert?hostname=example.com"
{
"success": true,
"data": {
"hostname": "example.com",
"port": 443,
"reachable": true,
"status": 200
},
"error": null,
"meta": { "responseTime": 123 }
}
data.reachable が true であれば TLS ハンドシェイクが成立しています。false の場合、TLS バージョンの非互換や暗号スイートの不一致が原因である可能性があります。
よくある問題
TLS 1.2 の運用では、非推奨プロトコルの残存や安全でない暗号スイートの有効化が典型的なリスクです。
TLS 1.0/1.1 が有効なまま放置されている
TLS 1.0 と TLS 1.1 は RFC 8996(2021 年 3 月)で正式に非推奨となりました。Chrome 84(2020 年 7 月)、Firefox 78(2020 年 6 月)、Safari 14(2020 年 9 月)、Edge 84(2020 年 7 月)はいずれもこれらのバージョンを無効化しています。現在のブラウザーではこれらのプロトコルで接続できませんが、サーバー側で無効化していないと、ブラウザー以外のクライアント(古い API クライアントやスクリプト)からの接続時に脆弱なプロトコルが使用される可能性があります。
# TLS 1.0/1.1 を明示的に除外
ssl_protocols TLSv1.2 TLSv1.3;
RSA 鍵交換を使う暗号スイートが有効
TLS 1.2 では RSA 鍵交換を使用する暗号スイート(例: TLS_RSA_WITH_AES_128_GCM_SHA256)が定義されています。この方式ではサーバーの RSA 秘密鍵で鍵交換を行うため、秘密鍵が漏洩すると過去に記録された全通信が復号されます。ECDHE を鍵交換に使うスイートでは各セッションの鍵が独立しており、この問題は発生しません。ssl_ciphers で ECDHE プレフィックスのスイートのみを列挙して RSA 鍵交換を排除します。
TLS 1.3 のみの構成で古いクライアントが接続不能
TLS 1.3 は 2018 年に標準化されましたが、Java 8(デフォルト設定)、OpenSSL 1.0.x、Android 9 以前など TLS 1.2 までしか対応しないクライアントが存在します。これらのクライアントをサポートする必要がある場合は、ssl_protocols TLSv1.2 TLSv1.3 として両方を有効にします。接続ログやアクセス解析でクライアントの TLS バージョン分布を確認し、TLS 1.2 のトラフィックがゼロに近づいた時点で TLS 1.3 のみに移行する判断が可能です。
CBC モードの暗号スイートによる脆弱性
TLS 1.2 は AEAD(GCM)をサポートしますが、CBC モードの暗号スイートも引き続き使用可能です。CBC + HMAC の構成は BEAST 攻撃(2011 年)や Lucky Thirteen 攻撃(2013 年)の対象となりました。ssl_ciphers で GCM や ChaCha20-Poly1305 の AEAD スイートのみを指定し、CBC モードを排除することで対策できます。
セッション再開の実装差異
TLS 1.2 のセッション再開には Session ID 方式と Session Ticket 方式の 2 つがあります。Session Ticket(RFC 5077)はサーバー側で状態を持つ必要がないため広く使われていますが、チケット暗号化鍵が全サーバーで共有される場合に Forward Secrecy が損なわれます。チケット鍵を定期的にローテーションし、古い鍵を確実に破棄する運用が必要です。TLS 1.3 ではこの問題に対処するため、セッション再開の仕組みが PSK(Pre-Shared Key)ベースに再設計されています。
TLS バージョンの時系列
TLS プロトコルの主要なバージョンと関連イベントを時系列で整理します。
- 1999 年: TLS 1.0 が RFC 2246 で標準化される
- 2006 年: TLS 1.1 が RFC 4346 で標準化される。CBC の IV 明示化で BEAST 攻撃への対策が導入される
- 2008 年: TLS 1.2 が RFC 5246 で標準化される。SHA-256 以上のハッシュ、AEAD(GCM)をサポート
- 2011 年: BEAST 攻撃が公表され、CBC モード暗号の脆弱性が広く認知される
- 2013 年: Lucky Thirteen 攻撃が CBC + HMAC のタイミング脆弱性を実証する
- 2014 年: POODLE 攻撃により SSL 3.0 が実質的に廃止される
- 2018 年: TLS 1.3 が RFC 8446 で標準化される。ハンドシェイクの高速化と安全性の向上を実現
- 2020 年: Chrome、Firefox、Safari、Edge が TLS 1.0/1.1 を無効化する
- 2021 年: RFC 8996 で TLS 1.0 と TLS 1.1 が正式に非推奨化される