ASP.NET Core の目的文字列

IDataProtectionProvider を使うコンポーネントは、CreateProtector メソッドに固有の "目的" パラメーターを渡す必要があります。 目的 "パラメーター" は、データ保護システムのセキュリティに固有のものであり、ルート暗号キーが同じであっても、暗号コンシューマー間の分離を実現できます。

コンシューマーが目的を指定すると、そのコンシューマーに固有の暗号サブキーを派生させるためにルート暗号キーと共に目的文字列が使われます。 これにより、コンシューマーはアプリケーション内の他のすべての暗号コンシューマーから分離されます。そのペイロードは他のコンポーネントから読み取られず、他のコンポーネントのペイロードを読み取ることもできません。 また、この分離により、コンポーネントに対する全カテゴリの攻撃が実行不可能になります。

Purpose Diagram Example

上の図では、IDataProtector インスタンス A と B は、互いのペイロードを読み取ることができません。自分のペイロードのみを読み取ることができます。

目的文字列はシークレットである必要はありません。 他の適切に動作するコンポーネントが同じ目的文字列を提供することがないという意味で、単に一意である必要があります。

ヒント

データ保護 API を使うコンポーネントの名前空間と型名を使うことは、実際にはこの情報が衝突することはないので、経験則として適切です。

ベアラー トークンの作成を担当する Contoso が作成したコンポーネントには、その目的文字列として Contoso.Security.BearerToken を使うことができます。 また、Contoso.Security.BearerToken.v1 を目的文字列として使うこともできます。 バージョン番号を付加することで、将来のバージョンに Contoso.Security.BearerToken.v2 を目的として使うことができます。また、ペイロードに関する限り、異なるバージョンが互いに完全に分離されます。

CreateProtector の目的パラメーターは文字列配列なので、上の例は代わりに [ "Contoso.Security.BearerToken", "v1" ] と指定することもできます。 これにより、目的の階層を確立することができます。また、データ保護システムを使ったマルチテナント シナリオの可能性が広がります。

警告

コンポーネントは、信頼されていないユーザーの入力を目的チェーンの唯一の入力ソースにしてはいけません。

たとえば、セキュリティで保護されたメッセージを格納するコンポーネント Contoso.Messaging.SecureMessage について考えてみましょう。 セキュリティで保護されたメッセージング コンポーネントから CreateProtector([ username ]) を呼び出した場合、悪意のあるユーザーがユーザー名 "Contoso.Security.BearerToken" のアカウントを作成し、コンポーネントに CreateProtector([ "Contoso.Security.BearerToken" ]) を呼び出させて、その結果、セキュリティで保護されたメッセージング システムによって認証トークンと認識されるペイロードが誤って作成される可能性があります。

メッセージング コンポーネントにより適した目的チェーンは、適切な分離を提供する CreateProtector([ "Contoso.Messaging.SecureMessage", $"User: {username}" ]) です。

IDataProtectionProviderIDataProtector、および目的によって提供される分離とその動作は次のとおりです。

  • 特定の IDataProtectionProvider オブジェクトに対して CreateProtector メソッドを使うと、それを作成した IDataProtectionProvider オブジェクトと、メソッドに渡された目的パラメーターの両方に一意に関連付けられた IDataProtector オブジェクトが作成されます。

  • この目的パラメーターを null にすることはできません (目的が配列として指定されている場合、これは配列の長さをゼロにすることはできず、配列のすべての要素を null 以外にする必要があることを意味します)。空の文字列の目的は技術的には可能ですが、推奨されません。

  • 2 つの目的引数が等価になるのは、それらに (序数比較子を使って) 同じ文字列が同じ順序で含まれている場合に限ります。 1 つの目的引数は、対応する単一要素の目的配列と等価です。

  • 2 つの IDataProtector オブジェクトが等価になるのは、等価の目的パラメーターを持つ等価の IDataProtectionProvider オブジェクトから作成された場合に限ります。

  • 特定の IDataProtector オブジェクトに対して Unprotect(protectedData) を呼び出すと、等価の IDataProtector オブジェクトの protectedData := Protect(unprotectedData) に限り、元の unprotectedData が返されます。

注意

ここでは、あるコンポーネントによって、他のコンポーネントと衝突することがわかっている目的文字列が意図的に選択されるケースは考慮していません。 このようなコンポーネントは基本的に悪意のあるものと見なされます。また、このシステムは、悪意のあるコードが既にワーカー プロセス内で実行されている場合にセキュリティ保証を実現することを目的としていません。