ASP.NET Core でのサブキーの派生と認証された暗号化

キー リング内のほとんどのキーには、何らかの形式のエントロピが含まれていて、"CBC モード暗号化 + HMAC 検証" または "GCM 暗号化 + 検証" というアルゴリズム情報が含められます。 これらの場合、埋め込まれたエントロピを、このキーのマスター キー マテリアル (または KM) として参照し、キー派生関数を実行して、実際の暗号化操作に使用されるキーを派生させます。

注意

キーは抽象的であり、カスタム実装は下記のように動作しない可能性があります。 組み込みのファクトリのいずれかを使用するのではなく、キーで独自の IAuthenticatedEncryptor の実装を提供する場合は、このセクションで説明するメカニズムが適用されなくなります。

追加の認証されたデータとサブキーの派生

IAuthenticatedEncryptor インターフェイスは、認証されたすべての暗号化操作のコア インターフェイスとして機能します。 Encrypt メソッドでは、プレーンテキストと additionalAuthenticatedData (AAD) という 2 つのバッファーを受け取ります。 プレーンテキスト コンテンツのフローにより、IDataProtector.Protect の呼び出しは変更されませんでしたが、システムによって AAD が生成されています。これは 3 つのコンポーネントで構成されています。

  1. データ保護システムのバージョンを識別する 32 ビットのマジック ヘッダー 09 F0 C9 F0。

  2. 128 ビットのキー ID。

  3. この操作を実行している IDataProtector を作成した目的チェーンから形成された可変長文字列。

AAD は 3 つのコンポーネントすべてのタプルで一意であるため、すべての暗号化操作で KM 自体を使用する代わりに、それを使用して KM から新しいキーを派生させることができます。 IAuthenticatedEncryptor.Encrypt を呼び出すたびに、次のキー派生プロセスが実行されます。

( K_E, K_H ) = SP800_108_CTR_HMACSHA512(K_M, AAD, contextHeader || keyModifier)

ここでは、以下のパラメーターを指定して、カウンター モードで NIST SP800-108 KDF を呼び出しています (セクション 5.1 の「NIST SP800-108」を参照)。

  • キー派生キー (KDK) = K_M

  • PRF = HMACSHA512

  • ラベル = additionalAuthenticatedData

  • コンテキスト = contextHeader || keyModifier

コンテキスト ヘッダーは可変長であり、基本的に、K_EK_H を派生させるアルゴリズムの拇印として機能します。 キー修飾子は、Encrypt の各呼び出しでランダムに生成される 128 ビット文字列であり、KDF への他のすべての入力が定数であっても、この特定の認証暗号化操作では KE と KH が一意であることを極めて高い確率で保証することに役立ちます。

CBC モード暗号化 + HMAC 検証操作では、| K_E | は対称ブロック暗号キーの長さで、| K_H | は HMAC ルーチンのダイジェスト サイズです。 GCM 暗号化 + 検証操作では | K_H | = 0 です。

CBC モード暗号化 + HMAC 検証

上記のメカニズムによって K_E が生成されたら、ランダムな初期化ベクターを生成し、対称ブロック暗号アルゴリズムを実行してプレーンテキストを暗号化します。 次に、キー K_H で初期化された HMAC ルーチンを通じて初期化ベクターと暗号化テキストを実行し、MAC を生成します。 このプロセスと戻り値は、次のように、グラフィカルに表示されます。

CBC-mode process and return

output:= keyModifier || iv || E_cbc (K_E,iv,data) || HMAC(K_H, iv || E_cbc (K_E,iv,data))

Note

IDataProtector.Protect 実装では、呼び出し元に返す前の出力にマジック ヘッダーとキー ID が付加されます。 マジック ヘッダーとキー ID は、暗黙的に AAD の一部となっているため、また、キー修飾子は入力として KDF に渡されるため、最終的に返されるペイロードのすべてのバイトが MAC によって認証されることになります。

Galois/Counter Mode 暗号化 + 検証

上記のメカニズムによって K_E が生成されたら、ランダムな 96 ビットの nonce を生成し、対称ブロック暗号アルゴリズムを実行して、プレーンテキストの暗号化と 128 ビットの認証タグの生成を行います。

GCM-mode process and return

output := keyModifier || nonce || E_gcm (K_E,nonce,data) || authTag

Note

GCM ではネイティブに AAD の概念がサポートされていますが、元の KDF にのみ AAD をフィードし、GCM には AAD パラメーターとして空の文字列を渡すことをオプトインします。 これには 2 つの理由があります。 まず、方式の指定をサポートするため、暗号化キーとして直接 K_M を使用することは避ける必要があります。 さらに、GCM では、入力に関して非常に厳しい一意性の要件が適用されます。 GCM 暗号化ルーチンの呼び出しが、同じ (キー、nonce) ペアを持つ 2 つ以上の個別の入力データ セットに対して行われる確率が 2^32 を超えてはなりません。 K_E を固定すると、2^-32 の制限に抵触しないで 2^32 を超える暗号化操作を実行することができません。 これは非常に多くの操作のように思えるかも知れませんが、トラフィックが多い Web サーバーでは、これらのキーの通常の有効期間内に、わずか数日で 40 億個の要求が通過する可能性があります。 2^-32 の確率制限を守り続けるために、Microsoft では 128 ビットのキー修飾子と 96 ビットの nonce を引き続き使用しています。これにより、どの K_M についても、使用可能な操作の数が大幅に増加しています。 設計の簡素化のために、CBC 操作と GCM 操作の間で KDF コード パスが共有されています。KDF では AAD が既に考慮に入れられているため、それを GCM ルーチンに転送する必要はありません。