要約

  • HTTP message signature は Signature-Input に並べた field、derived component、署名 parameter から作る signature base を保護する。そこにない method、authority、target、credential、content が変わっても署名は成立し得る。
  • verifier は適切な署名と鍵を選び、時間、replay、digest、principal、resource、operation を自ら判断する。keyid や nonce は判断材料であり、自動的な信頼や一回性ではない。
  • proxy が client 署名を検証し、message を変換して再署名すると、別の custody statement が生まれる。proxy の署名は client が後付けの field を承認した証拠にはならない。

正しい署名が別の API で使われた

ある変更要求には、有効な Signature と Content-Digest が付いている。鍵は現役で、時刻も許容範囲、本文の digest も一致する。ところが covered component は date と content-digest だけだった。

本文は検証環境の endpoint に向けたものかもしれない。@target-uri がなければ実運用の endpoint に移しても signature base は変わらない。@method がなければ、照会のための payload が変更要求と組み合わされる余地がある。nonce と一回限りの業務 ID がなければ、許容時間内に同じ要求を繰り返せる。

暗号は破られていない。署名された対象が、実際に許可したい命令より小さかったのである。

RFC 9421 は wire image ではなく意味を組み立てる

HTTP message は proxy を通る。field line は結合され、HTTP/1.1 と HTTP/2 の間で表現が変わり、gateway が routing context を追加する。送信時の全 byte をそのまま署名すれば、正当な変換まで改竄になる。

RFC 9421 は、双方が message から同じ signature base を作る方式を採る。通常の HTTP field のほか、@method、@authority、@target-uri、@status のような derived component を選べる。順序も意味を持ち、@signature-params が component list と created、expires、keyid、nonce、tag を最後に結び付ける。

検証成功が示すのは、covered subset について受信 message が署名時 message と意味的に同等であることだ。subset 以外へ保証が広がるわけではない。

component が二つの署名と十個の署名は、同じ証明の強弱ではない。証明している object が違う。

coverage profile は operation ごとに持つ

RFC は全 API の重要 field を知り得ない。GET、課金、network policy の変更、account 削除では、保護すべき意味が異なる。だから application は method と route ごとに必須 coverage を定義する必要がある。

高影響の要求なら、@method、@authority、@target-uri、関連する authorization context、content-digest、一回限りの challenge が必要になり得る。署名 field が存在するかではなく、その署名がこの profile を満たすかを調べる。

ただし全 field を固定すればよいわけでもない。Via や Forwarded は intermediary が更新する。これを常に署名すると正常な転送を妨げる。権限または結果を変える component は覆い、proxy が変えてよい component は明示して別の custody boundary として扱う。

Heng Lu の Minimum Initial Specification に照らすと、共通仕様の仕事は base の構築と検証を決定的にすることだ。どの component、key、freshness、authorization を要求するかは running participant に残る。厳密な共通層と local decision は両立する。

content は digest を介して二度確認する

RFC 9421 は任意の本文をそのまま signature base に入れない。RFC 9530 の Content-Digest を計算し、その field を署名し、受信 content から digest を再計算する。

署名だけ確認して digest を再計算しなければ、攻撃者は署名済み digest 値を残したまま本文を交換できる。digest が署名されていなければ、本文と digest を同時に交換できる。field の保護と、field が現物を正しく記述することは別の検査である。

Content-Type や Content-Encoding も意味を変える。byte が同じでも parser が違えば operation が変わる。digest の計算対象となる representation の境界も profile に含めなければならない。

trailer に digest を置く場合、intermediary は trailer を落とせる。application が到着中の content を先に処理すれば、検証完了より effect が先になる。不可逆処理では buffer または transaction boundary が必要になる。

keyid は trust anchor ではない

keyid は key を探すための hint であり、その文字列自身が identity を証明するわけではない。RFC 9421 は key discovery と acceptable algorithm を application に任せる。

request が持ち込んだ任意の public key を受け入れる設計では、攻撃者は自分の命令を自分の key で署名して検証を通せる。証明できるのは private key possession だけだ。

verifier は key の実体と version、trust source、active interval、principal、role、許可 operation を結び付ける。audit には keyid だけでなく、その時点で解決された key version と policy version を残す。

rotation の dual signature は有用だが、開始と終了が必要である。互換性を理由に旧 key を無期限に残せば、変更は authority surface を狭めず、広げるだけになる。

IANA registry は name と algorithm の相互運用性を与える。特定の業務リスクへの適格性を承認する機関ではない。

時刻が新しくても replay は新しくない

created は署名生成時刻、expires は署名者が保証を終える時点を表す。verifier は clock tolerance と許容 age を決める。暗号的には正しいが、業務上は古い署名を拒否できる。

しかし短い window は一回性ではない。window 内で同じ message は何度でも届く。

nonce は一回値を置く場所を提供する。verifier が uniqueness を強制し、使用済み状態を atomic に書かなければ効果はない。複数 region が同時に未使用と判断すれば、一つの nonce が二つの commit を生む。

tag は複数署名から用途に合う候補を選ぶ助けになる。公開値なので攻撃者もコピーでき、権限にはならない。

proxy の再署名は新しい証言である

RFC 9110 では intermediary が通常の設計要素である。edge proxy は client signature を検証し、privacy field を削除し、内部 target に変換して自分の signature を追加できる。

downstream が受け取る proxy signature は、proxy 自身が何を検証し何を転送したかの証言だ。client が internal target や proxy-added identity field を署名したことにはならない。

origin は proxy にどこまで委任したかを決める。client signature の検証結果を運ぶだけなのか、内部 principal として command を発行できるのか。同じ boolean では区別できない。

証拠には external request context、選択した client signature、適用 profile、変換内容、internal context と proxy signature を連続して残す。最後の署名だけ残せば、client provenance が消える。

HTTP version 変換も context を変える。HTTP/1.1 の Host と HTTP/2 の :authority を跨ぐには @authority の意味値が適する。wire-specific field だけを署名すると、合法な変換が失敗するか、verification と authorization が別の authority を読む危険がある。

valid signature が複数あっても選択は必要

client、proxy、approver の署名を一つの message に載せられる。algorithm migration では新旧二つもあり得る。全て valid でも、対象 operation に必要なものとは限らない。

最初に検証できた署名を採用する方式は、logging signature を execution authority と誤認する。label、tag、signer role、coverage profile、key policy を合わせて選ぶ必要がある。

response の req parameter は関連 request の component も覆える。verifier は正確な request context を持たなければならない。署名済み response と署名済み request を後から並べただけでは、その response がその request の結果だとは証明できない。

TLS と application authorization は残る

TLS 1.3 は channel を暗号化し、設定に応じて peer を認証する。HTTP message signature は選択した message semantics を connection の外まで持続させられる。message signature は confidentiality を与えず、TLS を不要にしない。

HTTP authentication が credential を提示しても、現在の principal、resource、action、state を評価するのは application である。署名済み response が自動的に cacheable になるわけでもなく、その判断は RFC 9111 に残る。

Reality Layers の見方では、signature base は coordination artifact、verification は cryptographic fact、key mapping は identity claim、authorization は local decision、commit と downstream effect が operational reality である。前段の成功を後段の権限に読み替えないことが重要だ。

情報源と限界

これらは format と security boundary を示す。現在の普及率、特定 product の挙動、人間の identity、法的意思、non-repudiation、業務判断の正しさは証明しない。