要約

  • 2026年9月5日公開の個人Internet-Draftは、165オクテットのCOSE_Sign1を出発点に、6種類の二者択一のCBOR符号化を組み合わせた。
  • 64通りはすべて異なるバイト列と異なるdata-hashを生んだ。衝突はなく、Sig_structureは全件で同じ109オクテットだったため、署名はすべて検証できた。
  • 通常のデコーダーは1件も拒否しなかった。31件は、読み込んで書き戻すだけで出発時の表現へ無言で変換された。
  • 公開スクリプトとハッシュが一致する制品を使った独立実行でも、64個のハッシュ、拒否0件、正規化31件を再現した。
  • これは暗号破りでも実運用事故でもない。識別子の入力バイトを明示し、そのバイトを再現できる状態で保管するという統治課題である。

署名が見ている対象、ハッシュが見ている対象

RFC 9052に従うCOSE署名は、所定のコンテキスト、保護ヘッダー、外部認証データ、ペイロードからSig_structureを組み立てる。外側のCBORコンテナをどの長さ形式や分割方法で表すかは、必ずしも署名入力に含まれない。

一方、今回の測定草案data-hashと呼ぶ値は、送信された文全体のオクテット列を入力とする。検索や重複排除、後続の証明で使うなら、同じ意味ではなく同じバイトを識別するための名前だ。

したがって、同じ署名が通り、同じ項目を取り出せても、表現が違えばハッシュは違ってよい。危険なのは、その違いを仕様や記録から消し、意味の同一性をバイト同一性の代用品にすることである。

6個の選択肢が作る立方体

実験のAは165オクテットである。値を一切変更せず、CBORタグ18の有無、外側配列の確定長・不定長、非保護ヘッダーマップの確定長・不定長を切り替える。さらに保護ヘッダー、ペイロード、署名の各バイト文字列を一括または分割で出力する。

二択が6個なので組み合わせは64通りになる。公開JSONでは長さが164~170オクテットに分かれ、SHA-256は64個すべて異なる。衝突は0件だが、署名検証に使う109オクテットのSig_structureは1種類しかない。

64は全空間の大きさではない。整数の符号化幅とマップキーの順序は変えていない。RFC 8949が認める表現差はさらに広い。発見済みの形式だけを禁止する方式では、未知の組み合わせを閉じたと証明できない。

エラーなしで原本を失う

デコーダーは64件すべてを受け入れた。31件では、デコード後に同じライブラリでエンコードするとAと完全に同じバイトが出た。入力の表現は消えたのに、アプリケーションから見れば処理は成功している。

ここに監査上の落とし穴がある。サービスがBを受け取り、hash(B)を公開した後、Bそのものではなく再出力Aだけを保存したとする。後日も署名は検証できる。しかし保存物からhash(B)は作れない。公開インデックスが指す証拠と、サービスが手元に残した証拠が一致しない。

「無言」という表現は悪意を意味しない。整った形式で出力することはライブラリの正当な動作になり得る。測定は実在サービスの保存方法も故障率も調べていない。ただし、パース成功をバイト保管の証明に使えないことは実証した。

再実行で確認できた範囲

著者は起点ベクトル、64件の測定結果、生成スクリプトを公開している。raw配布先への接続に失敗したため、GitHub Contents APIから同じスクリプトを取得し、2個のJSON制品のハッシュを照合してから一時環境で実行した。

AはSHA-256 8595e4a4c8b93e7b1b7b798dc302a2b7d2890021f7eff372d79b32f78867e4acとしてバイト単位で再構成され、異なるdata-hash 64個、拒否0件、Aへの変換31件が再現された。こちらはcbor2 5.7.1、草案記載の環境は6.1.3、CPython 3.13、macOS arm64である。別バージョンでの一致は中心結果を補強するが、網羅的な相互運用試験ではない。

Datatracker上、この文書はIETFの支持も標準化手続上の正式な地位もない個人草案である。RFCストリーム、担当Area Director、telechat日程もない。文書自身も規範を提案しないと明記する。署名偽造、ハッシュ衝突、暗号プリミティブの破綻、実サービスの事故は一つも示されていない。

「登録されたまま」はまだ決定ではない

測定結果は、IETF Last Call中だったCOSE Receipt向けCCFプロファイルの議論にも入った。Nicholas Templemanは9月5日のメールで文書の前進を支持しつつ、data-hashを再シリアル化ではなく登録時のオクテットに結び付ける文言を提案した。この指摘は非ブロッキングだとも記した。

これは参加者の意見で、採択済み文言やIETF合意ではない。SCITT Reference APIsとCCFプロファイルは作業中のWG草案である。RFC 9943はSigned Statement、登録、Receiptの役割を定めるが、今回の正確なプリイメージまで自動的には決めない。

先行する個人草案Canonical Payload Bindingには、正規化をせず受信オクテット列をそのまま入力にするas-transmittedがある。jcs-ncde-nはWithdrawnと表示される。今回の測定は既存案が扱うクラスを数量化したのであり、その案を標準化したのではない。