要約

  • 複合アルゴリズムは二つのcomponent署名を一つのOIDで表すが、CMSはSignedData、SignerInfo、署名属性に別々の識別子を持つ。signerのdigestは複合名が固定するpre-hashと一致し、signature OIDのparametersは存在してはならない。
  • 二つのcomponentが通っても検証は終わらない。受信側は署名されたDERを正確に再現し、内容digestを再計算し、保護されたアルゴリズム宣言を比較し、証明書と権限を別に判断する必要がある。

暗号ライブラリは二つの成功を返した。ML-DSAの署名は正しく、従来側の署名も正しい。ところがCMS封筒のdigestAlgorithmは、選択された複合OIDが要求するものと違っていた。

個々の計算が成功した時、矛盾した封筒まで成功と呼べるのか。

draft-ietf-lamps-cms-composite-sigs-05は、その判断を実装任せにしないための文書である。LAMPS作業部会のactive Internet-Draftで、IETF stream、想定ステータスはProposed Standard。改訂05は2026年5月22日付で、11月23日に失効する。Datatrackerは10月1日の工程変更を記録し、現在はRFC Editor queueで第二編集者を待つ状態を示す。まだRFCではなく、この状態は製品対応、証明書発行、設定有効化、相互運用性や移行完了の証拠ではない。

基礎となるComposite ML-DSA草案は、ML-DSAとRSA、ECDSA、Ed25519またはEd448を一つの公開鍵・署名インターフェースにまとめ、全componentが成功した時だけ検証を成功させる。CMS草案は、その原語へ渡すバイトと外層の識別子を定める。

一つのOIDでも外層は残る

改訂05は18個の複合OIDを再掲する。同じAlgorithmIdentifierが複合公開鍵と署名アルゴリズムを示し、parametersは必ず欠落する。アプリケーションが独自の二署名コンテナや結合ルールを作らずに済むのが利点だ。

しかしCMSには別の判断面がある。SignedData.digestAlgorithmsはdigest集合を持ち、各SignerInfoはdigestAlgorithmとsignatureAlgorithmを持つ。signedAttrsにはCMSAlgorithmProtectionを置ける。証明書は鍵アルゴリズムを表す。

これらが食い違った時、暗号原語の成功だけではどの宣言を信じるか決められない。回执には複合OID、証明書鍵OID、SignerInfoの二識別子、parametersの有無、署名された保護値、各component verdictを分離して残すべきだ。「PQ署名valid」という一語では解析上の選択が消える。

pre-hashは複合名で決まる

このCMSプロファイルでComposite ML-DSAはpre-hash modeだけを提供する。各複合名はCMS側のdigestを一つに固定する。組み合わせによってSHA-256、SHA-512、またはSHAKE256になる。

SignerInfo.digestAlgorithmはそのdigestと一致しなければならない。SHA-256とSHA-512のparametersは省略する。SHAKE256もparametersを省略し、digest長は64バイトである。

従来componentが内部で別のdigestを使うことはある。ECDSA P-384が内部でSHA-384を使っても、CMS面のpre-hashがSHA-512という複合名は変わらない。ログは「内部」と「CMS外層」を区別しなければ、正しい差を障害に見せたり、危険な外層差を見落としたりする。

SignedData.digestAlgorithmsには対応digestを含めることが推奨される。one-pass verifierが計算を準備できず失敗する可能性があるためだ。ただし、この集合はコンテナ全体の処理ヒントであり、特定SignerInfoのmandatory equalityを代替しない。

signedAttrsが署名対象を変える

署名属性がない場合、署名対象はeContent OCTET STRINGのvalueであり、tagとlength octetsを含まない。

署名属性がある場合、署名対象はSignedAttrs valueの完全なDER encodingになる。tagとlengthを含み、最終メッセージのIMPLICIT [0] tagではなくEXPLICIT SET OF tagを使う。

最低限の属性はcontent-typeとmessage-digestである。受信側は内容からdigestを再計算して比較する。別の方法で再エンコードした属性や、内容digestを検査していない属性に対するcomponent成功は、CMS検証完了ではない。

証拠は受信した生CMSのhashから始める。内容hash、正確なsignedAttrs DER hash、受信digest、再計算digest、複合検証器へ渡したバイト範囲を保存する。整形したASN.1表示は原本を置き換えない。

複合原語にはcontext stringがあるが、このCMS profileは空文字列に固定する。ここで非空contextによる用途分離を主張できない。content type、署名属性、証明書policyまたは検証済みアプリケーション規則が用途を分ける。

アルゴリズムの説明も署名する

RFC 6211のCMSAlgorithmProtectionは、digestとsignatureまたはMAC algorithmをsignedAttrsへ入れる。RFC 8933はCMSの整合規則を強化した。改訂05はalgorithm substitutionを避けるため、この属性を含めることを推奨する。

署名されていない外層フィールドは署名入力を変えずに書き換えられる。保護属性内の識別子はDER署名対象になるため、検証者はSignerInfo、複合OID、証明書鍵と比較できる。

属性があるだけでは足りない。構造、位置、OID、parameters、鍵互換性を検査する。草案がMUSTではなくSHOULDとする以上、欠落を許すかどうかは可視なpolicy座標にし、generic successに埋め込まない。

レジストリと本文の時計は同じではない

草案はASN.1 module identifierをIANAに要求する。凍結した改訂05本文には置換前のplaceholderが残る。一方、10月2日に取得したIANA public registryはid-mod-composite-mldsa-cms-2026にdecimal 88を掲載し、このInternet-Draftを参照する。

両方とも現在の事実である。レジストリには割当があり、草案sourceには編集placeholderがあり、文書はRFC Editor queueにいて、RFC番号はまだない。割当をRFC出版や実装配備と読み替えてはならない。

二つの成功は署名者の権限ではない

基礎仕様は全componentの成功を要求し、component key materialを別contextで再利用することを禁じる。これは重要な暗号学的境界だ。

それでも証明書path、status freshness、key usage、署名者の権限、内容の意味、宛先、後続処理は別である。正しく署名された承認文書は、承認対象の行為が実行されたことを証明しない。

解析・encoding、algorithm agreement、content digest、component verdict、certificate path/status、identity/authorization、application disposition、delivery、durability、external outcomeを別のreceiptとして保つ必要がある。