[21] TLS Handshake Protocol の Certificate
メッセージは証明書を表します。サーバーからクライアントへはサーバー証明書、
サーバーからクライアントへはクライアント証明書となります。
[4] サーバーからの Certificate
メッセージは、
クライアントに対してサーバーの証明書鎖を伝えるものです >>1。
[26] クライアントからの Certificate
メッセージは、
サーバーに対してクライアントの証明書鎖を伝えるものです >>18。
[45]
HandshakeType
11 (certificate
)
[6] Certificate
メッセージは、
0バイト以上224-1バイト以下の証明書の列
(鎖, 証明書鎖) です >>1。
[17] 各証明書は、1バイト以上224-1バイト以下の列です >>1, >>16。 どのような証明書であるべきかにも規定があります (>>11)。
[7] 送信者の証明書が最初に来なければなりません >>1。
[38] その後の証明書は前の証明書を直接証明するものでなければなりません >>1。
[8] ルートCAを表す自己署名証明書は、鎖から省略して構いません >>1。 省略しない場合は末尾に来ます。
[41] 長さ0でもいいということは、証明書鎖が空になることが (少なくても仕様上は) あり得るということです。 その場合は当然証明書による検証ができず、安全ではありません。
[44] 実用上はサーバーが証明書鎖を空にすることはまずありません。 クライアントは認証が必要な場合以外、空にできます (>>20)。
[42] 証明機関の発行する証明書を利用できないときは、 いわゆるオレオレ証明書が使われます。 すなわち、その場限りのルート証明書に相当するEE証明書を1つだけ含んだ証明書鎖になります。
[43] 証明書鎖にはバイト長の制限はあるものの、証明書は何個でも含められます。 実際上は十分大きな数で制限されます。
[47]
厳密な話は置いておくとして、 Certificate
の中身をちょっと覗きたいだけの場合、
[2] サーバーは、合意した鍵交換方式が認証に証明書を使う場合には、
Certificate
メッセージを送信しなければなりません >>1。
[3] サーバーは、 ServerHello
メッセージの直後に Certificate
メッセージを送信します >>1。
[19] クライアントは、 ServerHelloDone
メッセージを受信した直後に、
(サーバーが CertificateRequest
メッセージで要求していれば)
Certificate
メッセージを送信できます。 >>18
[20] クライアントは、適切な証明書が存在しない時は、
証明書を含まない (certificate_list
が長さ0の)
Certificate
メッセージを送信しなければなりません
>>18。
[25] クライアントは、 service identity その他アプリケーション依存の証明書の検証を行います。
[22] サーバーは、クライアントが証明書を送らなかった場合には、
クライアント認証なしでhandshakeを継続しても構いませんし、
handshake_failure
fatal alert で応答しても構いません。 >>18
[23] サーバーは、クライアントの証明書鎖の一部が受け入れられない (例えば既知の信頼した CA が署名していない) 場合、 クライアント認証なしとみなしてhandshakeを継続しても構いませんし、 fatal alert で応答しても構いません。 >>18
[27] サーバーは、 CertificateVerify
メッセージの検証の際や、
premaster secret の計算に、クライアントの Certificate
を使います >>18。
[5] 証明書は、両者間で折衝した cipher suite の鍵交換アルゴリズムや TLS拡張において適当なものでなければなりません >>1, >>18。
[11] 証明書は PGP などで予め明示的に折衝した場合を除き、 X.509 の v3 証明書でなければなりません >>1, >>18。
[12] サーバーからの Certificate
メッセージにおける末端実体証明書の公開鍵 (と関係する制約) は、
選択した鍵交換アルゴリズムと互換性があるものでなければなりません >>1。
[28] クライアントからの Certificate
メッセージにおける末端実体証明書の公開鍵 (と関係する制約)
は、 CertificateRequest
メッセージで指定された証明書型と互換性があるものでなければなりません >>18。
[29] クライアントからの Certificate
メッセージにおける証明書は、
CertificateRequest
メッセージで空でない certificate_authorities
が指定されていた場合、指定されたいずれかの CA が発行した証明書が証明書鎖のいずれかとして含まれているべきです >>18。
[13] サーバーからの Certificate
メッセージにおける適切な証明書の選択には、 SNI や trusted_ca_keys
の指定があればそれを使います >>1。
[14] サーバーからの Certificate
メッセージにおいては、
signature_algorithms
の指定があれば、その署名アルゴリズムを使った証明書でなければなりません >>1。
[30] クライアントからの Certificate
メッセージにおいては、
ハッシュアルゴリズムと署名アルゴリズムの組は CertificateRequest
メッセージでの指定に従った証明書を使わなければなりません >>18。
[15] サーバーは複数の証明書候補がある時にこうした基準の他、設定やポート番号など諸々の基準でいずれかを選択できます。 1つ証明書がある時もそれらの基準に合致するか検査するべきです。 >>1
[51]
多くの実装は OpenSSL を使っており、 OpenSSL の PEMファイル形式で証明書鎖を指定すると、
OpenSSL サーバーがそれを Certificate
形式に変換して送信することになります。
[31] https://i.allnightnippon.com/
このサーバー、 中間証明書を返さなくて末端実体証明書だけ返してくる。 なのに Windows の Chrome でも IE でもアクセスできてしまう。 Linux の wget, curl, LibreSSL ではエラーになる。 W3C Markup Validator ではエラーになる。 Internet Archive ではエラーにならない。
[34] >>31 未だに治っていないがサービスはなくなって他のホストにリダイレクトされる。 たぶんサーバーが消えるか証明書の期限に達するまでもうこのままだろう。
[32] BS11オンデマンド|TOPページ, , https://vod.bs11.jp/video/
[33] >>32 からの新しい末端実体証明書が使われてますが、 それに変わった頃から中間証明書が送信されてこなくなりました。 Windows の Chrome では普通にアクセスできてしまいます。 変わってから数日間、修正される様子もないですし、 SNS に苦情も出ていないので、多くの環境で正常にアクセスできてしまっているのではないでしょうか。