3. バージョン2カウンター署名
カウンター署名は通常、主要な署名を確認する2番目の署名として定義されます。カウンター署名の通常の例は、公証人が文書に署名して、あなたが文書に署名したことを証明する署名です。公証人は通常、公証が行われた日時を示すタイムスタンプを含めます。ただし、このようなタイムスタンプはCOSEではまだ定義されていません。将来の文書で定義されたタイムスタンプは、保護されたヘッダーパラメータとして含まれる可能性があります。したがって、COSE_SignatureまたはCOSE_Sign1オブジェクトのいずれかにカウンター署名を適用することは、この従来の定義と一致します。本文書は、カウンター署名のコンテキストを拡張して、定義されているすべてのセキュリティ構造に適用できるようにします。[GROUP-OSCORE] で行われているように、カウンター署名が同じユーザーによって適用される場合でも、最初の操作とは別の操作として扱う必要があります。
COSEは、2つの異なる形式のカウンター署名をサポートしています。完全なカウンター署名は、COSE_Signatureと同じ構造を持つ構造COSE_Countersignatureを使用します。したがって、完全なカウンター署名は、連鎖されたカウンター署名を含む、保護された属性と保護されていない属性を持つことができます。省略されたカウンター署名は、構造COSE_Countersignature0を使用します。この構造には署名値のみが含まれ、他には何も含まれません。これらの構造を相互に変換することはできません。署名の計算には使用されている構造を識別するパラメータが含まれているため、変換された構造は署名の検証に失敗します。
バージョン2カウンター署名は、署名の計算に使用されるアルゴリズムを、[RFC8152] のセクション4.5で指定されている元のバージョンから変更します。新しいバージョンには、サブセットだけでなく、すべての構造に対して生成された暗号化素材が含まれるようになりました。
COSEは、データ構造の指定方法の統一性を目指して設計されました。この結果の1つは、COSEの場合、カウンター署名の概念を単なる署名の署名という考え方を超えて拡張し、新しい署名レイヤーを作成することなく、ほとんどの構造に署名できるようにすることです。カウンター署名を作成するときは、結果として得られるセキュリティプロパティを明確にする必要があります。COSE_SignatureまたはCOSE_Sign1で行われる場合、通常のカウンター署名のセマンティクスが保持されます。つまり、カウンター署名は署名の存在、および(まだ指定されていないタイムスタンプとともに使用される場合)署名が存在する時点についての声明を出します。COSE_MacまたはCOSE_Mac0で行われる場合、ペイロードとMAC値が含まれます。COSE_EncryptまたはCOSE_Encrypt0で行われる場合、暗号化されたデータの存在が証明されます。暗号化されていないデータを証明することと、暗号化されたデータを証明することには違いがあることに注意する必要があります。後者が望ましい場合は、データに署名を適用してから暗号化する必要があります。2つの異なるキーを使用すると復号化に成功し、タグチェックも成功するが、2つの完全に異なる平文が生成されるケースを構築することは常に可能です。この状況は、暗号化されたデータのカウンター署名では検出できません。
3.1. 完全なカウンター署名
COSE_Countersignature構造は、COSE_Signatureと同じ機能セットを可能にします。これは、署名のすべての機能がこの構造で複製されることを意味します。具体的には、キーとアルゴリズムの識別をカウンター署名の属性に配置できるため、カウンター署名者は、カウンター署名されるものの作成者と関係がある必要はありません。これは、カウンター署名自体にカウンター署名できることも意味します。これは、長期アーカイブサービスなどのプロトコルで必要な機能です。カウンター署名の使用方法の詳細については、[RFC4998] で説明されている証拠記録構文に記載されています。
完全なカウンター署名構造は、コンテキストに応じて、タグ付きまたはタグなしのいずれかでエンコードできます。タグ付きのCOSE_Countersignature構造は、CBORタグ19によって識別されます。カウンター署名構造は、署名されたオブジェクトの署名者に使用されるものと同じです。完全なカウンター署名のCDDLフラグメントは次のとおりです。
COSE_Countersignature_Tagged = #6.19(COSE_Countersignature)
COSE_Countersignature = COSE_Signature
カウンター署名のフィールドの詳細は、[RFC9052] のセクション4.1に記載されています。
署名に対するカウンター署名の例は、付録A.1.1にあります。暗号化オブジェクト内のカウンター署名の例は、付録A.3.1にあります。
カウンター署名に使用できるのは、付録付きの署名アルゴリズム([RFC9052] のセクション8.1を参照)のみであることに注意してください。これは、カウンター署名を評価せずに本文を処理できる必要があり、メッセージ回復を伴う署名スキームではこれが不可能なためです。
3.2. 省略されたカウンター署名
省略されたカウンター署名は、メッセージの発信元の識別が必要であるが、カウンター署名をできるだけ小さくしたいという要望がある暗号化グループメッセージングをサポートします。省略されたカウンター署名の場合、署名操作に関連する保護された属性の規定はありません。つまり、省略されたカウンター署名を計算または検証するためのパラメータは、暗号化、署名、またはMAC処理を記述するために使用されるのと同じコンテキストによって提供されます。
省略されたカウンター署名のCDDLフラグメントは次のとおりです。
COSE_Countersignature0 = bstr
署名値を表すバイト文字列は、Countersignature0属性に配置されます。この属性は、保護されていないヘッダーパラメータとしてエンコードされます。
3.3. 署名および検証プロセス
署名を作成するには、明確に定義されたバイト文字列が必要です。Countersign_structureは、正規形式を作成するために使用されます。この署名および検証プロセスは、カウンター署名のターゲット構造 (COSE_Signature, COSE_Sign1, COSE_Sign, COSE_Mac, COSE_Mac0, COSE_Encrypt, または COSE_Encrypt0)、署名者情報 (COSE_Signature)、およびアプリケーションデータ (外部ソース) を取り込みます。Countersign_structureはCBOR配列です。カウンター署名のターゲット構造は、署名を計算する前に、すべての暗号化機能を完了している必要があります。Countersign_structureのフィールドは、順に次のとおりです。
context (コンテキスト): 署名のコンテキストを識別するコンテキストテキスト文字列。コンテキストテキスト文字列は次のいずれかです。
-
other_fields が存在しない場合に COSE_Countersignature 構造を使用するカウンター署名の場合は "CounterSignature"。
-
other_fields が存在しない場合に COSE_Countersignature0 構造を使用するカウンター署名の場合は "CounterSignature0"。
-
other_fields が存在する場合に COSE_Countersignature 構造を使用するカウンター署名の場合は "CounterSignatureV2"。
-
other_fields が存在する場合に COSE_Countersignature0 構造を使用するカウンター署名の場合は "CounterSignature0V2"。
body_protected (ボディ保護): ターゲット構造からのシリアル化された保護属性。bstrタイプでエンコードされます。保護された属性がない場合は、長さゼロのバイト文字列が使用されます。
sign_protected (署名保護): 署名者構造からのシリアル化された保護属性。bstrタイプでエンコードされます。保護された属性がない場合は、長さゼロのバイト文字列が使用されます。このフィールドは、Countersignature0V2属性の場合は省略されます。
external_aad (外部AAD): アプリケーションから外部的に提供される追加の認証データ (AAD)。bstrタイプでエンコードされます。このフィールドが提供されない場合、デフォルトで長さゼロのバイト文字列になります。(このフィールドの構築に関するアプリケーションガイダンスについては、[RFC9052] のセクション4.4を参照してください。)
payload (ペイロード): 署名されるペイロード。bstrタイプでエンコードされます。ペイロードは、転送方法に関係なくここに配置されます。
other_fields(その他のフィールド): ターゲット構造にbstrフィールドが2つしかない場合は省略されます。このフィールドは、2番目以降のすべてのbstrフィールドの配列です。例として、これは署名値を含む COSE_Sign1 構造の1つの要素の配列になります。
上記のテキストを説明するCDDLフラグメントは次のとおりです。
Countersign_structure = [
context : "CounterSignature" / "CounterSignature0" /
"CounterSignatureV2" / "CounterSignature0V2" /,
body_protected : empty_or_serialized_map,
? sign_protected : empty_or_serialized_map,
external_aad : bstr,
payload : bstr,
? other_fields : [+ bstr ]
]
カウンター署名を計算する方法:
-
Countersign_structureを作成し、適切なフィールドに値を入力します。
-
セクション4で説明されているエンコーディングを使用して、Countersign_structureをバイト文字列にエンコードすることにより、値 ToBeSigned を作成します。
-
K(署名に使用するキー)、alg(署名に使用するアルゴリズム)、および ToBeSigned(署名する値)を渡して、署名作成アルゴリズムを呼び出します。
-
結果の署名値を正しい場所に配置します。これは、完全なカウンター署名の場合、COSE_Countersignature構造の「signature」フィールドです(セクション3.1を参照)。これは、省略されたカウンター署名の場合のCountersignature0属性の値です(セクション3.2を参照)。
カウンター署名を検証する手順:
-
Countersign_structureを作成し、適切なフィールドに値を入力します。
-
セクション4で説明されているエンコーディングを使用して、Countersign_structureをバイト文字列にエンコードすることにより、値 ToBeSigned を作成します。
-
K(検証に使用するキー)、alg(署名に使用したアルゴリズム)、ToBeSigned(署名する値)、および sig(検証する署名)を渡して、署名検証アルゴリズムを呼び出します。
署名の検証を実行することに加えて、アプリケーションは適切なチェックを実行して、キーが署名IDと正しくペアになっていること、および署名IDがアクションを実行する前に承認されていることを確認します。