要約
- RFC 8879では、受信側が解凍可能なalgorithmを先に示した場合、TLS 1.3 endpointは通常のCertificateを
CompressedCertificateへ置き換えられる。advertisementは一つの表現を許すだけで、実際の利用や無制限のresourceを証明しない。 uncompressed_lengthは復元後のmessage長と完全に一致し、outputはその値を超えてはならない。実装はTLSの24-bit ceilingより低いlocal limitを設定できる。この判定はcertificateがpeerを認証する前に起きる。- decompression成功はauthentication成功ではない。offer、選択algorithm、compressed bytes、宣言長と実長、復元hash、解析chain、validation、alert、fallback、transport outcomeを別の事実として残す必要がある。
identityより先にallocationを決める
大量の新規接続を処理するTLS terminatorを考える。clientはClientHelloでzlib、Brotli、Zstandardを提示した。serverはalgorithm 2を選び、小さなpayloadと12MBのuncompressed_lengthを返す。
serverを認証するはずのCertificate messageはまだ圧縮されたままである。receiverはCA、subject name、public keyをallocation判断の根拠にできない。まず、そのalgorithmを自らofferしたか確認し、通常Certificateと同じlocal size limitを適用し、decoderの出力を宣言値で止め、最終長が一致しなければ拒否する。
ここに運用権限がある。senderは提示された集合から表現方法を選ぶ。receiverは、どのtransformを実行し、未認証connection一つへどれだけmemoryとCPUを渡すかを決める。Brotli対応の表明は、peerへのallocation authority移譲ではない。
TLS framingの上限は16,777,215 bytesだが、RFC 8879はより低い実装上限を認める。その値はcompressed pathとordinary pathで同じでなければならない。通常なら大きすぎるCertificateを、小さいwrapperに入れたことでparserへ通してはならない。
capability、selection、resultを分離する
compress_certificateは一方向のsignalである。clientがClientHelloへ入れると、server Certificateを解凍できるalgorithmを示す。serverがCertificateRequestへ入れると、client Certificateを解凍できるalgorithmを示す。応答extensionはない。
送信側は提示されたalgorithmを一つ使ってもよいし、通常Certificateを送ってもよい。packet captureでextension 27を見ても、その後にhandshake type 25が送られた証拠にはならない。offer countを圧縮成功数として扱うdashboardは、可能性を実行結果へすり替えている。
directionも独立している。server certificateを受け取れるclientが、自分のcertificateを圧縮できるとは限らない。後者にはserverのCertificateRequestでのsignalが必要である。library buildやapplication optionにより、送信のみ、受信のみ、algorithmの部分集合という状態も生じる。
このextensionはTLS 1.3以降だけで機能し、TLS 1.2では無視される。古いTLS record compressionとは別物である。RFC 8879が変換するのは一つのhandshake messageであり、復元後のcertificate処理を弱めない。
圧縮対象はencoded Certificate messageそのもの
入力はPEM fileや個別X.509 certificateではない。本来wireへ出るencoded Certificate message全体であり、request context、certificate list、各CertificateEntryのextensionを含む。別のextensionがmessageを変えれば、その変更後bytesが入力になる。
したがってevidenceには少なくとも二つのhashが要る。compressed headerとpayloadのhashは、受信したrepresentationを示す。復元後Certificate messageのhashは、TLS parserへ渡った正確なbytesを示す。その後、leafとintermediateのfingerprintがvalidation対象を表す。
同じ入力でもalgorithmが違えば圧縮bytesは変わる。library versionが変わっても、同じmessageを異なる形に圧縮し得る。compressed payload hashだけでは、zlib、Brotli、Zstandard、uncompressed pathの間でcertificate identityを比較できない。
precompressionもmessage identityに従う。OpenSSLはserver certificateを事前圧縮して保存できる。一方、client Certificateはserverから受け取ったunique request contextを含むためon-demandになる。server cacheもhostnameだけで管理できない。chain更新、intermediate順、per-entry extensionが変われば、古いartifactとの対応を失う。
長さは安全のgateであり、scoreではない
CompressedCertificateにはalgorithm ID、24-bitのuncompressed_length、compressed bytesがある。decompression失敗、宣言値超過、実長不一致はbad_certificateでconnectionを終了させる。上限は出力中に守るべきで、終了後の比較だけでは遅い。
宣言長は早期拒否とbuffer planningに役立つが、senderの誠実さや復元内容の安全性を保証しない。protocol上は合法でも、high concurrency serviceにとって大きすぎる値はある。local limitは実測したmemory、CPU、同時接続数から決める必要がある。
また、compressed outputが常に小さいという規則もない。BoringSSL testsは意図的にshrinking、expanding、random transformを扱う。protocol validityは、選択algorithmで入力をbound内に正確に復元することにある。ratioはoptimization outcomeである。
よって宣言長、実長、peak allocation、decoder time、failure classを分けて測る。高い圧縮率がmemory spikeを隠す場合もあり、小さな改善が一つのpacketを減らす場合もある。ratioだけからsecurityやlatencyは導けない。
復元が終わってからtrust evaluationが始まる
復元したCertificateは、最初からuncompressedで来た場合と同じ処理を受ける。messageをparseし、chainを構築し、nameとtimeを確認し、local policyを適用し、TLS 1.3 transcript内のCertificateVerifyを検証する。compressionはexpired certificateやunknown CAを正当化しない。
failure taxonomyを保つべきである。未提示algorithmはnegotiation error。output overrun、decoder error、length mismatchはreconstruction error。不正なCertificate structureはparse error。nameやchainの不一致はvalidation error。CertificateVerify失敗はhandshake authentication errorである。
全てを「TLS certificate error」に潰すと、どのcontrolが拒否したか分からない。逆にdecompression_successだけを成功と呼ぶと、期待identity、private key possession、application authorizationを証明していないのに結論を先取りする。
running codeは境界を具体化する。BoringSSLは通常Certificateを組み立てて正確な長さを保持し、選択callbackで圧縮してmessageを作る。testsは異常な長さやtransformを検査する。OpenSSLはsend、receive、preference、server precompressionを別々に制御する。IANA registry、library branch、production settingは別の証拠である。
wire削減とservice outcomeを接続する
first handshakeではchainがbytesの多くを占めるため、圧縮はpacketを減らし、条件によってはtransport round tripを避ける。しかしchain、congestion window、loss、record packing、CPU、cache、共通algorithmで結果は変わる。disk上のPEM sizeをwire上Certificate lengthの代わりにしてはならない。
方向別offer、実message、algorithm、元長と圧縮長、records、packets、retransmission、CPU、memory、validation、完了時間を一つのsampleへ結ぶ。同じcertificate identityとpolicyでuncompressed controlを置く。それで初めて改善を帰属できる。
共通algorithmがなければ通常Certificateへfallbackできる。fallback増加はclient mixの変化かもしれず、decoderを失ったbuildやTLS termination位置の変更かもしれない。両pathが同じlimitとvalidationを使う限り、これはrepresentation fallbackであってtrust downgradeではない。
情報源
- RFC 8879 — TLS Certificate Compression
- RFC 8446 — TLS 1.3
- RFC 9325 — TLS/DTLSの安全な利用
- IANA — TLS extensionとcertificate compression algorithm
- RFC 1950 — ZLIB format
- RFC 7932 — Brotli format
- RFC 8478 — Zstandard
- OpenSSL — Certificate compression functions
- OpenSSL — 送受信option
- BoringSSL — TLS 1.3 message実装
- BoringSSL — Certificate compression tests
- Heng Lu — Running-Code Primacy
会員向け解説
プロフィールの詳細
適切な会員レベルでログインすると、解説全文と出典メモをご覧いただけます。
Strategic Circle 限定
Strategic Circle
すべての読者に公開されています。参加してログインすると プロフィール解説 を閲覧できます。
Strategic Circle に参加Leadership Alliance 会員限定
Leadership Alliance
対象となる IP 資産の所有者・管理者向けです。ログインすると Leadership Alliance の解説を閲覧できます。
Leadership Alliance に参加
