TLS 入門
TLSは安全に通信するためのプロトコルです。OSI参照モデルのトランスポート層での通信のために使用されます。すなわち、アプリケーションレイヤーを含む、トランスポート層よりも上のレイヤーを暗号化対象とします。
TLSで実現するものとしては、大きく以下の2点が挙げられます。
少し別の観点で見ると、TLSでは以下の内容を実現します。
機密性については、暗号化に対応します。データが知らないうちに変わると困ります。完全性については、このようなことがないことを保証します。真正性について、これは認証に対応します。
すなわち、それぞれのリスク対策として、機密性は通信内容が他社に漏れないこと、完全性は通信内容に改ざんがあればそれに気付けること、真正性としては、通信相手、すなわち、Webサイトの運用者になりすましがあれば、すぐに気付けることが挙げられます。
SSL/TLS
そもそも、TLSはSSLとセットで語られることも多く、SSL/TLSなどと表記されることがあります。
SSLとTLSの端的な違いは、例えば、以下のことが挙げられます。
SSLとTLSをそれぞれバージョンごとに特徴を挙げると以下のようになります。
SSL
SSL 1.0
Netscape社が商用トランザクションのセキュリティのためにの開発を始めたが、リリースされなかった
SSL 2.0
Netscape Navigator 1.1という当時支配的だったブラウザに実装
ただし、重大な脆弱性があり、SSL 3.0の開発を始める
SSL 3.0
スクラッチで開発。TLSの各バージョンにも受け継がれる設計を確立
POODLE攻撃の脆弱性を受け、TLSの利用が推進され始める
TLS
TLS 1.0
マスターシークレットが独自構成ではなく、PRFで生成
verifay_dataの値が独自構成ではなく、PRFで生成
完全性の検証(MAC)で標準化されたHMACを利用
TLS 1.1
CBC暗号化利用モードで、各TLSレコードに明示的なIVを利用
パディング攻撃対策として、bad_record_macアラートを返すことを要求。decryption_failedアラートを廃止
TLS 1.2
クライアントが新しい拡張signature_algorithmを使って受け入れを希望するハッシュと署名のアルゴリズムを通知可能
PRFでMD5とSHA1を組み合わせていた部分をSHA256に置き換え
デジタル署名でMD5とSHA1を組み合わせていた部分をデフォルトでSHA256に置き換え。ただし、暗号スイートでハッシュ関数を指定可能
Finishedメッセージのverify_data要素の長さを暗号スイートで明示的に指定可能
TLS 1.3
セッションのリネゴシエーションや再開に関する脆弱性のある方式を廃止し、セッション再開については新たな方式を採用
ネゴシエーション (handshake) シーケンスの大幅な変更
以降は、基本的にTLS 1.2をベースとした内容で説明します。
TLSハンドシェイク
TCPの3ウェイハンドシェイクによりTCPコネクションを確立後に、TLSハンドシェイクが行われます。
接続方法のネゴシエーションが行われることについて言及しましたが、これはクライアントとサーバーがそれぞれ可能な処理内容を暗号スイートを通してやりとりします。
暗号スイートにはTLSの目的を実現する手段と、その手段を実現するにあたっての情報の交換方法が書かれています。
クライアント側は自身が対応している暗号スイートを優先度順にしてリストを送ります。通常は、サーバー側は自身で対応している暗号スイートの中で、クライアントから提示されたリストの上から選択します。Server Order Preference等の設定が行われている場合は、サーバー側のリストの上から選択します。
このようにネゴシエーションが行われて、どのようにTLS通信が行われるかが決まります。
すなわち、TLSハンドシェイクは様々な方法でも実現可能な仕組みのフレームワークのようなものです。
暗号スイート
暗号スイートは例えば、以下のような文字列で表します。
Copy ECDHE-ECDSA-AES128-SHA256
上記は大きく4つの要素からなり、それぞれ以下の内容を実現する方法を表しています。
もう少し掘り下げると、それぞれ以下のとおりです。
鍵交換(Key Exchange)
TLSハンドシェイク内で具体的にどういった方法で鍵交換を行うかの取り決め
TLSハンドシェイクの説明を聞くと、このRSAの説明のみをイメージしてしまっている人も多いという印象
認証(Authentication)
認証はTLSの目的の一つ。大事な機能で忘れちゃだめ。
暗号(Cipher)
機密性はTLSの目的の一つ。これが一番みんながイメージが湧きやすいところか。
データ完全性(Data Integrity)
完全性はTLSの目的の一つ。データが改ざんされていれば気付けるようにしておくために、ハッシュ関数を使用する
message authentication algorithm のことを指していて、メッセージの認証に使用。OpenSSLだとMacという記載からも分かる
一般的な名称とOpenSSLでの名称
例えば、以下のようなフォーマットで先程説明したものとは異なる表記のものを見かけることもあるでしょう。
OpenSSLで以下のようなコマンドを実行すると、利用可能な暗号スイートのリストが見られます。ここに含まれていることが確認できます。その横に詳細が書かれていますが、上記暗号スイートは、TLS 1.2で、鍵交換はRSA、認証はRSA、暗号化はAES 128bit、MACはSHA256で実行することを記載したものであることがわかります。
Copy $ openssl ciphers -v
TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD
TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any Au=any Enc=CHACHA20/POLY1305(256) Mac=AEAD
TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD
:
AES128-SHA256 TLSv1.2 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA256
:
PSK-AES128-CBC-SHA256 TLSv1 Kx=PSK Au=PSK Enc=AES(128) Mac=SHA256
PSK-AES128-CBC-SHA SSLv3 Kx=PSK Au=PSK Enc=AES(128) Mac=SHA1
鍵交換
RSA鍵交換
クライアントが、プリマスターシークレットの値として48バイトの乱数を生成して、サーバーの公開鍵で暗号化してClientKeyExchangeメッセージに入れて送信します。サーバー側は自身の秘密鍵で復号することで、プリマスターシークレットの値を入手できます。
この方法の欠点としては、サーバー側の秘密鍵が流出すると、プリマスターシークレットを生成し、セッションを乗っ取ることができます。リアルタイムではなく、過去のデータも遡って見ることができてしまいます。そのたえめ、PFSの性質がありません。
なお、プリマスターシークレットからマスターシークレット生成理由としては、鍵交換方法によってプリマスターシークレットの長さが異なることが理由として挙げられます。
Diffie-Hellman鍵交換 / 楕円曲線Diffie-Hellman鍵交換
Diffie-Hellman鍵交換は、安全ではない通信路で共有鍵を生成するためのアルゴリズムです。この方法では、一方向の計算は簡単で逆方向の計算が困難である数学の性質を利用します。
まず、事前準備として、公開パラメータg,pを事前に共有しておきます。また、サーバー、クライアントはそれぞれ、事前に秘密鍵に相当するx,yという値を用意しておきます。
それぞれ、公開パラメーターから自身のDH公開鍵を以下の計算式で計算します。
サーバーがDH公開鍵を以下のように計算し、クライアントに送ります。
クライアントも同様にDH公開鍵を以下のように計算し、サーバーに送ります。
クライアントはサーバーから送られてきた公開鍵を最初にgの値に対して計算した方法と同様に、サーバーはクライアントから送られてきたDH公開鍵を最初にgの値に対して計算した方法と同様に計算します。すると、以下のように共通の値を取得することができ、このように共有鍵を生成します。
Copy K = A^y mod p = B^x mod p (= (g^x)^y mod p = (g^y)^x mod p )
Diffie-Hellman鍵交換にはEphemeral、Static、Anonymousの種類があります。Staticな方法は、サーバーおよりクライアントの証明書に静的にパラメータを埋め込んで利用する方法です。その結果、鍵交換の結果が常に同じ共有鍵になります。一方で、前回の鍵交換で使ったパラメータを利用しない方法はEphemeralな方法で、PFSがある状態になります。DHE(一時的Diffie-Hellman)と呼びます。
TLSでは基本的にStaticな方法もサポートされているが、使われることはなく、TLS 1.3では廃止されています。
DH鍵交換は受動的な攻撃には強いですが、攻撃者が相手のフリをして間に入り込む、いわゆるMan-In-The-Middle(MITM)攻撃には弱いです。そのため、認証と組み合わせて使用します。
TLSではDHの公開鍵に対してデジタル署名を付加することで、署名は相手が公開している公開鍵で検証し、その公開鍵の検証はデジタル証明書のルート証明書が信頼されていることを確認することで行います。
DHとは異なり、楕円曲線暗号を用いたものがECDHE(一時的楕円曲線Diffie-Hellman)です。DHパラメータとしてサーバー側で定義されたある楕円曲線を使用します。
非対称暗号化と対象暗号化
TLSでは非対称暗号化と対称暗号化を使い分けます。端的にそれぞれをまとめると以下のような内容になります。
非対称暗号化
名前からも分かる通り、暗号化側と復号側が異なるもので実現する内容です。
対称暗号化
事前に同意しておいた秘密鍵を、暗号化側と共通側で共通のものを使用
複数のユーザーがいると、その組み合わせだけ共通鍵が必要になる。
鍵交換には暗号スイートのKey Exchangeで指定した対象暗号化の方法が使用されます。その後のデータのやり取りには対称暗号化が利用されます。
ではなぜ、非対称暗号化から対称暗号化に切り替えるか。それは、対称暗号化の処理に対するCPUコストが大きいため、計算に時間がかかり、サイズの大きい計算には不向きだからです。
そのため、最初の認証や共有鍵を相手とやりとりするときに対称暗号化の方法を利用し、その後のデータのやりとりには非対称暗号化が利用されます。
なお、TLSでは共通鍵として、新規コネクションごとにランダムなセッション鍵を使用します。これは侵入者が得ることができる暗号部分の量を減らすためです。仮にバレてもその部分のみしか盗み見られず、影響範囲を抑えることができます。
メッセージ詳細
フォーマット
TLSは、Recordプロトコルがコネkす本庄でやり取りされる低レベルのメッセージ転送をを行います。以下のような構成になっています。
Copy ------------------------------------------------------------------------------
| ヘッダー(コンテントタイプ(サブプロトコル) + バージョン + レコード長) | メッセージデータ |
------------------------------------------------------------------------------
暗号化および完全性の検証
最初のネゴシエーションが完了後、ネゴシエーションした結果に基づいて暗号化および完全性の検証
拡張性
データの転送や暗号化処理以外はサブプロトコルで行う。
圧縮機能はCRIME攻撃に利用されたことで、現在は利用されていません。
サブプロトコル
TLSのコアとしては以下4つのサブプロトコルが定義されています。
Handshakeプロトコルは、実際にTLSハンドシェイクの際に、パラメーターのネゴシエーションや認証を行う際に使用されます。Handshakeプロトコルとしては以下のメッセージが定義されています。ClientKeyExchangeは実際には異なるため、カッコ書きで記載しています。
TLSハンドシェイクの一連の流れで、ChangeCipherSpecのメッセージがお互いに交換されますが、これはハンドシェイクメッセージの一部ではなく、Change Cipher Specプロトコルとして、1つだけChangeCipherSpecのメッセージというメッセージが定義されており、こちらが利用されています。そのため、ハンドシェイクの完全性検証の対象外です。
Application Dataプロトコルは、アプリケーションデータを運ぶために使用されます。これらのデータは、セキュリティのパラメータに基づいて、Recordプロトコルのレイヤーでパッケージ化、細分化、および暗号化されます。
Alertプロトコルは、もう一方の相手に例外的な状況を伝えるために使用します。エラーメッセージやclose_notifyという接続のシャットダウンに使用します。close_notifyが送られる理由としては、強制切断攻撃で、攻撃者が能動的に通信を横取りして以降のメッセージをブロックするという攻撃にさらされているのか、正常に通信が終了しているのかを明示化するためです。
RSAやDiffie-Hellmanを利用したTLSハンドシェイク
TLSハンドシェイクの方法はあくまで目的を実現するためのフレームワークのようなもので、具体的な方法は暗号化スイートを始めとするセキュリティパラメーターで決まります。
セッション再開(Session Resumption)
TLSのハンドシェイクは負荷の大きい処理です。そのため、フルハンドシェイクを実行後は、マスターシークレットの値をキャッシュして再利用する方法があります。
セッションID
クライアントとサーバーの両方でセッションのセキュリティパラメータを保持しておきます。サーバーがセッションをキャッシュしておき、クライアントからClientHelloで対応するセッションIDが提示される場合、対応するセッション識別子を返します。
セッションチケット
サーバーは、すべてのセッションデータを収集し、暗号化してから、チケットの形式でクライアントに返します。それ以降の接続では、クライアントがサーバーにそのチケットを送信します。次に、サーバーがチケットの整合性をチェックして内容を復号化し、その情報を使用してセッションを再開します。
このように実現することで、サーバー側ではデータを保持しておく必要がありません。
ただし、TLS 1.3では、ハンドシェイク完了後にサーバはクライアントに対して新しいセッションチケットを送るようにします。このクライアントに対するチケットは、以前のセッションIDのように鍵を探すデータベースとして利用することができます。このデータは、前の接続に対応し、自身で暗号化、認証された値とすることができます。つまり、サーバは状態を持つ必要がありません。
ELBについては、種類別に以下のものに対応しています。ALBとCLBは、複数のノードで構成されますが、ノードが変わる場合にはSession Resumptionの機能がりようできず、フルハンドシェイクが行われます。
NLB : セッションチケット (ロードバランサーレベル)
ALB : セッションチケット + セッションID (ノードレベル)
ALBに対して、以下のように実行することで、セッションIDおよびセッションチケットに対応していることが分かります。
Copy $ openssl s_client -connect alb.test.hayashier.com:443 -reconnect
:
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Session-ID-ctx:
Master-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
TLS session ticket lifetime hint: 43200 (seconds)
TLS session ticket:
0000 - xx xx xx xx xx xx xx xx-xx xx xx xx xx xx xx xx ....x.x.x....,..
0010 - xx xx xx xx xx xx xx xx-xx xx xx xx xx xx xx xx ..y...y......,..
:
00a0 - xx xx xx xx xx xx xx xx-xx xx xx xx xx xx xx xx ....z.z.z....,..
-no_ticket
オプションを付与して、セッションチケットを利用しない場合、セッションチケットは利用していないことが確認できます。
Copy SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Session-ID-ctx:
Master-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Start Time: 1638592362
Timeout : 7200 (sec)
Verify return code: 0 (ok)
再ネゴシエーション
再ネゴシエーションは、セッションを維持したまま暗号方式を変更するために利用します。
再ネゴシエーションは、既に確立しているセッションを使って、サーバからクライアントへのHelloRequestと呼ばれる要請のメッセージか、クライアントからの初期ネゴシエーションと同様のClientHelloのメッセージが送られることによって開始する。
今現在は一部の特殊なユースケース等を除き、多くのユースケースでは必要とすることはないでしょう。
再ネゴシエーションの挙動を確認するためには、以下のコマンドを実行後、R
を入力します。
Copy $ openssl s_client -connect alb.test.hayashier.com:443
NLB/ALBでは再ネゴシエーションが無効化されていますが、CLBでは有効化されています。そのため、無効化状態である必要がある場合には、NLB/ALBを利用する必要があります。
NLBの場合は、以下のような結果が返ってきます。
Copy RENEGOTIATING
write:errno=54
ALBの場合は、以下のとおりです。
Copy RENEGOTIATING
4495674988:error:140040E5:SSL routines:CONNECT_CR_SRVR_HELLO:ssl handshake failure:/AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-47.140.1/libressl-2.8/ssl/ssl_pkt.c:585:
CLBの場合は、以下のとおりです。
Copy RENEGOTIATING
depth=4 C = US, O = "Starfield Technologies, Inc.", OU = Starfield Class 2 Certification Authority
verify return:1
depth=3 C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", CN = Starfield Services Root Certificate Authority - G2
verify return:1
depth=2 C = US, O = Amazon, CN = Amazon Root CA 1
verify return:1
depth=1 C = US, O = Amazon, OU = Server CA 1B, CN = Amazon
verify return:1
depth=0 CN = *.test.hayashier.com
verify return:1
SSL証明書
SSL証明書とは
そもそもSSL証明書とは、例えば、以下の特徴が挙げられます。
あるエンティティ(ここでは、サーバーの運営者)が特定の公開鍵に対応する秘密鍵を保有していることを保証するためのもの
X.509 v3 デジタル証明書が主流のフォーマット
PEM 形式で扱われることが多い : バイナリ形式(DER)の証明書を Base64 エンコード+αしたもの
一つ目の特徴を実現するにあたって、PKIの仕組みを利用します。PKI(Public Key Infrastructure)とは、信頼できる第三者機関(認証局、CA)を介することで、不特定多数の相手と事前に個別の手続きを行うことなく相手の識別と認証を実現させる仕組みです。
TLSの文脈では、ユーザーがドメイン名を利用してWebサーバーにアクセスしているとき、そのWebサーバーが当該ドメイン名を管理しているエンティティにより提供されていることを認証して確かめる仕組みとなります。
ASN.1というデータ構造やオブジェクトの定義等の方法を定めたものでデータを表現し、DERの方法でエンコーディングを行い、Base64エンコーディングでASCII形式で表現したものがPEMです。
パブリックな証明書はパブリックな認証局によって運用されています。一方でプライベート証明書はプライベート認証局で管理します。
パブリック証明書による認証は、以下の2つの段階で構成されます。
PKIの仕組みにより、証明書が信頼されたCAから発行されているか検証
検証が成功した証明書を使って、TLS ハンドシェイク中に Web サーバーを認証
すなわち、2つめの段階で、Web サーバーが証明書の所有者であることを確かめます。
認証局が予めルート証明書をブラウザベンダーやOSプロバイダーに発行しておきます。
そして、CAのルート証明書はブラウザのアプリケーションやOSの一部として配布されます。
Webサーバーの運営者は、証明書署名リクエストを認証局に行います。すると、認証局はWebサーバーに対して署名付きの証明書を渡します。
ここまでユーザーがWebサーバーにリクエストを送るまでに整っている必要があります。その後、ユーザーがWebサーバーに対してリクエストを送ると、TLSハンドシェイクの過程でWebサーバーはSSL証明書を渡します。その際、Webサーバー側は証明書に対応する秘密鍵で署名したデータもユーザーに送ります。ユーザーはその後、PKIによる証明書の検証後に、証明書の公開鍵で署名されたデータを検証することで認証が完了します。その後、TLSのセッションが確立します。
一言でまとめると、TLS通信を行う際にサーバー証明書とルート証明書、中間証明書は以下の箇所に保存されます。
中間証明書: Webサーバー(ロードバランサー、CDN 等)
サーバー証明書: Webサーバー(ロードバランサー、CDN 等)
なお、TLSネゴシエーションの際に、サーバー証明書と合わせて複数の中間証明書(証明書チェーン)が送られることもあります。このとき、TLS通信を行うクライアントでは証明書の検証にあたって複数の信頼パスを利用することが可能な状態になります。
このとき、検証でどの信頼パス、すなわち、どのルート証明書を選択するかは、Webブラウザーなどのクライアント側の実装に依存する動作になります。適切な信頼パスが選ばれない場合は、ルート証明書がインストールされているか等確認する必要があります。
証明書ストアの場所
ユーザーがWebアプリケーションにアクセスする際に参照されるルート証明書がどこに保存されているものを参照するかはブラウザ等のアプリケーションによります。
Webブラウザ
Chrome
Settings > Private and security > Security
をクリックすると、Manage certificates
を選択すると、Keychain Accessのアプリケーションが開きます。System Roots
を選択すると、MacOSにインストールされているルート証明書を確認できます。
Firefox
Settings > Private & Security
をクリックすると、Certificatesの項目でView Certificates...
が選択できます。その後、Authotiesタブを選択すると、Firefoxにインストールされているルート証明書を確認できます。
OpenSSL
macOSでは/private/etc/ssl/cert.pem
、Amazon Linux2では/etc/pki/tls/cert.pem
に格納されます。
以下のようにOPENSSLDIR
の値を参考にできます。
Copy $ openssl version -a
LibreSSL 2.8.3
built on: date not available
platform: information not available
options: bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx)
compiler: information not available
OPENSSLDIR: "/private/etc/ssl"
curl
内部的にはOpenSSLなどを利用しているので、それに応じて確認する必要があります。たとえば、以下のように確認できます。
Copy $ curl --version
curl 7.79.1 (x86_64-koji-linux-gnu) libcurl/7.79.1 OpenSSL/1.0.2k-fips zlib/1.2.7 libidn2/2.3.0 libssh2/1.4.3 nghttp2/1.41.0 OpenLDAP/2.4.44
Release-Date: 2021-09-22
Protocols: dict file ftp ftps gopher gophers http https imap imaps ldap ldaps mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB SPNEGO SSL UnixSockets
プログラミング言語
Javaの場合は、/etc/pki/ca-trust/extracted/java/cacerts
や/etc/ssl/certs/java/cacerts
などが利用されます。例えば、ルート証明書の一覧は以下のように確認します。
Copy # keytool -v -list -keystore /etc/pki/ca-trust/extracted/java/cacerts
ルート証明書をインポートする場合は以下のように実行します。
Copy # keytool -import -trustcacerts -alias YOUR_ALIAS -keystore /etc/pki/ca-trust/extracted/java/cacerts -file YOUR_CERTS_FILE
ルート証明書を削除する場合は以下のように実行します。
Copy # keytool -delete -noprompt -alias YOUR_ALIAS -keystore /etc/pki/ca-trust/extracted/java/cacerts -storepass YOUR_PASSWORD
SSL証明書の中身
実際のSSL証明書は以下のようなファイルになります。
Copy -----BEGIN CERTIFICATE-----
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END CERTIFICATE-----
証明書ファイルの中身は、大きく証明書本体と署名アルゴリズムと署名データの3つに分けられます。
証明書ファイルの中身は、大きく証明書本体と署名アルゴリズムと署名データの3つに分けられます。
証明書本体には公開鍵をはじめとする主要な情報が含まれており、TLSで認証に使用します。署名データは本体を署名アルゴリズムに従って暗号学的に生成したデータです。検証には3つすべてのデータを使用します。
先程、PEM形式とは、ASN.1というデータ構造やオブジェクトの定義等の方法を定めたものでデータを表現し、DERの方法でエンコーディングを行い、Base64エンコーディングでASCII形式で表現したものであることを説明しました。実際に、ASN.1の形式でパースすると、以下のような内容が含まれていることが分かります。最初のSEQUENCEからはしばらく証明書本体の中身に相当するものが続き、最後のSEQUENCERからは証明書アルゴリズムが続きます。最後に、BIT STRINGで署名された値になります。
Copy $ openssl asn1parse -i -in cert.pem
0:d=0 hl=4 l= 932 cons: SEQUENCE
4:d=1 hl=4 l= 652 cons: SEQUENCE
8:d=2 hl=2 l= 9 prim: INTEGER :CA2E336678056462
19:d=2 hl=2 l= 13 cons: SEQUENCE
21:d=3 hl=2 l= 9 prim: OBJECT :sha512WithRSAEncryption
32:d=3 hl=2 l= 0 prim: NULL
34:d=2 hl=3 l= 147 cons: SEQUENCE
37:d=3 hl=2 l= 11 cons: SET
39:d=4 hl=2 l= 9 cons: SEQUENCE
41:d=5 hl=2 l= 3 prim: OBJECT :countryName
46:d=5 hl=2 l= 2 prim: PRINTABLESTRING :JP
50:d=3 hl=2 l= 14 cons: SET
52:d=4 hl=2 l= 12 cons: SEQUENCE
54:d=5 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
59:d=5 hl=2 l= 5 prim: UTF8STRING :Tokyo
66:d=3 hl=2 l= 18 cons: SET
68:d=4 hl=2 l= 16 cons: SEQUENCE
70:d=5 hl=2 l= 3 prim: OBJECT :localityName
75:d=5 hl=2 l= 9 prim: UTF8STRING :Shinagawa
86:d=3 hl=2 l= 12 cons: SET
88:d=4 hl=2 l= 10 cons: SEQUENCE
90:d=5 hl=2 l= 3 prim: OBJECT :organizationName
95:d=5 hl=2 l= 3 prim: UTF8STRING :AWS
100:d=3 hl=2 l= 11 cons: SET
102:d=4 hl=2 l= 9 cons: SEQUENCE
104:d=5 hl=2 l= 3 prim: OBJECT :organizationalUnitName
109:d=5 hl=2 l= 2 prim: UTF8STRING :SE
113:d=3 hl=2 l= 31 cons: SET
115:d=4 hl=2 l= 29 cons: SEQUENCE
117:d=5 hl=2 l= 3 prim: OBJECT :commonName
122:d=5 hl=2 l= 22 prim: UTF8STRING :alb.test.hayashier.com
146:d=3 hl=2 l= 36 cons: SET
148:d=4 hl=2 l= 34 cons: SEQUENCE
150:d=5 hl=2 l= 9 prim: OBJECT :emailAddress
161:d=5 hl=2 l= 21 prim: IA5STRING :xxxxxx@xxx.xxx
184:d=2 hl=2 l= 30 cons: SEQUENCE
186:d=3 hl=2 l= 13 prim: UTCTIME :211015152029Z
201:d=3 hl=2 l= 13 prim: UTCTIME :211016152029Z
216:d=2 hl=3 l= 147 cons: SEQUENCE
219:d=3 hl=2 l= 11 cons: SET
221:d=4 hl=2 l= 9 cons: SEQUENCE
223:d=5 hl=2 l= 3 prim: OBJECT :countryName
228:d=5 hl=2 l= 2 prim: PRINTABLESTRING :JP
232:d=3 hl=2 l= 14 cons: SET
234:d=4 hl=2 l= 12 cons: SEQUENCE
236:d=5 hl=2 l= 3 prim: OBJECT :stateOrProvinceName
241:d=5 hl=2 l= 5 prim: UTF8STRING :Tokyo
248:d=3 hl=2 l= 18 cons: SET
250:d=4 hl=2 l= 16 cons: SEQUENCE
252:d=5 hl=2 l= 3 prim: OBJECT :localityName
257:d=5 hl=2 l= 9 prim: UTF8STRING :Shinagawa
268:d=3 hl=2 l= 12 cons: SET
270:d=4 hl=2 l= 10 cons: SEQUENCE
272:d=5 hl=2 l= 3 prim: OBJECT :organizationName
277:d=5 hl=2 l= 3 prim: UTF8STRING :AWS
282:d=3 hl=2 l= 11 cons: SET
284:d=4 hl=2 l= 9 cons: SEQUENCE
286:d=5 hl=2 l= 3 prim: OBJECT :organizationalUnitName
291:d=5 hl=2 l= 2 prim: UTF8STRING :SE
295:d=3 hl=2 l= 31 cons: SET
297:d=4 hl=2 l= 29 cons: SEQUENCE
299:d=5 hl=2 l= 3 prim: OBJECT :commonName
304:d=5 hl=2 l= 22 prim: UTF8STRING :alb.test.hayashier.com
328:d=3 hl=2 l= 36 cons: SET
330:d=4 hl=2 l= 34 cons: SEQUENCE
332:d=5 hl=2 l= 9 prim: OBJECT :emailAddress
343:d=5 hl=2 l= 21 prim: IA5STRING :xxxxxx@xxx.xxx
366:d=2 hl=4 l= 290 cons: SEQUENCE
370:d=3 hl=2 l= 13 cons: SEQUENCE
372:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
383:d=4 hl=2 l= 0 prim: NULL
385:d=3 hl=4 l= 271 prim: BIT STRING
660:d=1 hl=2 l= 13 cons: SEQUENCE
662:d=2 hl=2 l= 9 prim: OBJECT :sha512WithRSAEncryption
673:d=2 hl=2 l= 0 prim: NULL
675:d=1 hl=4 l= 257 prim: BIT STRING
もっとわかりやすい形で確認していきましょう。以下のコマンドを実行することで確認できます。手元に証明書ファイルがある場合は、openssl x509 -in cert.pem -noout -text
のように実行することで確認できます。
Copy $ openssl s_client -connect alb.test.hayashier.com:443 < /dev/null 2> /dev/null | openssl x509 -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
0b:cc:80:45:cd:fc:74:45:ad:b3:40:28:a8:cb:ac:5c
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, O=Amazon, OU=Server CA 1B, CN=Amazon
Validity
Not Before: Dec 1 00:00:00 2021 GMT
Not After : Dec 29 23:59:59 2022 GMT
Subject: CN=*.test.hayashier.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:dd:db:5d:e0:d4:93:aa:f9:08:74:12:15:11:27:
af:7c:ee:2a:43:f7:a2:2c:5e:93:2e:50:c4:7b:3f:
2e:70:f8:6a:a3:9d:75:e6:ea:93:30:ec:24:8b:63:
d7:03:51:3e:17:80:61:ce:ed:51:2a:a8:29:b8:9f:
3c:c0:97:8a:b7:10:53:1d:18:dd:42:62:3e:b0:16:
0a:9f:6e:ba:a2:2d:f9:6f:12:16:e3:3e:72:f8:36:
5b:95:c4:01:a7:65:7f:64:d4:66:4c:e7:df:fd:11:
cd:fe:53:3c:59:41:3f:8d:a2:0c:9a:d6:86:08:4b:
18:86:52:01:82:22:75:a1:0b:11:8b:3c:11:33:41:
ef:50:f6:01:06:84:c7:79:8a:f6:24:91:67:f5:06:
03:6d:78:fc:e3:5f:a9:39:f1:ef:8b:f8:cb:fe:f1:
71:5f:3d:be:b3:93:bd:ce:d3:07:a6:24:7c:82:07:
5b:22:03:40:3a:cf:1a:da:b2:46:3f:e6:2a:59:4d:
ff:df:b8:a5:77:dc:ff:ca:b7:4a:9f:6d:d8:9a:a6:
c0:79:73:89:6e:70:54:1b:69:39:04:fd:59:c8:06:
87:40:23:0c:c9:36:ef:38:ae:d5:86:3a:e8:3b:28:
18:66:c8:c3:bc:55:cc:20:a6:54:12:b1:16:b2:15:
91:ab
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Authority Key Identifier:
keyid:59:A4:66:06:52:A0:7B:95:92:3C:A3:94:07:27:96:74:5B:F9:3D:D0
X509v3 Subject Key Identifier:
96:04:82:AB:B4:83:C8:97:65:4F:48:9E:F1:29:3A:0C:5B:64:87:4C
X509v3 Subject Alternative Name:
DNS:*.test.hayashier.com, DNS:test.hayashier.com
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 CRL Distribution Points:
Full Name:
URI:http://crl.sca1b.amazontrust.com/sca1b-1.crl
X509v3 Certificate Policies:
Policy: 2.23.140.1.2.1
Authority Information Access:
OCSP - URI:http://ocsp.sca1b.amazontrust.com
CA Issuers - URI:http://crt.sca1b.amazontrust.com/sca1b.crt
X509v3 Basic Constraints: critical
CA:FALSE
1.3.6.1.4.1.11129.2.4.2:
...j.h.v.)y...99!.Vs.c.w..W}.`
........}sX.......G0E. '...&..!Ig'.......7."x..m...OU...!....c...3u.....*.x;......6...W..x.v.A...."FJ...:.B.^N1.....K.h..b......}sX.c.........I*.3.Q..&..!.....-.G"...;.#h@PDi..*.....?K..G
Signature Algorithm: sha256WithRSAEncryption
6a:b0:93:0b:79:c2:60:90:8f:a5:6e:0f:de:e0:66:63:32:6e:
42:b9:69:6a:80:43:27:1c:d4:b5:59:81:40:c1:c8:9e:7a:4a:
62:e8:47:4b:7c:df:f7:a0:a9:5a:02:a8:d4:61:79:00:4a:7c:
31:da:17:94:be:b9:d3:67:e2:56:84:17:6d:5c:ae:a3:8a:91:
ba:b8:26:ae:0c:f3:c2:f2:84:fe:0e:87:a9:8f:be:db:34:62:
02:3f:1b:3c:55:ec:7d:d9:ea:ef:53:ae:8d:74:50:d2:99:4b:
85:12:fa:08:61:01:51:6a:43:bf:01:40:4c:25:08:9a:20:55:
1d:54:d1:4d:6a:c8:e1:a7:f0:d9:6e:88:d3:11:01:29:af:39:
0c:d7:64:71:38:e8:ff:99:b8:8b:98:d5:3f:d4:4f:15:32:85:
25:9b:6d:16:c2:a2:b4:f5:92:42:06:68:c0:11:0c:38:6b:85:
e5:aa:52:9e:e2:f2:4a:3c:79:87:34:88:27:f6:1e:9d:52:41:
d1:11:b2:90:f6:ca:1a:76:6b:2f:46:d3:8c:71:66:76:30:cd:
b2:a3:2a:57:e4:03:cc:fb:27:7d:e7:0d:16:c7:f5:ef:9d:33:
94:00:f2:99:f2:7b:26:a4:9a:a6:30:55:2d:3f:ec:cb:08:d9:
26:1d:6b:63
自己署名証明書の情報を確認します。ここでは、拡張情報は確認できないことが分かります。
Copy $ openssl s_client -connect alb.test.hayashier.com:443 < /dev/null 2> /dev/null | openssl x509 -noout -text
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 17654627072782306786 (0xf501d5c8d32f0de2)
Signature Algorithm: sha512WithRSAEncryption
Issuer: C=JP, ST=Tokyo, L=Shinagawa, O=AWS, OU=SE, CN=alb.test.hayashier.com/emailAddress=xxxxxx@xxx.xxx
Validity
Not Before: Oct 15 16:38:49 2021 GMT
Not After : Oct 16 16:38:49 2021 GMT
Subject: C=JP, ST=Tokyo, L=Shinagawa, O=AWS, OU=SE, CN=alb.test.hayashier.com/emailAddress=xxxxxx@xxx.xxx
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:c7:7f:97:df:b0:dd:a8:0d:db:b0:47:c1:7e:5c:
97:95:5b:7f:4b:88:0b:af:2d:5a:0a:5e:8f:87:cd:
29:39:18:90:f7:7a:26:c0:23:f0:1a:12:a5:e9:d9:
20:56:62:d2:c7:02:38:65:33:6f:ed:73:1a:2e:cc:
04:51:e3:27:aa:bb:e5:e0:59:8e:ea:e6:3b:fe:6b:
8d:07:c3:8d:7a:ab:5e:2e:2f:ea:52:3a:a8:09:3c:
3d:95:6c:36:f9:c0:cc:8c:25:16:65:d2:3d:79:03:
34:12:22:bb:2f:4d:e5:81:a4:0e:0d:9b:47:ea:f4:
b9:e2:65:a6:d6:a7:38:d0:26:da:4f:b9:ea:f8:9f:
9c:96:92:70:ba:f1:9a:c5:ce:61:60:1c:a1:c2:27:
9a:91:ac:48:21:39:4f:b1:17:ac:a0:3b:75:27:c8:
39:7a:03:cf:89:70:d9:4d:e6:1a:6a:7c:c4:db:07:
82:ea:aa:b2:cb:4c:3a:c2:b0:01:fe:e3:20:8c:c5:
13:b6:70:a4:4d:5c:b3:8e:75:bc:66:aa:af:e3:a9:
35:50:9f:ca:e7:f8:a7:35:fc:b9:ff:44:16:9f:23:
4f:d1:2f:d2:ad:83:86:39:c0:0e:1c:6b:83:cc:e1:
ef:ec:74:a3:e0:e3:e2:5b:76:f5:ca:b7:73:df:ac:
de:45
Exponent: 65537 (0x10001)
Signature Algorithm: sha512WithRSAEncryption
65:08:dc:fd:2d:8f:df:92:bf:49:07:ec:9b:8a:71:0b:78:e0:
e2:36:6d:80:33:e1:fe:6d:ef:2b:44:5c:8f:c6:cb:7e:16:8d:
ff:ca:5c:68:ec:af:85:f9:a4:42:4a:1a:11:d4:0d:4f:04:0c:
fd:d9:13:fa:39:e7:94:a8:c0:d2:6a:7a:1c:4a:1d:16:e7:c8:
99:39:59:5e:8c:80:7a:59:71:56:23:14:08:fd:33:d6:2d:bf:
0e:4f:64:53:e8:12:7e:93:f1:f1:7f:03:9c:ee:bf:be:e7:b0:
53:38:d6:ec:6a:a8:a7:b0:90:b0:95:30:6a:7b:05:ff:f1:e0:
4d:e7:5a:40:d9:1d:e7:d8:45:03:4c:cb:3b:bf:90:58:58:51:
7b:d1:28:be:60:dc:62:c5:15:f4:8f:ad:06:34:3f:d2:df:19:
af:8d:92:34:e2:6c:ca:8e:63:ca:32:82:c9:6f:8f:68:72:18:
11:af:16:f8:00:90:e7:d8:fe:25:88:14:75:1b:a1:96:74:29:
3d:57:bd:7a:e9:7c:fd:6c:68:f3:a8:e8:b2:83:34:b9:d6:2b:
02:e7:5c:45:90:f3:98:01:4f:f5:e3:86:83:b8:18:38:d5:b8:
0e:27:89:c8:f0:22:ea:a3:71:8b:ae:29:83:6b:95:86:03:96:
d3:a2:51:58
最初にDataという証明書本体の中身があり、最後にSignature Algorithmで証明アルゴリズムとそれを利用したデジタル署名があることが確認できます。デジタル署名の部分にはData部を認証局の秘密鍵を使って計算したものが入ります。ただし時間の短縮のため、ダイジェスト方式が用いられます。 これにより、証明書のデジタル署名の部分には、上記のDataの部分を MD5などのハッシュ関数を用いてハッシュ値(メッセージダイジェスト)を得て、それを秘密鍵で暗号化したものがデジタル署名のところに入ります。
Data以降ではしばらく証明書本体の中身が続きます。項目をまとめると以下の内容になります。
基本情報
公開鍵 : Subject Public Key Info
拡張情報
機関鍵識別子 : Authority Key Identifier
所有者鍵識別子 : Subject Key Identifier
拡張鍵用途 : Extended Key Usage
所有者別名 : Subject Alternative Name
失効リスト配布点 : CRL Distribution Points
機関情報アクセス : Authority Information Access
検証
上記、証明書本体の中身のうち、検証の段階では以下のデータを使用します。
基本情報
公開鍵 : Subject Public Key Info
拡張情報
機関鍵識別子 : Authority Key Identifier
所有者鍵識別子 : Subject Key Identifier
発行者(Issuer)には証明書を発行した認証局の名前が入ります。発行機関と証明する内容などについては、C=JP, ST=Tokyo, L=Shinagawa, O=AWS, OU=SE, CN=alb.test.hayashier.com/emailAddress=xxxxxx@xxx.xxx
ように書かれていますが、これはディレクトリシステムの仕様X.500に基づいた表現です。
所有者(Subject)には証明書の所有者の名前が入ります。ACMの場合はWebサーバーが使用するドメイン名が入ります。
公開鍵は、サーバー証明書の場合、Web サーバーが使う秘密鍵と対応する公開鍵が入ります。
上位の認証局の証明書とサーバー証明書の情報は関係性を持ちます。
上位の認証局の証明書の所有者(Subject)は、サーバー証明書の発行者(Issuer)と同じ値です。
上位の認証局の証明書の所有者鍵識別子(SKI)は、サーバー証明書の機関鍵識別子(AKI)と同じ値です。
上位の認証局の証明書およびサーバー証明書の所有者鍵識別子(SKI)は、上位の認証局の証明書の公開鍵に対する一意の識別子で、通常ハッシュ値が使用されます。
サーバー証明書の署名は、上位の認証局の証明書の秘密鍵とサーバー証明書から計算します。すなわち、検証する際は、上位の認証局の証明書の公開鍵とサーバー証明書で行います。
認証
認証の段階では、証明書本体の中身のうち、公開鍵(認証局の証明書の公開鍵のみ)もしくは所有者別名(SAN)を使用します。
基本情報
公開鍵 : Subject Public Key Info
拡張情報
所有者別名 : Subject Alternative Name
認証にはデジタル署名を活用します。アクセスしている相手が、サーバー証明書の公開鍵に対応する秘密鍵を持っていることで確かめます。
有効性
証明書の有効性の確認も行われます。その際、証明書本体の中身のうち、以下の情報を利用します。
拡張情報
拡張鍵用途 : Extended Key Usage
失効リスト配布点 : CRL Distribution Points
機関情報アクセス : Authority Information Access
CRLとOCSPは証明書の失効状況確認に使用します。実際にこちらを活用して、失効状況の確認を行うかはクライアントに依存します。
CRLとは有効期限よりも前に失効させたデジタル証明書の一覧です。例えば、証明書の誤発行や証明書の秘密鍵紛失で悪用されるのを回避するために利用されます。デジタル証明書の受け取り側は、デジタル証明書とCRLを照合することで証明書が現在も有効であるかを確認できます。CRLは認証局から定期的に最新情報が配布されます。クライアントは、Webサイトなどから受信したサーバ証明書のシリアル番号とCRLに登録された証明書のシリアル番号を照合して有効性を確認できます。
OCSPはX.509公開鍵証明書の失効状態を取得するための通信プロトコルです。CRLの手法の代替手段として策定された実装です。OCSPクライアントがOCSPサーバ(OCSPレスポンダ)に対してデジタル証明書の有効性を確認します。
サーバー証明書の種類
DV証明書 : ドメイン認証
認証局の人は対象ドメインを管理する権限があるかのみを確認
OV証明書 : 企業認証
ドメインの管理権に加え、運営組織の実在性などを電話などにより確認
EV証明書
OV証明書と同様の確認を行うが、確認方法が国際的な認定基準に基づいて行われる
証明書の検証の仕組み
サーバー証明書発行時
サーバー証明書を発行するにあたって、以下の流れで対応します。
ルート認証局と中間認証局は、それぞれ自身の証明書に対応する秘密鍵と公開鍵を持っています。
ユーザーは証明書作成のために、公開鍵と秘密鍵のペアを作成します。
その鍵ペアを使って、CSR(署名要求) を作成します。作成したCSRで、電子証明書の発行依頼を中間認証局に行う
中間認証局はCSRの記載事項が正しいことを確認する。
ACMの場合、秘密鍵の生成、CSR生成、証明書の発行をマネージドに提供します。3つめの証明書の正しいことの確認は、DNS検証やEメール検証をします。
信頼チェーン(Chain of Trust)
検証するにあたっては、サーバー証明書からルート証明書までの証明書パスを探します。この信頼チェーンを通して、ルート証明書は既にローカルで信頼できるものとして認識しているので、サーバー証明書を確認することで、検証が可能になります。
サーバー証明書発行時に、以下の仕組みができています。この仕組みを利用して検証します。
ルート認証局の秘密鍵を使って、自身のルート証明書に署名(自己署名)することでルート認証局が自身を正しいことを保証するものとする
ルート認証局の秘密鍵を使って中間証明書に署名することで中間認証局が正しいことを保証
中間認証局の秘密鍵を使ってデジタル証明書に署名することでデジタル証明書に書かれたホスト名の機器は中間認証局が正しいことを保証
これによって、検証時は以下の流れで信頼チェーンを探すことができます。
中間認証局の公開鍵を使って、サーバー証明書の電子署名を復号し、実際のデジタル証明書のハッシュ値を計算したものと比較し、正当性を確認することで検証
ルート証明書の公開鍵を使って、中間証明書の電子署名を復号し、実際のデジタル証明書のハッシュ値を計算したものと比較し、正当性を確認することで検証
ルート証明書の公開鍵を使って、ルート証明書の電子署名を復号し、実際のデジタル証明書のハッシュ値を計算したものと比較し、正当性を確認することで検証
証明書パスを見つけるにあたって以下の方法があります。
中間証明書は、サーバー証明書をインストールする際に、サーバー証明書と中間証明書を一つのファイルとしてつなげることで、
中間証明書も一緒にインストールするのが一般的です。ルート証明書のように信頼ストアにインストールされていることも多いですが、そうではないこともよくあることが理由です。
そのため、上記理由でローカルの信頼ストアはあまり使われず、サーバーから送信される証明書チェーンが基本的に使われます。
キーペアの中身
RSAの場合におけるキーペアの確認を確認します。
公開鍵の場合は以下のような内容になります。
Copy $ openssl rsa -in public.pem -text -noout -pubin
Public-Key: (2048 bit)
Modulus:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
Exponent: 65537 (0x10001)
公開鍵の場合は以下のような内容になります。
Copy $ openssl rsa -in private.pem -text -noout
Private-Key: (2048 bit)
modulus:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
publicExponent: 65537 (0x10001)
privateExponent:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
prime1:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
prime2:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
exponent1:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
exponent2:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
coefficient:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:
ルート認証局と中間認証局が分かれている理由
信頼されたルート証明書は一度その秘密鍵が漏れてしまうと世界中のクライアントに影響が出てしまいます。その場合は速やかにそのルート証明書を失効し、新たな証明書を生成し、クライアントに配布する必要があります。
2階層だった場合、証明書を発行した上位認証局の証明書はルート証明書であるため、こちらを無効化することになりますが、それを実行した場合、発行した全ての証明書が無効になります。これでは影響範囲が大きいため、間に中間認証局を挟み、3階層にします。
ルート認証局はオフラインで構築しておき、別途構築した複数の中間認証局へ、それぞれ中間証明書を発行します。
自己証明書
ルート認証局が証明した証明書がある一方で、自己証明証明書とは所有者自身で署名した証明書になります。
前者がパブリック向けの使用に適しているのに対して、後者はクローズドな環境のみの利用に適しています。
前者であれば、信頼ストアにルート証明書を持っている、もしくはOSの信頼ストアを利用しているブラウザで基本的に信頼されていますが、後者では公開鍵を手動でインポートするまで信頼されません。
これに伴い、ルート認証局が署名した証明書では証明書の更新や修正はブラウザ側の変更は必要ありませんが、自己署名証明では更新や修正があるごとに新しい証明書をインポートし直す必要があります。
自己署名証明書は以下のように作成できます。
Copy $ openssl genrsa 2048 > private.pem
$ openssl req -new -x509 -key private.pem -sha512 -days 1 -out cert.pem
公開鍵を作成する場合は以下
Copy $ openssl rsa -pubout < private.pem > public.pem
ACMにインポートする場合は、以下の手順で実行します。
Copy $ aws acm import-certificate --certificate file://cert.pem --private-key file://private.pem
$ aws acm describe-certificate --certificate-arn arn:aws:acm:ap-northeast-1:...
クロス証明書
ルート証明書から発行されたサーバ証明書を別のルート証明書が設定されているクライアントでも利用できるようにする仕組みです。
サーバー証明書と合わせて複数の中間証明書(証明書チェーン)が送信される場合もあります。これにより、TLS通信を行うクライアントでは証明書の検証にあたって複数の信頼パスを利用できます。このとき、検証でどの信頼パスもしくはルート証明書を選択するかは、Webブラウザーなどのクライアントに依存します。必要なルート証明書がインストールされていない場合や、不要な証明書チェーンが含まれている場合、提供されている証明書パスを利用するように証明書チェーンを再構築していない場合などに、意図しないルート証明書を選択することもあります。
例えば、新しい認証局を立ち上げる場合やルート証明書の移行、古くからあるルート証明書しか使えないクライアントに対して証明書を利用できるようにするといった場合に使用します。
ある証明書に対して、検証先の上位の証明書が分岐している場合、その証明書のIssuerと一致するSubjectおよびAKIと一致するSKIを持つ証明書が複数あります。すなわち、それらの証明書のSubjectやSKI(もしくは公開鍵)は同じ値を持ちます。Issuerは異なります。
Topics
トラブルシューティング
以上を踏まえて、TLSハンドシェイクに失敗する理由としては、例えば以下のようなものが挙げられます。TLS接続関連の問題のトラブルシューティングの際には参考になるかもしれません。
ネゴシエーションエラー
サーバー側の暗号スイートがクライアント側になく一致しない
サーバー側の暗号スイートのリストが新しく、クライアント側が保持しているリストが古い場合
証明書の問題(サーバー証明書、クライアント証明書)
CN、ドメインの不一致
親ドメインのワイルドカード指定は、親ドメインとは一致しない
間違った証明書(そもそもアップロードができないこともある)
秘密鍵
暗号化(パスワードやパスフレーズで保護)された秘密鍵
証明書、秘密鍵、証明書チェーンがPEMエンコードされていない
チェーン内の中間証明書が正しい順序
チェーンの最初の証明書はサーバー証明書を発行したCAの証明書でないといけない
SNI対応
クライアントがSNI未対応(ALBの場合デフォルト証明書が選ばれる)
openssl s_client
の-servername
オプションの未指定
SMTPやPostgresなどのプロトコル
クライアントのClientHelloの前にいくつかのプロトコル変換が行われる
ELBはこれに対応していない
TCPリスナーを使用し、バックエンドインスタンス側で対応する必要がある
TLS通信の解読
TLS通信解読の方法は状況に応じていくつか方法があります。いずれの場合も第三者から通信を容易に読み取られるといった類のものではなく、デバッグなどの用途に使用するものです。
SSLKKEYLOGFILE変数を用いた方法
この方法はクライアント側で準備をしておくことにより、自身が行ったTLS通信の中身を確認するものです。このとき、SSL証明書の秘密鍵等は事前に準備する必要はありません。
以下のようにSSLKEYLOGFILE
環境変数でログの出力先を指定したあとに、実際に解読対象の通信を行う。すると、変数に指定したログにデータが書き込まれる。
Copy $ export SSLKEYLOGFILE=/home/ubuntu/sslkeylog.log
# ここでたとえば下記のように対象の通信を行う。
# $ curl https://hayashier.com
$ cat sslkeylog.log
CLIENT_RANDOM xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Wiresharkで、Preferences... > Protocols > TLS の画面を開き、(Pre)-Master-Secret log filename
で上記ファイルを指定。TLS debug file
はデバッグログ出力するログのパス。うまくキャプチャできない場合に活用できる。
すると、TLSの通信も以下のように中身が見られるようになります。
Copy 1 2021-10-15 16:47:23.601334 172.31.5.148 44.237.150.182 TCP 74 35686 → 443 [SYN] Seq=0 Win=62727 Len=0 MSS=8961 SACK_PERM=1 TSval=3293266384 TSecr=0 WS=128
2 2021-10-15 16:47:23.601709 44.237.150.182 172.31.5.148 TCP 74 443 → 35686 [SYN, ACK] Seq=0 Ack=1 Win=26847 Len=0 MSS=1460 SACK_PERM=1 TSval=2439383746 TSecr=3293266384 WS=256
3 2021-10-15 16:47:23.601722 172.31.5.148 44.237.150.182 TCP 66 35686 → 443 [ACK] Seq=1 Ack=1 Win=62848 Len=0 TSval=3293266384 TSecr=2439383746
4 2021-10-15 16:47:23.608216 172.31.5.148 44.237.150.182 TLSv1.2 583 Client Hello
5 2021-10-15 16:47:23.608509 44.237.150.182 172.31.5.148 TCP 66 443 → 35686 [ACK] Seq=1 Ack=518 Win=28160 Len=0 TSval=2439383753 TSecr=3293266391
6 2021-10-15 16:47:23.613762 44.237.150.182 172.31.5.148 TLSv1.2 2406 Server Hello, Certificate, Server Key Exchange, Server Hello Done
7 2021-10-15 16:47:23.613777 172.31.5.148 44.237.150.182 TCP 66 35686 → 443 [ACK] Seq=518 Ack=2341 Win=60544 Len=0 TSval=3293266397 TSecr=2439383758
8 2021-10-15 16:47:23.614293 172.31.5.148 44.237.150.182 TLSv1.2 192 Client Key Exchange, Change Cipher Spec, Finished
9 2021-10-15 16:47:23.615913 44.237.150.182 172.31.5.148 TLSv1.2 117 Change Cipher Spec, Finished
10 2021-10-15 16:47:23.615921 172.31.5.148 44.237.150.182 TCP 66 35686 → 443 [ACK] Seq=644 Ack=2392 Win=60544 Len=0 TSval=3293266399 TSecr=2439383760
11 2021-10-15 16:47:23.615974 44.237.150.182 172.31.5.148 HTTP2 135 SETTINGS[0], WINDOW_UPDATE[0]
12 2021-10-15 16:47:23.615976 172.31.5.148 44.237.150.182 TCP 66 35686 → 443 [ACK] Seq=644 Ack=2461 Win=60544 Len=0 TSval=3293266399 TSecr=2439383760
13 2021-10-15 16:47:23.616043 172.31.5.148 44.237.150.182 HTTP2 119 Magic
14 2021-10-15 16:47:23.616049 172.31.5.148 44.237.150.182 HTTP2 122 SETTINGS[0]
15 2021-10-15 16:47:23.616063 172.31.5.148 44.237.150.182 HTTP2 108 WINDOW_UPDATE[0]
16 2021-10-15 16:47:23.616091 172.31.5.148 44.237.150.182 HTTP2 140 HEADERS[1]: GET /
17 2021-10-15 16:47:23.616111 172.31.5.148 44.237.150.182 HTTP2 104 SETTINGS[0]
18 2021-10-15 16:47:23.616529 44.237.150.182 172.31.5.148 TCP 66 443 → 35686 [ACK] Seq=2461 Ack=907 Win=28160 Len=0 TSval=2439383761 TSecr=3293266399
19 2021-10-15 16:47:23.616696 44.237.150.182 172.31.5.148 HTTP2 104 SETTINGS[0]
20 2021-10-15 16:47:23.616698 172.31.5.148 44.237.150.182 TCP 66 35686 → 443 [ACK] Seq=907 Ack=2499 Win=60544 Len=0 TSval=3293266399 TSecr=2439383761
21 2021-10-15 16:47:23.649782 44.237.150.182 172.31.5.148 HTTP2 808 HEADERS[1]: 200 OK, DATA[1]
22 2021-10-15 16:47:23.649783 44.237.150.182 172.31.5.148 HTTP2 104 DATA[1] (text/html)
23 2021-10-15 16:47:23.649811 172.31.5.148 44.237.150.182 TCP 66 35686 → 443 [ACK] Seq=907 Ack=3241 Win=59904 Len=0 TSval=3293266433 TSecr=2439383793
24 2021-10-15 16:47:23.649816 172.31.5.148 44.237.150.182 TCP 66 35686 → 443 [ACK] Seq=907 Ack=3279 Win=59904 Len=0 TSval=3293266433 TSecr=2439383793
25 2021-10-15 16:47:23.650796 172.31.5.148 44.237.150.182 TLSv1.2 97 Alert (Level: Warning, Description: Close Notify)
26 2021-10-15 16:47:23.651117 44.237.150.182 172.31.5.148 TCP 66 443 → 35686 [FIN, ACK] Seq=3279 Ack=938 Win=28160 Len=0 TSval=2439383795 TSecr=3293266434
27 2021-10-15 16:47:23.651408 172.31.5.148 44.237.150.182 TCP 66 35686 → 443 [FIN, ACK] Seq=938 Ack=3280 Win=59904 Len=0 TSval=3293266434 TSecr=2439383795
28 2021-10-15 16:47:23.651658 44.237.150.182 172.31.5.148 TCP 66 443 → 35686 [ACK] Seq=3280 Ack=939 Win=28160 Len=0 TSval=2439383796 TSecr=3293266434
次にtsharkにおける実行方法にも触れます。
tsharkをインストールするため、Macの場合は以下のようにWireshark付属の形でインストールします。
Copy $ brew install --cask wireshark
tsharkの場合は以下のように実行します。GUIで既に解読している場合は設定を解除しておいてください。GUIの方で設定していると特にキーログファイルを指定しなくても解読されます。
Copy $ tshark \
-r ./ssldecrypt.pcap \
-o "tls.keylog_file:./sslkeylog.log" \
-o "tls.debug_file:./tlsdebug.log"
すると、以下のように通信が見られるようになります。
Copy 1 0.000000 172.31.5.148 → 44.237.150.182 TCP 74 35686 → 443 [SYN] Seq=0 Win=62727 Len=0 MSS=8961 SACK_PERM=1 TSval=3293266384 TSecr=0 WS=128
2 0.000375 44.237.150.182 → 172.31.5.148 TCP 74 443 → 35686 [SYN, ACK] Seq=0 Ack=1 Win=26847 Len=0 MSS=1460 SACK_PERM=1 TSval=2439383746 TSecr=3293266384 WS=256
3 0.000388 172.31.5.148 → 44.237.150.182 TCP 66 35686 → 443 [ACK] Seq=1 Ack=1 Win=62848 Len=0 TSval=3293266384 TSecr=2439383746
4 0.006882 172.31.5.148 → 44.237.150.182 TLSv1 583 Client Hello
5 0.007175 44.237.150.182 → 172.31.5.148 TCP 66 443 → 35686 [ACK] Seq=1 Ack=518 Win=28160 Len=0 TSval=2439383753 TSecr=3293266391
6 0.012428 44.237.150.182 → 172.31.5.148 TLSv1.2 2406 Server Hello, Certificate, Server Key Exchange, Server Hello Done
7 0.012443 172.31.5.148 → 44.237.150.182 TCP 66 35686 → 443 [ACK] Seq=518 Ack=2341 Win=60544 Len=0 TSval=3293266397 TSecr=2439383758
8 0.012959 172.31.5.148 → 44.237.150.182 TLSv1.2 192 Client Key Exchange, Change Cipher Spec, Finished
9 0.014579 44.237.150.182 → 172.31.5.148 TLSv1.2 117 Change Cipher Spec, Finished
10 0.014587 172.31.5.148 → 44.237.150.182 TCP 66 35686 → 443 [ACK] Seq=644 Ack=2392 Win=60544 Len=0 TSval=3293266399 TSecr=2439383760
11 0.014640 44.237.150.182 → 172.31.5.148 HTTP2 135 SETTINGS[0], WINDOW_UPDATE[0]
12 0.014642 172.31.5.148 → 44.237.150.182 TCP 66 35686 → 443 [ACK] Seq=644 Ack=2461 Win=60544 Len=0 TSval=3293266399 TSecr=2439383760
13 0.014709 172.31.5.148 → 44.237.150.182 HTTP2 119 Magic
14 0.014715 172.31.5.148 → 44.237.150.182 HTTP2 122 SETTINGS[0]
15 0.014729 172.31.5.148 → 44.237.150.182 HTTP2 108 WINDOW_UPDATE[0]
16 0.014757 172.31.5.148 → 44.237.150.182 HTTP2 140 HEADERS[1]: GET /
17 0.014777 172.31.5.148 → 44.237.150.182 HTTP2 104 SETTINGS[0]
18 0.015195 44.237.150.182 → 172.31.5.148 TCP 66 443 → 35686 [ACK] Seq=2461 Ack=907 Win=28160 Len=0 TSval=2439383761 TSecr=3293266399
19 0.015362 44.237.150.182 → 172.31.5.148 HTTP2 104 SETTINGS[0]
20 0.015364 172.31.5.148 → 44.237.150.182 TCP 66 35686 → 443 [ACK] Seq=907 Ack=2499 Win=60544 Len=0 TSval=3293266399 TSecr=2439383761
21 0.048448 44.237.150.182 → 172.31.5.148 HTTP2 808 HEADERS[1]: 200 OK, DATA[1]
22 0.048449 44.237.150.182 → 172.31.5.148 HTTP2 104 DATA[1] (text/html)
23 0.048477 172.31.5.148 → 44.237.150.182 TCP 66 35686 → 443 [ACK] Seq=907 Ack=3241 Win=59904 Len=0 TSval=3293266433 TSecr=2439383793
24 0.048482 172.31.5.148 → 44.237.150.182 TCP 66 35686 → 443 [ACK] Seq=907 Ack=3279 Win=59904 Len=0 TSval=3293266433 TSecr=2439383793
25 0.049462 172.31.5.148 → 44.237.150.182 TLSv1.2 97 Alert (Level: Warning, Description: Close Notify)
26 0.049783 44.237.150.182 → 172.31.5.148 TCP 66 443 → 35686 [FIN, ACK] Seq=3279 Ack=938 Win=28160 Len=0 TSval=2439383795 TSecr=3293266434
27 0.050074 172.31.5.148 → 44.237.150.182 TCP 66 35686 → 443 [FIN, ACK] Seq=938 Ack=3280 Win=59904 Len=0 TSval=3293266434 TSecr=2439383795
28 0.050324 44.237.150.182 → 172.31.5.148 TCP 66 443 → 35686 [ACK] Seq=3280 Ack=939 Win=28160 Len=0 TSval=2439383796 TSecr=3293266434
RSA秘密鍵を登録する方法
SSL証明書の秘密鍵等は事前に準備できる場合に、利用できる方法です。
この場合もいくつか方法がありますが、たとえば、以下の3つの方法で秘密鍵を登録することができます。
Wireshark > Preferences... > RSA Keys を選択後、Add new keyfile...
Wireshark > Preferences... > Protocols > TLSを選択後、RSA Keys list
対象のTLS通信のパケットを右クリック > Protocol Preferences > Transport Layer Security > RSA keys list....
以下の記事で上記3つの方法のうち、最後の方法を利用した解説をしています。
##################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################
Topics
TLS拡張
SNI
接続テスト
Copy $ openssl s_client -connect alb.test.hayashier.com:443 -servername alb.test.hayashier.com
SNIが利用できない場合は、SANを利用したり、リスナーやロードバランサーを分ける等の対応が必要になります。
NPN
ALPN
TLS False Start
TLS 再ネゴシエーション
OCSPステープリング
セッションチケット
Certificate Transparency
Public Key Pinning
Slide 22
ssldumpのやり方は古い?うまくいかず
Copy $ sudo apt install ssldump -y
$ ssldump -v
ssldump 1.0
Copyright (C) 1998-2001 RTFM, Inc.
All rights reserved.
Compiled with OpenSSL: decryption enabled
ダンプしても解読されない
Copy $ sudo ssldump -d -k ~/private.pem port 443 and host alb.test.hayashier.com
New TCP connection #1: ip-172-31-5-148.us-west-2.compute.internal(58156) <-> ec2-44-240-232-112.us-west-2.compute.amazonaws.com(443)
1 1 0.0073 (0.0073) C>S Handshake
ClientHello
Version 3.3
resume [32]=
52 ba 08 9f b3 3c 46 ce c1 20 25 43 ac e5 24 6f
f5 31 95 60 3a 2a e4 be 2e b1 0e 65 0c 11 a1 f5
cipher suites
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_DHE_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_EMPTY_RENEGOTIATION_INFO_SCSV
compression methods
NULL
extensions
server_name
host_name: alb.test.hayashier.com
next_protocol_negotiation
application_layer_protocol_negotiation
encrypt_then_mac
extended_master_secret
signature_algorithms
1 2 0.0135 (0.0062) S>C Handshake
ServerHello
Version 3.3
session_id[32]=
bd 2b 71 9f 0e 32 b4 69 72 96 fd 3c 5a 05 1f 9b
fa 64 3d b5 71 b7 4b 2b a1 ff 95 ce c8 c1 a1 ca
cipherSuite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
compressionMethod NULL
extensions
application_layer_protocol_negotiation
1 3 0.0135 (0.0000) S>C Handshake
Certificate
1 4 0.0135 (0.0000) S>C Handshake
ServerKeyExchange
Not enough data. Found 327 bytes (expecting 32767)
1 5 0.0135 (0.0000) S>C Handshake
ServerHelloDone
1 6 0.0141 (0.0005) C>S Handshake
ClientKeyExchange
DiffieHellmanClientPublicValue[65]=
04 0b a6 93 d2 b4 e8 d0 e3 74 4d 90 24 94 10 46
cd b7 ec 6b 94 b4 df 0e ad 41 a5 7d ea 08 c3 5f
c1 78 ec 23 65 95 23 5c 44 16 b4 c4 70 b4 39 ee
dc 10 ac 0f 9b ac 82 98 5b 98 09 dd 04 c7 5a 23
8d
1 7 0.0141 (0.0000) C>S ChangeCipherSpec
1 8 0.0141 (0.0000) C>S Handshake
1 9 0.0164 (0.0022) S>C ChangeCipherSpec
1 10 0.0164 (0.0000) S>C Handshake
1 11 0.0165 (0.0001) S>C application_data
1 12 0.0166 (0.0000) C>S application_data
1 13 0.0166 (0.0000) C>S application_data
1 14 0.0166 (0.0000) C>S application_data
1 15 0.0166 (0.0000) C>S application_data
1 16 0.0166 (0.0000) C>S application_data
1 17 0.0175 (0.0008) S>C application_data
1 18 0.0213 (0.0037) S>C application_data
1 19 0.0213 (0.0000) S>C application_data
1 20 0.0216 (0.0002) C>S Alert
1 0.0222 (0.0005) C>S TCP FIN
1 0.0226 (0.0003) S>C TCP FIN
解読されたらこうなるはず
https://fm4dd.com/openssl/https-analyzing.shtm
TLS 1.3
NLBではTLS 1.3対応した。ALBもTLS 1.3対応予定。Bootcampのころには対応しているかも
バージョン 1.2 との違いは、大きく以下の 3 つで
セッションのリネゴシエーションや再開に関する脆弱性のある方式を廃止し、セッション再開については新たな方式を採用
ネゴシエーション (handshake) シーケンスの大幅な変更
1の暗号アルゴリズムについては、ストリーム暗号 (RC4)、CBC ブロック暗号などの問題がある古い暗号アルゴリズムを廃止し、AEAD (認証付き暗号) 方式が要求されるようになりました。
また、静的な公開鍵を使う鍵交換方式 (RSA による鍵交換や、Static DH) は廃止となりました。(デジタル署名としての RSA は引き続き有用な方式として利用可能です)
つまり鍵交換には必ず Ephemeral Diffie-Hellman (DHE) および Ephemeral Elliptic Curve Diffie-Hellman (ECDHE) のどちらかが使われることになりました。
2については脆弱性のあったリネゴシエーションや圧縮、"Session ID" や "Session Ticket" を使ったセッション再開などが廃止となりました。厳密に言うと、Session Ticket は PSK (Pre Shared Key) と統合されました。
3について、TLS v1.3 のシーケンスの変更は、Google が開発した SPDY や QUIC の思想に影響されたものであり、さらに QUIC との融合を果たす予定の HTTP/3 へとつなげるためのものだと考えています。これらは全てセキュアかつ高速な Web 通信を目指し、最適なプロトコルを模索したプロセスでもあります。
Google は SPDY を開発した 2009 年頃から、RTT (Round Trip Time: 通信の往復時間) の影響を少なくすること (具体的にはネゴシエーションによる往復を極力少なくすること) が帯域を増やすよりも重要であることを主張してきました。SPDY や QUIC の開発、今回の TLS のシーケンス変更もその流れに沿うものです。
TLS v1.2 と v1.3 のシーケンス, Handshake の比較
TLS v1.3 においてはデータ送信までのネゴシエーションの往復が 1 回減っているのが分かります。
Server Key ExchangeはServer Helloのkey_share Extension、Client Key ExchangeはClient Helloのkey_share Extensionにそれぞれに移動
また、ネゴの途中から暗号化されていること (特にサーバ証明書が (クライアント証明書も) 暗号化されていること) も大きな特徴です。
Application Dataは2往路目から送信される
Slide 29 TLS 1.3 – Hello Retry Request
key_share とは何か?
key_share は TLS v1.3 (RFC8446) にて定められた、鍵交換方式のための extension (拡張属性) です。
TLS v1.2 までは鍵交換方式は Client Hello / Server Hello の "Cipher Suite" フィールドでネゴシエーションされ、その後、DH 公開鍵などの鍵交換の元ネタを Server Key Exchange / Client Key Exchange に乗っけて送っていました。
TLS v1.3 以降では、Client Hello / Server Hello の Supported_Groups extension で、鍵交換方式の候補を複数提示し、key_share extension でそれら候補のうちいくつかのキー元ネタ (DH 公開鍵など) も送ってしまいます。
Hello Retry Request とは何か?
TLS 1.3 では Hello Retry Request という新たなメッセージが設けられました。
今までは鍵交換は Client Hello と Server Hello のネゴシエーションの間に『方式』が決まり、その後に具体的な鍵交換が行われていましたが、1.3 からは最初の Client Hello に supported_groups と key_share で鍵交換のパラメータが入ったりします。
ので一発目は不発に終わる可能性もあります。その場合サーバは Hello Retry Request で受け入れられるネゴシエーション情報を送り、Client Hello は適切なパラメータに修正して再送します。
Slide 30 TLS 1.3 – Adapt new way about Session Resumption
New Session Ticket とは何か?
『New Session Ticket』は TLS のセッションの再開を行うためのもの
TLS 1.2 までのセッション再開方式=SessionID/SessionTicket
セッション ID 方式
TLS 1.2 においては、セッション回復方法としてはもともと『セッション ID 方式』のみが規定されていましたが、この方式ではセッション ID を照合するためにサーバではキャッシュ情報をタイムアウトまで持ち続ける必要がありました。
セッションチケット方式
クライアントは次回コネクション時の Client Hello 内の『Extension: SessionTicket TLS』にこのチケットを提示し、サーバ側ではそれを読み込み、その内容に沿ったセッション回復を行います。
このとき、厳密にはサーバの認証は行われませんが、サーバが正しくないとチケットを復号できないのでセッション再開は不可です。
TLS 1.3 以降のセッション再開方式=PSK
TLS 1.3 においては、従来の『セッション ID 方式』と『セッションチケット方式』は廃止
代わりにセッションチケットが PSK (Pre-Shared Key) に統合され、相互認証を行いつつ、セッションが再開されるようになりました。
PSK の本来の使い方は RFC 4279 で定義されており、クライアントアプリケーションとサーバアプリケーションでお互いに PSK を手動でセットし、それをもって互いが正しい通信先だと解釈し (この PSK 認証方式の場合、サーバ証明書は不要となる)、さらにそれを素に共通鍵を生成するのです。
今回の改訂により、サーバはセッション中の New Session Ticket にて PSK を払い出し、次回セッション再開時にクライアントは PSK による認証をしつつ、PSK を素にしたセッション回復 (Session Resumption)を行うことができるようになりました。つまり、今まで静的な PSK しか使えなかったのが、動的な PSK にも対応するようになったのです。
シーケンス図
TLS v1.3 の PSK を使った 1-RTT でのセッション再開
TLS v1.3 の PSK を使った 0-RTT でのセッション再開
HTTP/3 (HTTP over QUIC) で実装されることがほぼ決まっており、TLSv1.3 作成時でこの HTTP/3 を相当意識していたものと思われます。
ただし、セキュリティ的にやや甘く、実装は任意になっています。
メリット
TLSの旧版のプロトコルではクライアントがサーバーにアプリケーション・データを送出する前に2往復を必要
サーバはクライアントに対する最初のハンドシェイク・メッセージのレスポンスとしてアプリケーション・データを送ってしまうことも可能
これは、ネットワークの遅れがあっても、安全な接続を確立するのに要する時間への影響は少なくなるということ
セッション再開
これまでのTLSではクライアントはサーバがキャッシュを探すためのセッションIDを持っていました。もし、マッチした場合は同じセキュリティ・パラメータを使うことになりました。これは、非常に単純ですが、サーバ間で状態を共有する必要がありました。
TLS1.3では、これまでのTLSのチケット・システムを再活用する形で、画期的に進歩しました。ハンドシェーク完了後にサーバはクライアントに対して新しいセッション・チケットを送るようにします。
この、クライアントに対するひとかたまりのデータであるチケットは、以前のセッションIDのように鍵を探すデータベースとして利用することができます。ただしこのデータは、前の接続に対応する、自身で暗号化、認証された値とすることができます。つまり、サーバは状態を持たないですむということになります
以前あったような再ネゴシエーション、プロトコル・バージョンのダウングレーディング、圧縮、 CBCやパディングに対する攻撃などは改善され、プロトコルは全体的により強い攻撃耐性を実現
TLS1.2 と TLS 1.3、どこが違うの?
TLS 1.3のリリースでは、セキュリティとスピードの向上が約束されています。しかし、TLS 1.2からTLS 1.3への変更は、これらの改善をどのように実現しているのでしょうか?
TLS1.3は、2017年4月のインタネット・ドラフトで定義されました。
対称暗号アルゴリズムでは、全ての古いアルゴリズムは取り除かれ、TLS1.3で残っているアルゴリズムはすべて、AEAD(Authenticated Encryption with Associated Data) で認証された暗号化を使用します。
ゼロRTT(0-RTT)モードが追加され、一部のセキュリティ特性を犠牲にすることで一部のアプリケーションデータの接続設定では往復回数を削減できるようになりました。
ServerHello以後のすべてのハンドシェークメッセージは暗号化されます。
HMACベースのExtract-and-Expand Key Derivation Function(HKDF)をプリミティブとして使用して、鍵導出関数を再設計しました。
ハンドシェイク状態遷移は、より一貫性があり余分なメッセージを取り除くよう再構成されました。
ECCは基本仕様に入り、複数の新しい署名アルゴリズムが含まれています。楕円曲線のポイント・フォーマット・ネゴシエーションは、各楕円曲線の単一ポイント・フォーマットを使用することで削除されました。
圧縮、カスタムDHEグループ、およびDSAが削除されました。RSAパディングでPSSが使用されるようになりました。
TLS 1.2のバージョンネゴシエーション検証メカニズムは、拡張機能のバージョンリストを使用して廃止されました。
セッション再開については、サーバー側の状態の有無にかかわらず旧バージョンTLSのPSKベースの暗号スイートから、1つの新しいPSK交換方式に統一されました。
TLS 1.3 では,暗号スイートの定義方法が変更されています.鍵交換とサーバ認証が削除され,次のような組み合わせです.TLS_[認証付暗号]_[ハッシュ]
その他,以下のような変更があります.
共通鍵暗号アルゴリズムでは,認証付暗号 (AEAD: Authenticated Encryption with Associated Data) を用いる.
鍵導出関数は,HKDF (HMAC-based Extract-and-Expand Key Derivation Function) に変更された.
鍵交換方法は,Forward security を持つものに限られる.
鍵交換には 3つのモード (EC)DHE,PSK-only,PSK with (EC)DHE がある.
主な暗号スイートの例です.
TLS_CHACHA20_POLY1305_SHA256
pkcs8について
Copy $ openssl genrsa > server.key
$ openssl req -new -key server.key -out req.txt
$ openssl pkcs8 -topk8 -in server.key -out pkcs8.pem -nocrypt
$ openssl x509 -signkey server.key -req -in req.txt -days 365 > server.crt
$ aws iam upload-server-certificate --server-certificate-name ExampleCert --certificate-body file://server.crt --private-key file://pkcs8.pem
CaseID: 2119584253, 2123406113
Links
Javaにおけるルート証明書
ルート証明書のインストールが足りないと以下のようなエラーが出る。 Ref: 2188557603
Copy Caused by: redis.clients.jedis.exceptions.JedisConnectionException: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
キーストアファイルは一般的に /etc/ssl/certs/java/cacerts や /etc/pki/ca-trust/extracted/java/cacerts などが利用されている
Copy # ルート証明書の一覧
$ sudo keytool -v -list -keystore {キーストアファイル} | egrep "Amazon|Starfield"
# ルート証明書のインポート
$ sudo keytool -import -trustcacerts -alias {エイリアス名} -keystore {キーストアファイル} -file {インポート対象の証明書ファイル}
# ルート証明書の削除
$ sudo keytool -delete -noprompt -alias "starfieldservicesrootcertificateauthority-g2" -keystore /etc/pki/ca-trust/extracted/java/cacerts -storepass "changeit"
ルート証明書は、例えば、以下のようなところからダウンロードしてくる。
Copy $ keytool -v -list -keystore /etc/pki/ca-trust/extracted/java/cacerts
Warning: use -cacerts option to access cacerts keystore
Enter keystore password:
***************** WARNING WARNING WARNING *****************
* The integrity of the information stored in your keystore *
* has NOT been verified! In order to verify its integrity, *
* you must provide your keystore password. *
***************** WARNING WARNING WARNING *****************
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 127 entries
Alias name: accvraiz1
Creation date: Oct 2, 2021
Entry type: trustedCertEntry
Owner: C=ES, O=ACCV, OU=PKIACCV, CN=ACCVRAIZ1
Issuer: C=ES, O=ACCV, OU=PKIACCV, CN=ACCVRAIZ1
Serial number: 5ec3b7a6437fa4e0
Valid from: Thu May 05 09:37:37 UTC 2011 until: Tue Dec 31 09:37:37 UTC 2030
Certificate fingerprints:
SHA1: 93:05:7A:88:15:C6:4F:CE:88:2F:FA:91:16:52:28:78:BC:53:64:17
SHA256: 9A:6E:C0:12:E1:A7:DA:9D:BE:34:19:4D:47:8A:D7:C0:DB:18:22:FB:07:1D:F1:29:81:49:6E:D1:04:38:41:13
Signature algorithm name: SHA1withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3
Extensions:
#1: ObjectId: 1.3.6.1.5.5.7.1.1 Criticality=false
AuthorityInfoAccess [
[
accessMethod: caIssuers
accessLocation: URIName: http://www.accv.es/fileadmin/Archivos/certificados/raizaccv1.crt
,
accessMethod: ocsp
accessLocation: URIName: http://ocsp.accv.es
]
]
#2: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: D2 87 B4 E3 DF 37 27 93 55 F6 56 EA 81 E5 36 CC .....7'.U.V...6.
0010: 8C 1E 3F BD ..?.
]
]
#3: ObjectId: 2.5.29.19 Criticality=true
BasicConstraints:[
CA:true
PathLen:2147483647
]
#4: ObjectId: 2.5.29.31 Criticality=false
CRLDistributionPoints [
[DistributionPoint:
[URIName: http://www.accv.es/fileadmin/Archivos/certificados/raizaccv1_der.crl]
]]
#5: ObjectId: 2.5.29.32 Criticality=false
CertificatePolicies [
[CertificatePolicyId: [2.5.29.32.0]
[PolicyQualifierInfo: [
qualifierID: 1.3.6.1.5.5.7.2.2
qualifier: 0000: 30 82 01 14 1E 82 01 10 00 41 00 75 00 74 00 6F 0........A.u.t.o
0010: 00 72 00 69 00 64 00 61 00 64 00 20 00 64 00 65 .r.i.d.a.d. .d.e
0020: 00 20 00 43 00 65 00 72 00 74 00 69 00 66 00 69 . .C.e.r.t.i.f.i
0030: 00 63 00 61 00 63 00 69 00 F3 00 6E 00 20 00 52 .c.a.c.i...n. .R
0040: 00 61 00 ED 00 7A 00 20 00 64 00 65 00 20 00 6C .a...z. .d.e. .l
0050: 00 61 00 20 00 41 00 43 00 43 00 56 00 20 00 28 .a. .A.C.C.V. .(
0060: 00 41 00 67 00 65 00 6E 00 63 00 69 00 61 00 20 .A.g.e.n.c.i.a.
0070: 00 64 00 65 00 20 00 54 00 65 00 63 00 6E 00 6F .d.e. .T.e.c.n.o
0080: 00 6C 00 6F 00 67 00 ED 00 61 00 20 00 79 00 20 .l.o.g...a. .y.
0090: 00 43 00 65 00 72 00 74 00 69 00 66 00 69 00 63 .C.e.r.t.i.f.i.c
00A0: 00 61 00 63 00 69 00 F3 00 6E 00 20 00 45 00 6C .a.c.i...n. .E.l
00B0: 00 65 00 63 00 74 00 72 00 F3 00 6E 00 69 00 63 .e.c.t.r...n.i.c
00C0: 00 61 00 2C 00 20 00 43 00 49 00 46 00 20 00 51 .a.,. .C.I.F. .Q
00D0: 00 34 00 36 00 30 00 31 00 31 00 35 00 36 00 45 .4.6.0.1.1.5.6.E
00E0: 00 29 00 2E 00 20 00 43 00 50 00 53 00 20 00 65 .)... .C.P.S. .e
00F0: 00 6E 00 20 00 68 00 74 00 74 00 70 00 3A 00 2F .n. .h.t.t.p.:./
0100: 00 2F 00 77 00 77 00 77 00 2E 00 61 00 63 00 63 ./.w.w.w...a.c.c
0110: 00 76 00 2E 00 65 00 73 .v...e.s
], PolicyQualifierInfo: [
qualifierID: 1.3.6.1.5.5.7.2.1
qualifier: 0000: 16 24 68 74 74 70 3A 2F 2F 77 77 77 2E 61 63 63 .$http://www.acc
0010: 76 2E 65 73 2F 6C 65 67 69 73 6C 61 63 69 6F 6E v.es/legislacion
0020: 5F 63 2E 68 74 6D _c.htm
]] ]
]
#6: ObjectId: 2.5.29.15 Criticality=true
KeyUsage [
Key_CertSign
Crl_Sign
]
#7: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
RFC822Name: accv@accv.es
]
#8: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: D2 87 B4 E3 DF 37 27 93 55 F6 56 EA 81 E5 36 CC .....7'.U.V...6.
0010: 8C 1E 3F BD ..?.
]
]
*******************************************
*******************************************
: