ASP.NET Core でのサブキーの派生と認証された暗号化
キー リング内のほとんどのキーには、何らかの形式のエントロピが含まれていて、"CBC モード暗号化 + HMAC 検証" または "GCM 暗号化 + 検証" というアルゴリズム情報が含められます。 これらの場合、埋め込まれたエントロピを、このキーのマスター キー マテリアル (または KM) として参照し、キー派生関数を実行して、実際の暗号化操作に使用されるキーを派生させます。
注意
キーは抽象的であり、カスタム実装は下記のように動作しない可能性があります。 組み込みのファクトリのいずれかを使用するのではなく、キーで独自の IAuthenticatedEncryptor
の実装を提供する場合は、このセクションで説明するメカニズムが適用されなくなります。
追加の認証されたデータとサブキーの派生
IAuthenticatedEncryptor
インターフェイスは、認証されたすべての暗号化操作のコア インターフェイスとして機能します。 Encrypt
メソッドでは、プレーンテキストと additionalAuthenticatedData (AAD) という 2 つのバッファーを受け取ります。 プレーンテキスト コンテンツのフローにより、IDataProtector.Protect
の呼び出しは変更されませんでしたが、システムによって AAD が生成されています。これは 3 つのコンポーネントで構成されています。
データ保護システムのバージョンを識別する 32 ビットのマジック ヘッダー 09 F0 C9 F0。
128 ビットのキー ID。
この操作を実行している
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_E
と K_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 を生成します。 このプロセスと戻り値は、次のように、グラフィカルに表示されます。
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 ビットの認証タグの生成を行います。
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 ルーチンに転送する必要はありません。
ASP.NET Core