要約

  • draft-templeman-scitt-framing-space-00は2026年9月5日に公開された個人提出のInformational Internet-Draftである。RFCでもIETFの合意でもなく、規範文を提案する文書でもない。
  • 6個の二値CBOR framingを組み合わせた実験は、受理可能な64バイト列と64個の異なるdata-hashを得た。一方、Sig_structureは一つだけで、同一署名がすべてで有効だった。
  • 64例のうち31例は、読み込みと再符号化だけで正規形Aへ黙って変換された。原受信バイトを先に保存しないサービスは、自ら発行した識別子を再現できなくなる。

問題は、異常な入力が拒否される場面ではない。入力が受理され、署名も通り、保存も成功する場面で起きる。

受信口は到着したbyte sequenceをハッシュして識別子を返す。次の処理はCBORをデコードし、値だけをキューへ渡す。保存層はその値をライブラリの好む形式で再符号化する。後日、識別子を検証しようとすると、保存されたバイトのハッシュは最初の値と一致しない。

Nicholas Templemanによる8ページの新ドラフトは、この経路を測定可能な形にした。9月5日のI-D告知が公開日と文書の身分を記録している。ドラフト自身も「何も規定せず、文言も提案しない」と限界を明示する。これは現在のSCITT作業への実験材料であり、標準化決定ではない。

外枠は同じ署名入力に含まれない

RFC 9052では、COSE署名はSig_structureから作る。COSE_Sign1の場合、context、protected attributes、external AAD、payloadが入る。外側コンテナのCBOR表現すべてが署名対象になるわけではない。

RFC 8949は、一つのデータモデル値に複数の直列化を許す。arrayやmapは定長にも不定長にもでき、byte stringは一体でもchunk分割でも表せる。利用profileが認めればtagの有無も違いになり得る。decoderが得る値は同じでも、通信路に現れたoctetは同じではない。

測定は165 octetのCOSE_Sign1オブジェクトAから始まる。変えるのはtag 18の有無、外側arrayとunprotected header mapの長さ形式、protected header・payload・signatureの三つのbyte stringを一体で出すか分割するか、という6項目である。

6個のスイッチから64組が生まれ、長さは164から170 octetになった。cbor2 6.1.3は一つも拒否しなかった。復元されたSig_structureは全例で同じ109 octetであり、同じ署名が検証できた。

ところが通信バイトをSHA-256に入れると、64個の異なるdata-hashになった。collisionはゼロである。異なる入力から異なるhashが出て、同じ署名入力では同じ署名が通る。暗号は設計どおりに動いている。

64は上限ではない

この実験はinteger widthやmap key orderを変えていない。そのため64という数は、既知の全形式を数え切った値ではなく、6つの独立自由度だけでも空間が急に広がることを示す値である。

運用規則が「tagなしを禁止する」「不定長arrayを禁止する」と発見順に例を並べても、残りの軸が作る組合せは残る。未知の例を探し続ける方式では、クラス全体を閉じたと証明できない。

公開されたframing-spaceデータには結果と生成手順があり、元のdata-hash vectorにはAのバイトがある。ドラフトは実行環境も示し、一つのframing軸について別のplatform・reader・COSE libraryなしで独立再計算されたことも記す。

これで機構は追試できる。しかし、現用サービスの何割が影響を受けるかは分からず、特定製品の欠陥も立証していない。再現可能性と普及率は別の証拠である。

自動整形が「受け取った事実」を消す

最も運用的な結果は31例のsilent repairだ。decoderで読み、再びencoderへ渡すと、31個がAのcanonical bytesに戻った。警告も失敗もない。

値を利用するだけなら、それは便利な標準化である。通信時のoctetを識別するなら、同じ処理は証拠の上書きになる。システムが保持したのは「自分ならどう書くか」であって「相手が何を送ったか」ではない。

data-hashがlookup、deduplication、registration、receipt、次のattestationのキーなら、差は外部結果へ出る。同じ署名済み内容が別レコードとして登録されたり、存在するのに見つからなかったりする。framingへ影響できる者は、payloadやsignatureを壊さずに実用上の識別位置を変えられる。

防御はparserより前に置く。受信bodyをimmutable objectとして保存し、そのバイトへhashを計算し、時刻・送信元・長さ・content typeと、どのnamed byte productionを対象にしたかを記録する。decoded valueとnormalized serializationは別の派生物として結び付け、元の証拠を置換しない。

protocolがdeterministic encodingを一つ選び、入口で非準拠を拒否する方法もある。RFC 8949のSection 4.2はその基礎を与える。ただしencoderがpreferred formを出すことと、decoderが入力をその形式だけに制限することは同じではない。

既存のas-transmitted profile draftはcanonicalizationを行わず、既存formatが名付けた正確なbyte sequenceをselectorで指定する。これは今回の測定より前に公開され、やはり個人ドラフトである。後の測定はその境界が必要な理由を数量化するが、提案へ標準の権威を与えない。

四つの判定を一つの緑ランプにしない

RFC 9943のSCITT architectureはSigned Statement、Transparency Service、Receipt、後段のappraisalを分ける。現在のSCITT Reference APIsとCCF receipt profileではdata-hashが登録や取得の座標になるため、byte identityのずれは実務上の問題になる。

それでも各判定の権限は限定される。raw bytesは一つのcomponentが受信した内容を示す。valid signatureは特定keyの下でSig_structureが壊れていないことを示すが、keyと本人の対応や行為の権限はapplicationが確かめる。receiptはservice ruleに基づく登録を示すが、記述内容の真実、新しさ、採用判断までは示さない。

Heng Luの現実を先に記述する原則に従えば、ここで悪役を作る必要はない。寛容なdecoderも、整った出力を作るencoderも正しく動作できる。失敗は二つの出力を同じ証拠だと扱う設計にある。

running-code primacyは、仕様表ではなく実際のgateway、queue、database、retrieval APIを通して64 vectorを流すことを求める。技術能力と権限の区別は、libraryの変換能力を、公開済みidentifierを書き換える権限にしない。

wire bytesとcanonical valueのどちらが常に正しい、という話ではない。識別対象を明示し、その対象を後から再現できる証拠を残す。それが先に決めるべき制御である。

Sources