35

Web アプリケーションによって書き込まれる Cookie を暗号化し、Cookie のサイズを最小限に抑えたいと考えているため、AES/CTR/NoPadding を選択しました。

十分にランダムで、アプリをステートレスに保つ IV として使用することをお勧めします。ランダムな IV を生成してメッセージに追加できることはわかっていますが、そうすると Cookie のサイズが大きくなります。

さらに、128 ビット AES の IV の推奨サイズは?

みんなは他にどうやってこれをやっているの?「実証済みの」方法はありますか? 車輪の再発明はしたくありません。

4

6 に答える 6

53

CTR セキュリティでは、同じキーを持つ 2 つのメッセージ暗号化に IV を再利用しないことが要求されます。実際にはさらに厳密です。CTR モードは、カウンターの連続する値を暗号化することによって機能し (IV はそのカウンターの初期値にすぎません)、同じカウンター値が 2 回使用されない場合にのみ、適切なセキュリティが実現されます。これは、IV で値を暗号化すると、別の暗号化で再利用してはならない連続する IV 値のシーケンスを実際に「消費」することを意味します。

これを行う簡単な方法は、暗号的に安全な乱数ジェネレーターを使用し、メッセージごとに新しい 16 バイトのランダム IV を作成することです。「暗号的に安全」に下線を引いたのは、それが重要だからです。基本的な乱数ジェネレーターでは不十分です。Java では、 を使用しますjava.util.SecureRandom。Win32 では、 を呼び出しますCryptGenRandom()。ランダムな選択では、可能な 128 ビット IV のスペースが十分に大きいため、衝突が発生する可能性は非常に低くなります。実際、これが AES が 128 ビット ブロックを使用する理由です (つまり、128 ビット IV を意味します)。

メッセージを復号化するエンティティは IV を知っている必要があるため、暗号化されたメッセージと一緒に保存する必要があります。それは余分な 16 バイトです。Cookie の場合、16 バイトはそれほど大きくありませんが、このオーバーヘッドを回避したいことは理解しています。Cookie の有効な最大長は Web ブラウザによって異なりますが、「どこでも」4000 文字が機能するようです。16 バイトの IV は、文字でエンコードされた場合 (たとえば Base64 を使用)、約 22 文字を使用します。つまり、最大 Cookie サイズの 1% よりはるかに少なくなります。

これで、ファンキーになり、策略を使って IV の長さを短くすることができます。

  • ハッシュ関数を使用して IV を生成します。サーバー側では、0 から始まり、新しい IV が必要になるたびにインクリメントされるカウンターを使用します。IV を取得するには、SHA-256 などの適切なハッシュ関数を使用してカウンターをハッシュし、ハッシュ値の最初の 16 バイトを保持します。ハッシュ関数の「ランダム化プロパティ」は、CTR 要件に関して IV を十分にランダムにするのに十分です。これには、暗号的に安全なハッシュ関数が必要であるため、SHA-256 (MD5 を避ける) が必要です。次に、カウンター値を Cookie に保存するだけで、カウンターは 16 バイトよりも短くなります (たとえば、顧客が 40 億人以下の場合、カウンターは 4 バイトに収まります)。ただし、隠れたコストがあります。サーバー (サーバーがシステムで暗号化を実行していると思います) は、カウンター値を再利用しないようにする必要があるため、"

  • 外部の一意の値を使用します。おそらく、Cookie は、各暗号化に一意の値を生成するのに十分なデータを提供するコンテキストの一部である可能性があります。たとえば、リクエストに「ユーザー ID」も (平文で) 含まれている場合、そのユーザー ID を IV ソースとして使用できます。セットアップは上記のものと似ています。すべてのデータを取得し、SHA-256 に詰め込みます。SHA-256 出力の最初の 16 バイトが必要な IV です。これは、特定の暗号化されたメッセージに対してそのデータが変更されず、それが本当に一意である場合にのみ機能します。これはめったに発生しません: たとえば、「ユーザー ID」は、同じユーザーの新しいメッセージを再暗号化する必要がまったくなく、ユーザー ID が再利用される可能性がない場合にのみ有効です (たとえば、古いユーザーが終了すると、新しいユーザーが来て、現在無料のユーザー ID を選択します)。

暗号的に安全な PRNG で生成されたランダムな 16 バイト IV を使用することは、依然として「安全な」方法であり、私が推奨する方法です。Cookie のスペースが不足している場合、これは 4 kB の制限に近づいていることを意味し、その時点で圧縮を使用することをお勧めします (暗号化のデータに対して。暗号化後、圧縮が機能する可能性はほとんどありません)。zlibを使用します (Java では、 から zlib にアクセスできますjava.util.zip)。

警告:上記のすべてにおいて、Cookie 暗号化が達成しようとしているセキュリティ特性を提供するのに役立つかどうかについては何も言っていません。通常、暗号化が必要な場合、実際には暗号化と整合性の両方が必要になるため、暗号化と整合性の組み合わせモードを使用する必要があります。GCMおよびCCMを検索します。さらに、Cookie 暗号化は、サーバー側にユーザ​​ー固有のデータを少し保存するコストを回避するという 1 つの目的に適しています。有効なユーザーを認証するなど、別の目的で Cookie を暗号化したい場合、それは間違っています。暗号化はそのための適切なツールではありません。

于 2011-01-07T14:23:02.383 に答える
4

質問に対する直接的な回答はありませんが、追加することがいくつかあります。

まず第一に、Cookie を暗号化することは私には意味がありません。データの機密性が必要な場合でも、データを Cookie に保存しないでください。整合性が必要な場合 (つまり、Cookie の内容を改ざんできない場合)、キー付きハッシュ (HMAC など) を使用する必要があります。

もう 1 つの注意点は、便宜上、すべて 0 の IV を使用しないことです。

IV のサイズは、ブロックのサイズと同じです。AES-128 の場合、ブロックサイズは 128、キーサイズは 128 であるため、IV は 128 ビットです。

これを行う最善の方法は、ランダムな AES キーを作成し、それを IV として使用することです。このランダムな IV は、同じキーを使用した後続の暗号化で再利用されない限り、公開される可能性があります。

編集

使用するモードの詳細については、この wiki ページを参照してください。ただし、使用する必要があることが確実でない限り、ECB を使用しないでください。その場合でも、専門家に確認してください。私が知る限り、CBC は (PCBC と共に) 最も安全です。

http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation

于 2011-01-05T20:12:38.400 に答える
2

IV をランダムにしない場合 (つまり、いくつかの繰り返しグループを使用する場合)、Cookie が常に同じクリア テキストで始まると、キーを見つけやすくなります。

AES-128 の IV サイズは 128 ビットです。IIRC、IV は暗号ブロックと同じサイズです。128 ビットは 16 バイトです。ASCII 16 進文字列として保存する場合は 32 バイト。それは本当に多すぎますか?このご時世で32バイトは全然少ない…

于 2011-01-05T20:09:31.067 に答える
0

Cookie に大きな乱数を含めます。おそらく、64 ビットまたは 128 ビットの数値で十分です。重複を取得するのが非常に困難になるように、十分な大きさが必要です。この数値には十分なエントロピーを入れてください。gettime() だけを使用しないでください。CRNG にアクセスできる場合は、ここで使用します。

アプリケーションで 256 ビットのマスター キーを保存します。SHA256 を使用してキー情報を取得します。繰り返しますが、これには CRNG を使用してください。

$keyblob = sha256( concat("aeskeyid", $masterkey , $randomnumberwithcookie ) )
$aeskey = $keyblob[0..15]
$aesiv = $keyblob[16..31]

HMAC の鍵を導出することもできます。

$mackeyblob = sha256( concat("hmackeyid", $masterkey , $randomnumberwithcookie ) )

または、SHA512 を使用して、上記の 2 つのハッシュ操作を 1 つに結合することもできます。

$keyblob = sha512( concat("randomkeyid", $masterkey , $randomnumberwithcookie ) )
$aeskey = $keyblob[0..15]
$aesiv = $keyblob[16..31]
$hmackey = $keyblob[32..63] 
于 2011-01-06T01:23:04.273 に答える