draft-ietf-wimse-http-signature

元ファイル (GitHub)

一言で言うと: HTTP Message Signatures のプロファイルであり、ワークロードが Workload Identity Token に結び付いた鍵でリクエスト(および任意でレスポンス)に署名することで、TLS を終端するプロキシを挟んでも証明が失われないようにする。

概要

HTTP で互いを呼び出すワークロードには認証が要る。相互 TLS は選択肢の一つだが、認証局(Certification Authority)の基盤がない場合や、呼び出しが複数の TLS ホップを経由する場合には、アプリケーション層での保護が好まれる(Section 1)。本ドラフトは、そのようなアプリケーション層の方式を HTTP Message Signatures([RFC9421])のプロファイルとして定義する。呼び出し側は Workload Identity Token(WIT)を送り、WIT 内の鍵に対応する秘密鍵でリクエストに署名することで、その鍵の保持を証明する。署名はメソッド、パス、クエリ、選択したヘッダー、および本文がある場合の Content-Digest を対象とし、三つの新しい署名パラメーターを持つ。宛先を示す wimse-aud、署名付きレスポンスを要求する wimse-sign-response、レスポンスをリクエストに結び付ける wimse-req-nonce である。本ドラフトは(CONNECT を除き)@authority に署名しないので、authority を書き換えるプロキシを挟んでも検証は壊れない。Datatracker 上の状態は Active、Publication Requested、Submitted to IESG for Publication である(subject.json)。

仕組み

図
sequenceDiagram
    participant C as クライアントワークロード
    participant M as TLS 終端ミドルボックス
    participant S as サーバーワークロード
    C->>C: 対象コンポーネントとパラメーターから署名ベースを構築する
    C->>M: Signature、Signature-Input、Workload-Identity-Token を付けたリクエスト
    M->>S: 新しい TLS 接続でリクエストを転送する
    S->>S: WIT を検証し、WIT の鍵で署名を検証する
    S->>S: tag、有効期間、nonce、wimse-aud を確認する
    alt 認証に失敗した場合
        S-->>C: 問題タイプ wimse-signature-invalid を付けた 400
    else 署名付きレスポンスが必須の場合
        S-->>M: wimse-req-nonce にリクエストの nonce を設定して署名したレスポンス
        M-->>C: レスポンスを転送する
        C->>C: 署名を検証し wimse-req-nonce を比較する
    else 署名が必須でない場合
        S-->>C: レスポンス(任意で署名付き)
    end
  1. クライアントは署名ベースを構築する。Section 3 により、@method、@path、@query、および存在する場合は Content-Type、Content-Digest、Authorization、Txn-Token、Workload-Identity-Token を対象に含める。created、expires、nonce、tag(値は wimse-workload-to-workload)、wimse-aud を設定し、任意で wimse-sign-response を設定する。keyid と alg は設定してはならない。
  2. クライアントは WIT と署名を付けてリクエストを送る。TLS を終端するミドルボックスからは平文の WIT と署名が見えるが、対象コンポーネントを書き換えれば検証に失敗する(Section 5.2)。
  3. サーバーは、署名を検証する前にワークロード資格情報ドラフトの規定に従って WIT を検証し、完全に検証されるまでメッセージをそれ以上処理してはならない(Section 3)。
  4. サーバーはラベルではなく tag の値で WIMSE 署名を見つけ、その tag を持つ署名が複数あればメッセージを拒否する。有効期間を確認し、wimse-aud を信頼済み設定と Simple String Comparison で照合する(Section 3、3.2)。
  5. 失敗した場合、サーバーは問題タイプ wimse-signature-invalid を付けた 400 を返し、どの検査が失敗したかは示さない(Section 3.6)。
  6. リクエストの wimse-sign-response が true の場合、またはローカルポリシーが要求する場合、サーバーはレスポンスに署名する。対象は @status、req パラメーター付きのリクエストコンポーネント、Content-Type、Content-Digest、Workload-Identity-Token であり、wimse-req-nonce にはリクエストの nonce を設定する(Section 3.4、3.5)。署名できない場合は、署名なしの成功ではなくエラーを返す。
  7. クライアントは署名付きレスポンスを検証し、wimse-req-nonce を自分の nonce と比較する。署名を要求した場合、署名のないレスポンスは拒否しなければならない(Section 3.5)。

ユースケース

  • TLS を終端するロードバランサーや API ゲートウェイを経由するサービス間呼び出しで、エンドツーエンドの証明を宛先でも検証できなければならない場合(Section 1、5.2)。
  • 剥がされた、または差し替えられたレスポンスを検出したいクライアントが、wimse-sign-response と wimse-req-nonce を併用する場合(Section 3.3、3.5、Appendix A.4)。
  • CONNECT メソッドによるプロキシのトンネリングで、プロファイルが @path と @query の代わりに @authority を対象にする場合(Section 3)。
  • 一つのサービスに複数の宛先名がある構成で、比較がバイト単位の完全一致であるため、受け入れる文字列をすべて受信側の設定に列挙しなければならない場合(Section 3.2)。
  • issue #419 にある今回の版向けの独立したテストベクターで、適合性を確認したい実装者とテスト担当者。

なぜ今重要か

  • きっかけ: subject.json によれば、本ドラフトに対して三つの新しい issue が立てられている。テストベクター(#419)、例における nonce のエントロピー(#420)、編集上のコメント(#417)である。またドラフトは Publication Requested と Submitted to IESG for Publication の状態にあり、ここでの文言はほぼ最終形になる。
  • 根拠となる資料: -08 の差分は、CONNECT の例外、wimse-aud への Simple String Comparison、64 ビット以上の nonce エントロピー、三つの登録済み問題タイプによる一様なエラー処理、およびシェパードレビューへの対応を加えている(Appendix B.1)。2026 年 11 月 6 日には、個人参加者が -08 向けのテストベクター一式(正例 6 件、負例 22 件、所見 3 件)を issue #419 に投稿し、WIMSE メーリングリストで告知した。issue 上での Yaron Sheffer のレビューと別の参加者による独立した検証を受けて、作者は 11 月 7 日に P-01、P-02、P-06、N-15 を再生成した。これらは @query の値に先頭の ? が欠けていた。11 月 5 日には Kathleen Moriarty が導入部への編集上のレビューを送り、Yaron Sheffer が issue #417 として記録した。
  • 期待される影響: 検証実装を共通の入力でテストできるようになり、これまで SHOULD や暗黙だった複数の挙動(nonce の生成とエントロピー、エラー時のステータスコード、wimse-aud の比較方法)が MUST になる。TLS の要件は新しくない。-07 でもすでに MUST で、Section 5.1 から Section 3 に移っただけである。-07 の実装は、nonce、エラー処理、audience の比較、CONNECT の経路を確認する必要がある。Section 4(Implementation Status)には二つの実装が最終更新日付きで載っているが、対応する版は書かれていない。Cofide(2025 年 11 月 13 日)と wimsey(2026 年 9 月 8 日)である。Cofide のリポジトリは前身の draft-ietf-wimse-s2s-protocol の実装だと説明しており、最終 push は 2025 年 11 月 14 日なので、-08 の変更より前のものである。-08 の後、ドラフトの main ブランチでは wimsey の項目が「signed responses as per version -08 of the draft」に更新された(PR #406)。

変更点

  • CONNECT の例外(Section 3): 送信者は @method と @authority を対象に含めなければならず、@path と @query を含めてはならない。CONNECT リクエストに対する署名付きレスポンスでは、パスとクエリのコンポーネントの代わりに @method;req と @authority;req を用いる。それ以外のメソッドでは引き続き @authority を省く。
  • @request-target の記述: -07 の「HTTP/1.1 以外では NOT RECOMMENDED」という文は、「@request-target ではなく @path と @query を別々に対象とし、[RFC9421] の Section 2.2.5 に従う」という記述に置き換えられた。
  • wimse-aud(Section 3.2): 受信者は、信頼済み設定にある値と Simple String Comparison([RFC3986] の Section 6.2.1)で照合しなければならない。末尾のスラッシュや明示的な既定ポートは一致せず、許容する変種はそれぞれ設定しなければならない。受信者は Host などのリクエストフィールドから audience を導出してはならない。
  • nonce(Section 3): 送信者は暗号論的に安全な乱数生成器を用いなければならず、エントロピーは 64 ビット以上、96 ビット以上が RECOMMENDED である。
  • 時間枠(Section 3): 受信者は有効期間外の署名を拒否しなければならない。Security Considerations にあった MUST をここに移したものである。
  • TLS(Section 3): サーバー認証付き TLS 接続とクライアントによるホスト名検証([RFC9525])の MUST は、Section 5.1 からプロトコルの節に移った。BCP 195 に従うことを求める SHOULD が新たに加わった。
  • Content-Digest(Section 3)は [RFC9530] を参照するようになった。[RFC9530] は [RFC3986]、BCP 195 と並ぶ新しい規範的参照である。
  • エラー処理(Section 3.6): 認証の失敗には wimse-signature-invalid を付けた 400 を返さなければならず、どの検査が失敗したかを示してはならない。署名が必須だが署名に対応しないサーバーは、wimse-signed-response-unsupported を付けた 501 を返さなければならない。署名に対応するが、このレスポンスには署名できないサーバーは、wimse-signed-response-unavailable を付けた 400 を返さなければならない。-07 では、検証の失敗については「400 などの」ステータスコードが適切と述べるだけで、必須の署名付きレスポンスを返せないサーバーについては 400 か 501 を返す SHOULD だった。problem details の本文は、相手が受け付けないと分かっている場合を除き SHOULD である。
  • wimse-sign-response(Section 3.3): true の場合、サーバーは署名するかエラーを返さなければならない。
  • IANA(Section 7.2): HTTP Problem Types への三件の登録が追加された。
  • 編集上の再構成: Security Goals は本文(-07 の Section 6)から Appendix A に移り、そのぶん Document History は Appendix B、DPoP との比較は Appendix C に繰り下がった。-07 で Security Considerations の下位節だった Privacy Considerations は独立した Section 6 になり、ワークロード資格情報ドラフトへの参照だけに縮小された。Section 5 にあった複数の MUST は、Section 3 を参照する説明文に書き換えられた。Section 3.1 のアルゴリズムの記述は、「ES256 のサポートが MUST であるという要件を引き継ぐ」から、ワークロード資格情報ドラフトのアルゴリズム要件に「従う」に変わった。Section 3.2 と Section 3.3 の「定義する」という文は書き換えられた。
  • 互換性と移行: 短い、または低エントロピーの nonce を使っていた -07 の送信者、URI 正規化後に wimse-aud を比較していた送信者または受信者、署名できないときに別の方法で 501 や 400 を返していたサーバー、およびすべての CONNECT 通信は、変更が必要になる。エラーレスポンスは、相手が problem details を受け付けないと分かっている場合を除き、登録済みの問題タイプを付ける必要がある。

技術的分析

  • 脅威モデルへの含意: WIT はベアラートークンとしては使われないが、盗まれたトークンと署名は、署名の有効期間内なら再送できてしまう(Section 5.1)。短い expires、nonce、任意のリプレイキャッシュがこれを軽減する。ただしドラフトは、攻撃者がどのクラスターメンバーが検証するかを選べる場合、リプレイ検出は有効でないと述べている(Section 5.1、Appendix A.4)。ミドルボックスからは平文の WIT と署名が見えるので、それを取得して再送したり、署名されていないヘッダーを書き換えたりできる(Section 5.2)。ドラフトは、対象コンポーネントを書き換えれば必ず検出されるとし、中間者での再署名は対象外としている。audience を @authority ではなく署名付きパラメーターで運ぶことで、authority が書き換えられても検証が通るようにしている(Section 3、5.1)。Appendix A.4 によれば、リクエストとレスポンスの組が削除されたことを必ず検出できるのは、クライアントが wimse-sign-response で署名を要求し、署名のないレスポンスを拒否する場合だけである。サーバーのローカルポリシーによる署名だけでは、クライアントから見ると日和見的な保護にとどまる(Section 3.5)。
  • プロトコルフローへの含意: 検証の順序は固定されている。まず WIT、次に HTTP メッセージ署名であり、両方が通るまでそれ以上の処理は行わない(Section 3)。WIMSE 署名は tag で見つけるため、中間者による他の署名と共存できる(Section 3、5.2)。wimse-sign-response は Accept-Signature より優先され、Accept-Signature でプロファイルより弱い対象範囲を要求してはならない(Section 3.5)。アルゴリズムは alg パラメーターではなく WIT の cnf.jwk.alg から決まり、ローカルポリシーで許容されないアルゴリズムは受信者が拒否する(Section 3.1)。署名に関する二つのエラー経路は、ステータスコードと問題タイプだけで区別される。未対応は 501、利用不能は 400 である(Section 3.6)。
  • 相互運用上の懸念: wimse-aud は完全一致の文字列として比較されるため、「送信者が知る」既定の対象 URI を使う送信者は、設定された値とバイト単位で一致させなければならない(Section 3.2)。@query はクエリが空でも含めなければならず、その値は ? である(Section 3)。署名ベースで先頭の ? を落とす誤りは、issue #419 のテストベクターの初版で実際に起きている。本文がある場合、Content-Digest は必ず存在し、検証されなければならない。CONNECT のリクエストとレスポンスは、異なる対象集合を用いる(Section 3)。Section 3 と 3.6 は WIT の検証についてワークロード資格情報ドラフトの「Section 5.1.4」を参照しているが、参照先の版(-02)に Section 5.1.4 はない。検証手順は、-08 より後に出た workload-creds-03 の Section 5.1.3 にある。Section 3.7 の例は固定の nonce(abcd1111 から abcd4444)を使っている。16 進 8 文字で最大 32 ビット、しかもランダムではないので Section 3 の下限を満たさず、真似してはいけない(issue #420)。例のファイルは -07 から変わっておらず、issue #419 の独立した検証では、Figure 2 の署名は ?flavor=vanilla で検証できたと報告されている。問題タイプの URI は IANA の Problem Types レジストリの名前空間にあり、Section 7.2 の登録が完了している必要がある(Section 7.2)。

未解決の問題

  • keyid と alg に対する検証側の挙動(Section 3): ドラフトは送信者に対して「使ってはならない」と述べているが、検証側がそれらを含むメッセージを拒否するのか無視するのかは、ドラフトの本文に書かれていない。テストベクターの作者は「reject」と記録し(issue #419 の N-06 と N-07)、リストで尋ねた。-08 のヘッダーに載る著者 2 人(Joe Salowey と Yaron Sheffer)のうち Sheffer が、2026 年 11 月 7 日に個人の意見として「IMO a MUST NOT in any security RFC should be rejected by the recipient.」と返信した。これはリスト上の一著者の意見で、ドラフトが採用した規定ではない。-08 後の main ブランチも含め、ドラフトの本文にはまだ書かれていない。
  • 例の nonce(Section 3.7): issue #420 は、#419 の所見 O-2 を受けて Yaron Sheffer が 2026 年 11 月 7 日に立てたもので、例の nonce は説明用でエントロピーの下限を満たさないという編集上の注記を例の近くに加えるよう求めている。例の生成コードは変えない方針である。issue は open のままで、注記はまだドラフトにない。
  • nonce の形式(Section 3): ドラフトはエントロピーのビット数を定めているが、nonce 文字列の符号化や長さは定めておらず、受信者がエントロピーをどう確認できるかも述べていない。-08 の後、main ブランチでは、同じ要件を満たすならクライアントが Accept-Signature にあるサーバー生成の nonce を使ってもよいことになった(PR #404、-09 向け)。
  • CONNECT の audience(Section 3、3.2): wimse-aud の既定値はクエリとフラグメントを除いた対象 URI だが、CONNECT の対象は authority-form である。CONNECT の場合の既定の audience が何かは、ドラフトに書かれていない。
  • 一様な 400 と別個の問題タイプ(Section 3.6): サーバーはどの検査が失敗したかを示してはならないが、署名付きレスポンスが利用できない場合の 400 は別のエラーである。problem details を受け付けないクライアントは両者を区別できず、ドラフトはこれを論じていない。
  • 中間者による再署名(Section 5.2): WIMSE 署名を剥がして置き換える処理は、デプロイ環境ごとのポリシーに委ねられている。
  • 導入部の文言(Section 1): Kathleen Moriarty のレビュー(issue #417)は、最初の文に HTTP を明記し、複数の TLS ホップにまたがるオブジェクトレベルの認証を説明するよう提案している。issue は open で結論は出ておらず、-08 の Section 1 にその文言はない。
  • リプレイキャッシュの範囲(Section 3、5.1、Appendix A.4): 何をどれだけの期間記憶するかはローカルポリシーであり、別のクラスターメンバーへのリプレイは成功し得る。
  • Appendix C には、署名付きレスポンスを必須にするかどうかは将来の版で決められる、という記述が残っている。

実験

  • Lab 1: Section 3.7.1 の Figure 2 のリクエストと Figure 4 のレスポンスについて、RFC 9421 のライブラリで署名ベースを再構築し、WIT 内の公開鍵で署名を検証して、@query が先頭の ? を含む ?flavor=vanilla になっていることを確認する。
  • Lab 2: issue #419 のテストベクター一式(P-01、P-02、P-06、N-15 は作者の 11 月 7 日のコメントにある再生成後の署名)に対して検証実装を実行し、受理と拒否の判断を期待結果と比較する。特に wimse-aud の変種(末尾のスラッシュ、明示的な既定ポート)、wimse-workload-to-workload の tag の重複、keyid と alg の存在、CONNECT の各ケースを見る。2026 年 11 月 11 日に一部を実施した(検証ログを参照)。受理か拒否かを判定する 22 本は実行したが、負例の入力の多くは issue の説明文から再構成したもので、N-17 と N-20 は未了である。
  • Lab 3: Host を書き換える TLS 終端プロキシをサーバーの前に置き、wimse-sign-response を true にした署名付きリクエストを送る。検証が引き続き成功すること、署名できない(ストリーミングの)サーバーが wimse-signed-response-unavailable を付けた 400 を返すこと、署名に対応しないサーバーが wimse-signed-response-unsupported を付けた 501 を返すことを確認する。

情報源

背景

きっかけ

新しい版が出て差分を取れる活動中の WG ドラフトとして、draft-ietf-wimse-http-signature-08 を選んだ。選定時のメモによれば、このドラフトには新しい issue が三つ立っている。テストベクター(#419)、例における nonce のエントロピー(#420)、編集上のコメント(#417)である。Datatracker の状態は Active、Publication Requested、Submitted to IESG for Publication である。

なぜ重要か

ドラフトは WG での手続きの終盤にあり、-08 の変更は IESG のレビュー前に挙動を固める最後の機会になる。-08 は、いくつかの緩い点を MUST にした。nonce の生成とエントロピー、400 と 501 のエラー挙動、wimse-aud に対する Simple String Comparison である。あわせて三つの問題タイプを登録し、既存の TLS の MUST を Security Considerations から Section 3 に移し、CONNECT の例外を加えた。-08 向けの独立したテストベクターが issue #419 に投稿されて WIMSE リストで告知され、査読者が導入部へのコメントを送った。-07 の実装者は変更点を確認する必要があり、検証実装を書く人は共通の入力でテストできるようになった。

未解決の問題

  • keyid と alg が存在する場合に、検証側が拒否するのか無視するのか。ドラフトは送信者が使ってはならないとだけ述べている(Section 3)。リストでの Yaron Sheffer の返信(2026 年 11 月 7 日)は拒否を支持しているが、本文には書かれていない。
  • authority-form を対象とする CONNECT で、既定の wimse-aud が何になるか(Section 3、3.2)。
  • 相手が problem details を受け付けない場合に、署名の「未対応」と「利用不能」をどう区別するか(Section 3.6)。
  • issue #420 がいつ反映されるか。Section 3.7 の例の nonce(abcd1111 など)は説明用で 64 ビットの下限を満たさない、という編集上の注記を求めている。issue は open である。
  • Kathleen Moriarty のレビュー(issue #417)で提案された導入部の文言が採用されるかどうか。issue は open で結論は出ておらず、-08 の Section 1 には含まれていない。

仕様メモ

参照

-08 に列挙されている規範的参照(Section 8.1):

  • BCP 195(RFC 8996 と RFC 9325)。-08 で新規。
  • draft-ietf-wimse-workload-creds-02(Workload Identity Token)。Section 3 と 3.6 は WIT の検証としてその「Section 5.1.4」を参照しているが、-02 に Section 5.1.4 はない(-02 の Section 5.1.3 は iss と鍵配布に関する注記)。検証手順は、-08 より後の 2026 年 10 月 30 日に出た workload-creds-03 の Section 5.1.3(「Validating the WIT」)にある。
  • RFC 2119 と RFC 8174(キーワード)。
  • RFC 3986(Simple String Comparison、Section 6.2.1)。-08 で新規。
  • RFC 7942(Implementation Status の節)。
  • RFC 9110(HTTP Semantics。CONNECT は Section 9.3.6、対象 URI は Section 7.1)。
  • RFC 9421(HTTP Message Signatures)。
  • RFC 9457(Problem Details for HTTP APIs)。
  • RFC 9525(ホスト名検証、Section 6.3)。
  • RFC 9530(Digest Fields)。-08 で新規。

参考情報の参照(Section 8.2):

  • draft-ietf-oauth-transaction-tokens-11(Txn-Token ヘッダー)。
  • draft-ietf-wimse-arch-08(用語とアーキテクチャ)。-07 では規範的参照で、-08 では参考情報の参照になった。ドラフトのソースでは {{!I-D.ietf-wimse-arch}} が {{?I-D.ietf-wimse-arch}} に変わっている。理由はシェパードレビュー(issue #385)にあり、「wimse-arch は本当に規範的か。参考情報のはずで、規範的なら downref になる」という指摘への対応である。
  • draft-ietf-wimse-mutual-tls-02。
  • draft-ietf-wimse-wpt-02(DPoP に着想を得た代替方式)。
  • IANA の HTTP Message Signature レジストリ。
  • RFC 9449(DPoP)。
  • RFC 9864(例で使う完全指定のアルゴリズム識別子 Ed25519)。

アルゴリズムそのものは WIT の cnf.jwk.alg で決まる(Section 3.1)。-08 は独自の基準を置かず、ワークロード資格情報ドラフトに従う。そちらでは汎用実装は ES256 をサポートしなければならず(MUST)、none、対称鍵、暗号化のアルゴリズムを除く IANA JOSE の署名アルゴリズムが使える。Ed25519 は例で使われているだけで必須ではなく、非推奨の EdDSA もどちらのドラフトでも禁止されていない。

主な変更

  • Section 3: リクエストと署名付きレスポンスに対する CONNECT の例外(@path と @query の代わりに @method と @authority)。
  • Section 3: Content-Digest が RFC 9530 を参照する。nonce には暗号論的に安全な乱数生成器と 64 ビット以上のエントロピー(96 ビット以上が RECOMMENDED)が必要になる。受信者は有効期間外の署名を拒否しなければならない(MUST)。サーバー認証付き TLS 接続とクライアントによるホスト名検証は、この節で要求される。
  • Section 3.1: アルゴリズムの基準の記述が、ワークロード資格情報ドラフトのアルゴリズム要件に「従う」に変更された。
  • Section 3.2: wimse-aud は受信者の信頼済み設定に対して Simple String Comparison で比較され、audience を Host から導出してはならない。
  • Section 3.3: wimse-sign-response が true の場合、サーバーは署名するかエラーを返す義務を負う。
  • Section 3.6: 認証の失敗にはすべて wimse-signature-invalid を付けた 400 を返し、どの検査が失敗したかは示さない。必須の署名に失敗した場合は、wimse-signed-response-unsupported を付けた 501、または wimse-signed-response-unavailable を付けた 400 を返す。problem details は SHOULD である。
  • Section 7.2: HTTP Problem Types への三件の登録。
  • 再構成: Security Goals は Section 6 から Appendix A に移り、Document History は Appendix B、DPoP との比較は Appendix C に繰り下がった。-07 の Section 5.3 だった Privacy Considerations は Section 6 になり、参照だけに縮小された。Section 5 の MUST は、Section 3 を参照する説明的な記述に言い換えられた。
  • -08 の文書履歴の項目は三つで、シェパードレビュー(#385)、CONNECT の例外(#368)、Simple String Comparison(#396)である。nonce、TLS、エラー処理、問題タイプ、Privacy、付録、wimse-arch の変更は個別には書かれていないが、どれも issue #385 にある Justin Richer のシェパードレビューの指摘に対応している。#385 は 2026 年 10 月 20 日に全項目にチェックが付いた状態で閉じられた。
  • メタデータ: 有効期限が 2027 年 4 月 23 日に変わり、第二著者の所属が Intuit から Independent に変わった。

影響分析

  • 上流: 署名の仕組みは RFC 9421、WIT とその検証は WIMSE のワークロード資格情報ドラフト、エラー本文は RFC 9457 と HTTP Problem Types レジストリに依存する。新たに加わった RFC 9530 への参照は、Content-Digest の生成方法に影響する。
  • 下流: Section 4 に挙がっている Cofide(proof-of-concept)と wimsey(alpha)の実装、および issue #419 のベクター一式を使うテスト作成者は、-08 の規則に従う必要がある。Section 4 には最終更新日(2025 年 11 月 13 日、2026 年 9 月 8 日)しかない。Cofide のリポジトリは draft-ietf-wimse-s2s-protocol の実装だと説明しており、最終 push は -08 より前の 2025 年 11 月 14 日である。-08 の後、main ブランチで wimsey の項目は「signed responses as per version -08 of the draft」に更新された(PR #406、2026 年 10 月 23 日マージ)。IANA は三つの署名メタデータパラメーターと三つの問題タイプを登録しなければならない。
  • 互換性: CONNECT を除き、正しい -07 のメッセージのワイヤ形式が -08 で変わることは示されていないが、送信者が作るべきもの(CSPRNG による 64 ビット以上のエントロピーを持つ nonce)、検証側による wimse-aud の比較(文字列の完全一致)、サーバーが返すべきもの(問題タイプ付きの 400 または 501)は厳しくなる。有効期間外の署名の拒否は、-07 でもすでに MUST だった(当時は Section 5.1)。正規化後の audience 比較、短い nonce、別のエラーコードに依存していた送信者は失敗し得る。ドラフトは移行期間について論じていない。

テストベクターの再実行

2026 年 11 月 11 日、このリポジトリは issue #419 の 28 本のベクターを、-08 の本文と RFC 9421 から書いた検証器にかけた。P-01、P-02、P-06、N-15 には、11 月 7 日のコメントにある再生成後の値を使った。issue がバイト列そのものを載せているのは、正例と N-15 だけである。それ以外の負例は、正例にどんな変更を加えるかを説明しているだけなので、スクリプトが入力を自分で組み立てた。これらはこのリポジトリによる再構成で、issue のバイト列ではない。スクリプトは vectors/verify_419.py、出力は vectors/verify_419.log にあり、再現手順は検証ログに書いた。検証器が正しく動いていることは、次のように確かめた。公開されているテスト用の鍵で signature base を組み直して署名し直すと、公開されている 8 本の署名とバイト単位で一致する(ログの 1 節)。

  • 入力: P-01〜P-06 と N-15 は公開されているメッセージそのもので、スクリプトはその 8 本の署名をバイト単位で再現する。N-04(本文の差し替え)と N-09(検証時刻を後ろにずらす)は、公開されているメッセージを元の署名のまま使う。N-14 は、公開されている P-02 のレスポンスから署名を取り除いたものである。N-01、N-02、N-03、N-05、N-06、N-07、N-08、N-10、N-11、N-12、N-13 は、変更を加えたあと公開されているテスト用の鍵で署名し直す。N-21 は値が示されていない issue の説明文から組み立て、同じ方法で署名する。N-16〜N-22 は振る舞いを扱うもので、スクリプト自身の送信側・サーバー側・検証側の処理に対する検査として実行する。
  • 結果: 受理か拒否かを判定する 22 本(P-01〜P-06、N-01〜N-15、N-21)は、この検証器ですべて期待どおりの判定になった。N-16、N-18、N-19、N-22 は送信側・サーバー側・検証側の振る舞いを扱う。スクリプトはこれらを自分の nonce 生成器、レスポンスの検査、署名の選び方に対して実行している。そのため一致しても、スクリプトの読み方での -08 の本文と期待結果が食い違わないことを示すだけで、他の実装については何も言えない。N-17(どの検査で失敗したかをエラーで明かさない)と N-20(何より先に WIT を検証する)は、メッセージ 1 本からは判定できないため採点していない。
  • N-04: issue には、本文の変更で "also makes the signature fail" と書かれている。今回の実行ではそうならなかった。変わるのは本文だけで、Content-Digest ヘッダーは元の値のままであり、署名が対象にしているのはそのヘッダーである。検証器が報告した失敗は、受信した本文から計算し直したダイジェストの不一致だけだった(Section 3: "the receiver MUST compute the Content-Digest value for the message content received and compare it with the Content-Digest value provided in the message")。
  • N-09: 検証時刻 T0+3600 が WIT-A の exp と同じなので、WIT の期限切れと署名の有効期間外が同時に起きる。スクリプトは T0+301 でも検査しており、この時刻では有効期間の検査だけが失敗し、やはり拒否される。
  • N-15: ES256 の署名は cnf.jwk の Ed25519 鍵では署名不正として失敗し、svcC の ES256 鍵では検証に通る。そのため cnf.jwk から鍵を取る検証器では、このベクターは Section 3.1 の「ローカルポリシーで許可されないアルゴリズム」の検査まで届かない。
  • -08 の本文が送信側の規則としてしか書いていない期待結果: N-06 と N-07(keyid と alg は "MUST NOT be used")、N-01(必須のコンポーネントは "MUST be signed")、N-02 と N-21(CONNECT の送信者は "MUST NOT cover @path or @query")。この検証器でこれらの規則を受信側で強制しない設定にすると、署名そのものは正しいので、この 5 本(N-01、N-02、N-06、N-07、N-21)はすべて受理される。他の検証器が拒否するかどうかは、送信側の規則をどう読むかによる。
  • P-04 は @authority を svcb.example.com:443 として署名している。-08 の Section 3 は "The @authority value is the host and port of the CONNECT target (Section 2.2.3 of RFC9421)" と書く。RFC 9421 の Section 2.2.3 は "The component value MUST be normalized according to the rules provided in [HTTP], Section 4.2.3. Namely, the hostname is normalized to lowercase, and the default port is omitted." と書く。authority 形式の CONNECT の対象にはスキームがなく、443 をその既定のポートとみなすかどうかはどちらにも書かれていない。そのため、この値は実装によって分かれ得る。

相互運用チェックリスト

  • リクエストが @method、@path、@query を対象に含み、CONNECT 以外のメソッドでは @authority を対象に含めていない(Section 3)。
  • クエリのないリクエストでも、@query に値 ? を付けて署名している(Section 3、RFC 9421 の Section 2.2.7)。また ?flavor=vanilla のような空でないクエリでは、署名ベースが先頭の ? を保持している。
  • CONNECT では、リクエストが @method と @authority を対象にして @path と @query を対象にせず、署名付きレスポンスが @method;req と @authority;req を対象にして @path;req と @query;req を対象にしていない(Section 3)。
  • Content-Type、Content-Digest、Authorization、Txn-Token、Workload-Identity-Token が存在する場合に対象に含まれ、署名付きレスポンスのすべてで Workload-Identity-Token が対象に含まれている(Section 3)。
  • 本文がある場合、Content-Digest が存在し、RFC 9530 に従って受信した内容から計算され、受信者が比較している。欠落または不一致の値は拒否される(Section 3)。
  • リクエストとレスポンスに created、expires、nonce、tag があり、tag が wimse-workload-to-workload に等しく、expires が短い(Section 3)。
  • 送信時に keyid と alg がない。これらが存在する場合の検証側の挙動はドラフトにないため、選択(拒否か無視か)を記録する。リストでの Yaron Sheffer の返信は拒否を支持しており、issue #419 のベクターも拒否を期待している(N-06、N-07)(Section 3)。
  • WIMSE 署名はラベルではなく tag で選択される。その tag を持つ署名が二つあるメッセージは拒否され、その tag がないメッセージは WIMSE 署名を持たないものとして扱われる(Section 3)。
  • nonce は暗号論的に安全な乱数生成器から得られ、64 ビット以上のエントロピーを持つ。Section 3.7 の abcd1111 のような固定の nonce をそのまま使わない(Section 3、issue #420)。
  • 有効期間(created と expires)外の署名は拒否される。ドラフトは許容値を示していないため、時計のずれに関する方針を文書化する(Section 3)。
  • 署名を確認する前に WIT を検証し、両方が通るまで何も処理しない(Section 3)。-08 はこの手順として workload-creds の「Section 5.1.4」を挙げているが、参照先の -02 にその節はない。workload-creds-03 の Section 5.1.3(「Validating the WIT」)を使う。
  • 署名アルゴリズムを WIT の cnf.jwk.alg から取り、ローカルで許容しないアルゴリズムは拒否する(Section 3.1)。ES256 は workload-creds が汎用実装にサポートを求めているので検証できる。Section 3.7 の例で使われる Ed25519 は、サポートしていれば検証できる。非推奨の EdDSA はどちらのドラフトも禁止していないので、扱いを意図して決めておく。
  • wimse-aud は設定された値と完全一致の文字列比較で照合される。末尾のスラッシュや明示的な既定ポートは一致しない。Host から導出されることはない(Section 3.2)。
  • 送信者の既定の wimse-aud(クエリとフラグメントを除いた対象 URI)が受信者の設定した文字列と一致するか、プロキシが URI を書き換える場合はデプロイ環境固有の audience が使われる(Section 3.2)。
  • wimse-sign-response は Boolean パラメーターであり、クライアントが署名を要求する場合にのみ true として書かれる。その場合クライアントは署名のないレスポンスを拒否し、それ以外では署名のないレスポンスを受け入れる(Section 3.3、3.5)。
  • 署名付きレスポンスのすべてで wimse-req-nonce にリクエストの nonce が設定され、クライアントは欠落または異なる値を拒否する(Section 3.4、3.5)。
  • クライアントが Accept-Signature を送る場合、少なくともプロファイルが要求するコンポーネントを列挙し、両者が食い違うときは wimse-sign-response が優先される(Section 3.5)。
  • 認証の失敗には問題タイプ wimse-signature-invalid を付けた 400 が返され、レスポンスから WIT と HTTP メッセージ署名のどちらが失敗したか分からない。この用途での 401 は NOT RECOMMENDED である(Section 3.6)。
  • 署名が必須だが未対応の場合、サーバーは wimse-signed-response-unsupported を付けた 501 を返す。署名に対応しているがこのレスポンスには不可能な場合(ストリーミング、非常に大きい場合)は、wimse-signed-response-unavailable を付けた 400 を返す。署名のない成功レスポンスは決して返さない(Section 3.5、3.6)。
  • 署名の失敗による 400 または 501 を受け取ったクライアントが、両方の問題タイプを扱え、相手が problem details の本文を送らない場合も適切に動作する(Section 3.6)。
  • WIT と署名は、サーバー認証付き TLS 上でのみ送られ、クライアントは RFC 9525 に従ってホスト名を検証している(Section 3)。
  • 独自の HTTP メッセージ署名を加えるプロキシが WIMSE 署名の選択を妨げず、対象コンポーネントを変更するプロキシがあれば検証が失敗する(Section 5.2)。
  • リプレイキャッシュを実装する場合、その挙動がローカルポリシーとして文書化されており、リプレイが別のクラスターメンバーに届いた場合の挙動も含まれている(Section 3、5.1)。
  • issue #419 のテストベクターを使う場合、P-01、P-02、P-06、N-15 の署名は作者の 11 月 7 日のコメントにある値を使う。issue 本文には、先頭の ? を欠いた @query で計算した元の値が残っている。
  • issue #419 の N-04 では、署名は有効なままで、計算し直した Content-Digest の不一致だけで失敗することを期待する。N-04 を署名の失敗として報告する検証器は、このベクターでは起きない失敗を報告している。
  • #419 が拒否を期待している送信側だけの規則について、受信側でどう扱うかを記録する。keyid や alg がある場合(N-06、N-07)、必須のコンポーネントがない場合(N-01)、CONNECT で @path がカバーされている場合(N-02、N-21)。CONNECT の @authority に明示の :443 を残すかどうかも記録する(P-04)。

検証ログ

環境

  • ランタイム: Python 3.15.2(vectors/verify_419.log の 1 行目に出力される)
  • ツール: cryptography 50.0.2(同じ行)(Ed25519、RFC 6979 の決定論的署名による ECDSA P-256)、ドラフトのソース取得に gh
  • バージョン: draft-ietf-wimse-http-signature-08(ietf-wg-wimse/draft-ietf-wimse-s2s-protocol のタグ draft-ietf-wimse-http-signature-08)、issue #419 のベクター(2026 年 11 月 7 日の再生成後の値)

手順

  1. Section 3.7 の例が使う sigs-*.txt のインクルードファイルを、タグ draft-ietf-wimse-http-signature-08 からローカルの includes/ に取得する(gh api repos/ietf-wg-wimse/draft-ietf-wimse-s2s-protocol/contents/<file>?ref=draft-ietf-wimse-http-signature-08 -H "Accept: application/vnd.github.raw")。
  2. python3 -I vectors/verify_419.py includes/ > vectors/verify_419.log を実行する。issue #419 のベクターの入力とテスト用の鍵はスクリプトに書き込んであるので、インクルードファイルが要るのは Section 3.7 の例の検査だけである。
  3. ログ末尾の集計表と、N-01、N-04、N-06、N-07、N-09、N-15 の個別の注記を読む。

結果

  • ログの 0 節: テスト用の鍵はどれも SHA-256("s01-validation-vectors:<name>") から導かれ(svcC は n-1 で割った余りに 1 を足す)、三つの WIT は発行者の鍵で検証に通る。
  • 1 節: スクリプトは公開されている 8 本の署名(P-01〜P-05、P-06 の 2 本、N-15)をバイト単位で再現する。
  • 負例の多くは、issue が説明する変更をこのリポジトリが再構成したもので、issue のバイト列ではない。どのベクターがどの入力を使ったかは仕様メモに書いた。
  • 期待結果と食い違ったベクターはなかった。受理か拒否かを判定する 22 本と、振る舞いを扱う 4 本が一致した。N-17 と N-20 は採点していない。所見は仕様メモの「テストベクターの再実行」にまとめた。

失敗パターン

  • P-01、P-02、P-06、N-15 に、11 月 7 日の値ではなく issue 本文の元の署名を使う: 元の署名は、先頭の ? を欠いた @query でしか検証に通らない。
  • N-04 を署名の失敗として報告する: 署名は正しく、失敗するのは計算し直したダイジェストだけである。

次にやること

  • N-17 と N-20 を、エラー本文と検査の順序を観測できる実際のサーバーに対して採点する。
  • スクリプトの WIT 検証を、ワークロード資格情報ドラフトの本文と突き合わせる。スクリプトはこのリポジトリの読み方に従っており、条項ごとの照合はしていない。