メインコンテンツまでスキップ

4. 署名オブジェクト

  1. 署名オブジェクト

COSEは2つの異なる署名構造をサポートしています。COSE_Signは、同じコンテンツに対して1つまたは複数の署名を適用することを可能にします。COSE_Sign1は単一の署名者に制限されています。これらの構造は互いに変換することはできません。署名計算には使用されている構造を識別するパラメータが含まれるため、変換された構造は署名検証に失敗します。

4.1. 1人以上の署名者による署名

COSE_Sign構造は、メッセージペイロードに対して1つまたは複数の署名を適用することを可能にします。コンテンツに関連するヘッダーパラメータと署名に関連するヘッダーパラメータは、署名自体と共に運ばれます。これらのヘッダーパラメータは、署名によって認証されるか、単に存在するだけの場合があります。コンテンツに関するヘッダーパラメータの例としては、コンテンツタイプヘッダーパラメータがあります。署名に関するヘッダーパラメータの例としては、署名の作成に使用されたアルゴリズムと鍵があります。

[RFC5652]は次のように示しています:

| 複数の署名が存在する場合、特定の署名者に関連付けられた1つの署名の正常な検証は、通常、その署名者による正常な署名として扱われます。ただし、他のルールが必要なアプリケーション環境もいくつかあります。署名者ごとに1つの有効な署名以外のルールを採用するアプリケーションは、それらのルールを指定する必要があります。また、署名者識別子の単純な照合だけでは署名が同じ署名者によって生成されたかどうかを判断するのに十分でない場合、アプリケーション仕様は、どの署名が同じ署名者によって生成されたかを判断する方法を記述する必要があります。異なる受信者コミュニティのサポートは、署名者が複数の署名を含めることを選択する主な理由です。

例えば、COSE_Sign構造には、Edwards-curve Digital Signature Algorithm (EdDSA) [RFC8032]とElliptic Curve Digital Signature Algorithm (ECDSA) [DSS]で生成された署名が含まれる場合があります。これにより、受信者は一方のアルゴリズムまたは他方に関連付けられた署名を検証できます。複数の署名評価に関する詳細情報は、[RFC5752]に記載されています。

署名構造は、使用されるコンテキストに応じて、タグ付きまたはタグなしとしてエンコードできます。タグ付きCOSE_Sign構造は、CBORタグ98によって識別されます。これを表すCDDLフラグメントは次のとおりです:

COSE_Sign_Tagged = #6.98(COSE_Sign)

COSE署名付きメッセージは2つの部分で定義されます。本文とメッセージに関する情報を運ぶCBORオブジェクトは、COSE_Sign構造と呼ばれます。署名と署名に関する情報を運ぶCBORオブジェクトは、COSE_Signature構造と呼ばれます。COSE署名付きメッセージの例は、付録C.1に記載されています。

COSE_Sign構造はCBOR配列です。配列のフィールドは順に次のとおりです:

protected(保護された): これは第3節で説明されている通りです。

unprotected(保護されていない): これは第3節で説明されている通りです。

payload(ペイロード): このフィールドには、署名されるシリアル化されたコンテンツが含まれます。ペイロードがメッセージに存在しない場合、アプリケーションはペイロードを別途提供する必要があります。ペイロードは、変更なしで転送されることを保証するためにbstrでラップされます。ペイロードが別途転送される場合(「分離コンテンツ」)、この場所にnil CBORオブジェクトが配置され、変更なしで転送されることを保証するのはアプリケーションの責任です。

  注:メッセージ回復アルゴリズムを使用した署名が使用される場合(第8.1節)、回復できる最大バイト数は元のペイロードの長さです。エンコードされたペイロードのサイズは、回復されるバイト数だけ減少します。元のペイロードのすべてのバイトが消費された場合、送信されるペイロードは不在ではなく、長さゼロのバイト文字列としてエンコードされます。

signatures(署名): このフィールドは署名の配列です。各署名はCOSE_Signature構造として表されます。

上記のCOSE_Signテキストを表すCDDLフラグメントは次のとおりです。

COSE_Sign = [ Headers, payload : bstr / nil, signatures : [+ COSE_Signature] ]

COSE_Signature構造はCBOR配列です。配列のフィールドは順に次のとおりです:

protected(保護された): これは第3節で説明されている通りです。

unprotected(保護されていない): これは第3節で説明されている通りです。

signature(署名): このフィールドには、計算された署名値が含まれます。フィールドのタイプはbstrです。署名値が8ビットの倍数でない場合、アルゴリズムはパディングを指定しなければなりません(MUST)。

上記のCOSE_Signatureテキストを表すCDDLフラグメントは次のとおりです。

COSE_Signature = [ Headers, signature : bstr ]

4.2. 1人の署名者による署名

COSE_Sign1署名構造は、メッセージに1つの署名のみが配置される場合に使用されます。コンテンツと署名を扱うヘッダーパラメータは、COSE_Signのように分離されるのではなく、同じバケットのペアに配置されます。

この構造は、使用されるコンテキストに応じて、タグ付きまたはタグなしとしてエンコードできます。タグ付きCOSE_Sign1構造は、CBORタグ18によって識別されます。これを表すCDDLフラグメントは次のとおりです:

COSE_Sign1_Tagged = #6.18(COSE_Sign1)

本文、署名、および本文と署名に関する情報を運ぶCBORオブジェクトは、COSE_Sign1構造と呼ばれます。COSE_Sign1メッセージの例は、付録C.2に記載されています。

COSE_Sign1構造はCBOR配列です。配列のフィールドは順に次のとおりです:

protected(保護された): これは第3節で説明されている通りです。

unprotected(保護されていない): これは第3節で説明されている通りです。

payload(ペイロード): これは第4.1節で説明されている通りです。

signature(署名): このフィールドには、計算された署名値が含まれます。フィールドのタイプはbstrです。

上記のCOSE_Sign1テキストを表すCDDLフラグメントは次のとおりです。

COSE_Sign1 = [ Headers, payload : bstr / nil, signature : bstr ]

4.3. 外部から提供されるデータ

COSEで提供される機能の1つは、アプリケーションが、認証される必要があるがCOSEオブジェクトの一部として運ばれない追加データを提供する能力です。これをサポートする主な理由は、CoAPメッセージ構造[RFC7252]を見ることで理解できます。ここでは、ペイロードの前にオプションを運ぶ機能が存在します。この場所に配置できるデータの例としては、CoAPコードやCoAPオプションがあります。データがCoAPメッセージのヘッダーにある場合、プロキシがプロキシ操作を実行するのに役立ちます。例えば、Acceptオプションは、プロキシが適切な値がプロキシのキャッシュにあるかどうかを判断するために使用できます。送信者は、追加データ機能を使用して、プロキシまたは攻撃者によるAccept値セットへの変更を検出できるようにすることができます。外部から提供されるデータにフィールドを含めることで、その後の変更はメッセージのサーバー処理を失敗させる原因となります。

このドキュメントでは、外部から提供される認証データバイト配列を使用するプロセスについて説明します。バイト配列を構築する方法はアプリケーションの機能です。この機能を使用するアプリケーションは、外部から提供される認証データがどのように構築されるかを定義する必要があります。そのような構築では、以下の問題を考慮する必要があります:

  • 複数の項目が含まれる場合、アプリケーションは、異なる入力で同じバイト文字列が生成されないようにする必要があります。問題のあるシナリオが発生する例としては、テキスト文字列「AB」と「CDE」を連結する場合、またはテキスト文字列「ABC」と「DE」を連結する場合などがあります。これは通常、フィールドを固定幅にするか、フィールドの長さを出力の一部としてエンコードすることで対処されます。CoAP[RFC7252]のオプションを例にとると、これらのフィールドはTLV構造を使用しているため、問題なく連結できます。

  • 複数の項目が含まれる場合、項目の順序を定義する必要があります。CoAPのオプションを例にとると、アプリケーションはフィールドをオプション番号順に並べるように指定できます。

  • アプリケーションは、バイト文字列が両側で同じになるようにする必要があります。CoAPのオプションを使用すると、同じ相対番号付けが維持されている場合に問題が発生する可能性があります。中間ノードがオプションを挿入または削除し、相対番号付けの方法を変更する可能性があります。アプリケーションは、相対番号が外部データ内のオプションのみに関連するように再エンコードされる必要があることを指定する必要があります。

4.4. 署名と検証プロセス

署名を作成するには、明確に定義されたバイト文字列が必要です。Sig_structureは、正規形式を作成するために使用されます。この署名および検証プロセスは、本文情報(COSE_SignまたはCOSE_Sign1)、署名者情報(COSE_Signature)、およびアプリケーションデータ(外部ソース)を取り込みます。Sig_structureはCBOR配列です。Sig_structureのフィールドは順に次のとおりです:

  1. 署名のコンテキストを識別するコンテキストテキスト文字列。コンテキストテキスト文字列は次のとおりです:

    "Signature":COSE_Signature構造を使用する署名の場合。

    "Signature1":COSE_Sign1構造を使用する署名の場合。

  2. 本文構造からの保護された属性。bstrタイプでエンコードされます。保護された属性がない場合は、長さゼロのバイト文字列が使用されます。

  3. 署名者構造からの保護された属性。bstrタイプでエンコードされます。保護された属性がない場合は、長さゼロのバイト文字列が使用されます。このフィールドは、COSE_Sign1署名構造では省略されます。

  4. アプリケーションからの外部提供データ。bstrタイプでエンコードされます。このフィールドが提供されない場合、デフォルトは長さゼロのバイト文字列になります。(このフィールドの構築に関するアプリケーションガイダンスについては、第4.3節を参照してください。)

  5. 署名されるペイロード。bstrタイプでエンコードされます。転送方法に関係なく、ここでは完全なペイロードが使用されます。

上記のテキストを記述するCDDLフラグメントは次のとおりです:

Sig_structure = [ context : "Signature" / "Signature1", body_protected : empty_or_serialized_map, ? sign_protected : empty_or_serialized_map, external_aad : bstr, payload : bstr ]

署名の計算方法:

  1. Sig_structureを作成し、適切なフィールドを入力します。

  2. 第9節で説明されているエンコーディングを使用してSig_structureをバイト文字列にエンコードし、値ToBeSignedを作成します。

  3. 署名作成アルゴリズムを呼び出し、K(署名に使用する鍵)、alg(署名に使用するアルゴリズム)、およびToBeSigned(署名する値)を渡します。

  4. 結果の署名値を正しい場所に配置します。これは、COSE_SignatureまたはCOSE_Sign1構造の「signature」フィールドです。

署名を検証する手順は次のとおりです:

  1. Sig_structureを作成し、適切なフィールドを入力します。

  2. 第9節で説明されているエンコーディングを使用してSig_structureをバイト文字列にエンコードし、値ToBeSignedを作成します。

  3. 署名検証アルゴリズムを呼び出し、K(検証に使用する鍵)、alg(署名に使用されたアルゴリズム)、ToBeSigned(署名する値)、およびsig(検証する署名)を渡します。

署名検証の実行に加えて、アプリケーションは、アクションを実行する前に、鍵が署名IDと正しくペアリングされていること、および署名IDが承認されていることを確認するための適切なチェックを実行します。