要約

  • Want-Content-DigestとWant-Repr-Digestはアルゴリズムの希望順位を伝える。受信した側は希望を無視したり、別の方式を選んだり、ダイジェストを返さなかったりでき、それだけではプロトコルエラーにならない。
  • 完全性の記録は、送った希望、返った証拠、証拠が覆うHTTP上の対象、受信側の計算と判断という四つの状態に分ける必要がある。
  • ダイジェストは対象バイトの不一致を見つける仕組みであり、送信者の認証、操作の認可、秘匿、HTTPメタデータ全体の保護を代行しない。

希望順位は発注書ではない

設定画面で「SHA-512を最優先」と選ぶと、運用者はその方式が次の応答に入ると考えがちだ。しかし、RFC9530のWant-*フィールドは相手に選択を伝える手段であって、合意成立を示す応答ではない。

二つのフィールドはいずれもStructured Fieldsの辞書を使う。キーがアルゴリズム名、整数が相対的な希望順位で、1が最も低く、10が最も高い。0は受け入れ不可を意味する。Want-Content-Digestはメッセージコンテンツ、Want-Repr-Digestは選択された表現についての希望を示す。

この数値は暗号強度の点数でも、検証結果でもない。10を付けても相手に義務は生じない。相手は辞書を考慮せず、一覧にない方式を返し、あるいはContent-DigestもRepr-Digestも返さないことができる。RFC9530は、その差だけをプロトコルエラーとはしていない。

もちろん、個別のサービスが厳格な条件を追加してもよい。指定方式がなければ失敗する、欠落時は処理しない、といった条件はアプリケーション契約として明示する。付録Cも、低い順位の方式を選ぶ場合、候補をまったく扱えない場合、アプリケーションが4xxや5xxを返す場合を例示するが、単一の必須ステータスは決めていない。

応答にWant-*が入る向きも見落としやすい。これはサーバーが将来のリクエストに付けてほしいダイジェストを知らせるものであり、その応答自身のダイジェストではない。「Digest」という文字列があることと、証拠が届いたことは別である。

一つの通信に四つの記録を残す

第一は希望の記録である。どちらのWant-*を送り、何をどの順位で示したか。第二は観測した証拠で、実際のフィールド、含まれるメンバー、ヘッダーかトレーラーかを残す。第三は対象で、メッセージコンテンツか選択された表現かを特定する。第四はローカルな結論で、採用した方式、計算したバイト、一致の有無、業務処理を記す。

この四分割があれば、「希望した」と「返った」を混同しない。sha-256が入っていても、受信側が計算したとは限らない。一致という表示だけあっても、どちらのフィールドを何に対して検証したのか分からなければ、完全性の説明にはならない。

互換性のために低い順位の方式を受け入れる判断も、欠落を許す判断もあり得る。重要なのは、それを成功一般に丸めないことだ。「代替方式を方針により受理」「証拠なしで継続」と記録すれば、後から保証水準を再現できる。空欄を検証成功に数えると、意思決定そのものが消えてしまう。

コンテンツと表現では計算対象が異なる

RFC3230のinstance digestには、何を覆う値なのかが分かりにくい場面があった。RFC9530はContent-DigestとRepr-Digestを分ける。前者は一つのHTTPメッセージが実際に運ぶコンテンツ、後者はHTTPセマンティクス上の選択された表現全体を対象にする。

部分応答では差が分かりやすいが、それだけの問題ではない。一つのリソースに複数の表現があり得る。Content-TypeやContent-Encodingによってバイト列と解釈が変わるため、保存された都合のよいファイルをハッシュしても、フィールドが指す対象を検証したことにはならない。

状態を変更するメソッドにも同じ注意が要る。PATCHリクエストの表現はパッチ文書であり得る一方、応答の表現は更新後リソースの選択表現かもしれない。Content-LocationとLocationを同一視して対象を決めることもできない。

社内APIの「payload checksum」という一項目だけでは、この境界が失われる。フィールド種別、表現メタデータ、エンコーディングの扱い、どの処理段階でバイトを取り出したかまで記録したい。そうしなければ、双方が正しく計算しているのに、別々の物を検証することが起こる。

実装可能と受入可能を分ける

現在のIANA登録ではSHA-512とSHA-256がActiveである。MD5、SHA、UNIX系のsum、Adler-32、CRC32CなどはDeprecatedに置かれている。RFC9530は、攻撃者を想定しない偶発的な破損検出で古い方式を使う余地を残す一方、敵対的状況やデジタル署名の文脈では使ってはならないとする。

登録状態だけでは各サービスの採否は決まらない。受信側は任意のメンバーを無視でき、計算する方式や数、対象サイズを制限できる。大きなコンテンツに対して相手が指定する多数の計算を無制限に行えば、CPUやメモリ帯域の負担面が広がる。

ライブラリが理解できる方式と、リスク方針が認める方式は別の一覧にするべきだ。強いメンバーと廃止予定のメンバーが同居したとき、ある部品が最初に扱える値だけを採用し、別の部品が最優先方式を使ったと思い込めば、同じ通信に二つの保証ができる。アルゴリズムアジリティだけではダウングレードを防げない。

記録には実際に選んだ方式、フィールド、対象、一致結果を残す。許容できる一つの一致で十分か、未知または禁止方式だけならどうするか、複数値が食い違えばどうするかはアプリケーションが決める。共通レジストリは選択を助けるが、責任者に代わってリスクを引き受けない。

トレーラーの到着前に動けば、事前検証ではない

二つの証拠フィールドはヘッダーにもトレーラーにも置ける。ストリームを送りながら最後に計算する場合、トレーラーは合理的だ。しかし仲介者が落とすことがあり、アプリケーションが到着前にデータを使うこともある。

状態変更を確定し、ファイルを公開し、後段へ転送した後で一致を確認しても、先の行為が完全性検証を条件にしていたことにはならない。後追い検証は監査に役立つが、因果の順序は変えられない。トレーラーが来なかったら、記録すべきは不在である。

保存後も同様だ。一致は検証時点の対象バイトについての証拠であり、永続的な無改変証明ではない。対象全体を保管して再計算しなければ、後の状態までは語れない。処理段階と論理時刻も完全性の記録に含める必要がある。

ダイジェストはHTTP全体を認証しない

RFC9530は範囲を狭く保っている。ダイジェストはメソッド、対象URI、ステータスコード、すべての表現メタデータを自動では束縛しない。送信者の身元を示さず、操作権限を与えず、秘密も守らない。

RFC9421のHTTP Message Signaturesでダイジェストフィールドを署名対象にできるが、署名ベースへ明示的に含め、必要な表現メタデータも選ばなければならない。署名とダイジェストが同じメッセージに並ぶだけでは結び付かない。鍵、時刻、再送への対策も別途必要である。

不一致から分かるのは、計算したバイトと提示値が異なることまでだ。誰が変えたか、悪意か、操作が許可されていたかは答えない。この限定性を守ることで、輸送保護、認証、認可、署名、保存管理を脅威に応じて正しく組み合わせられる。

参照資料と主張の範囲

運用例は仮想であり、導入率、事故件数、攻撃頻度、計算費用、普遍的に安全な閾値を測定したものではない。