1

独自の暗号化アルゴリズムを実装しようとするのは悪い考えであることはわかっています。そうではないと思う理由の一つは次のとおりです。

たとえばplainText = new byte[]{2,5,1,6,7}、ボブに送りたいとしましょう。

AES 暗号化または別のよく知られたアルゴリズムを使用すると、次のようになります。

cipherText = Aes.Encrypt(plainText, key, iv); // now I have some cipher text that is not readable to anyone if they do not have the key and iv vector.

誰かがそのメッセージを解読したい場合は、次のようなことをしなければなりません:

newPlainText = Aes.Decrypt(cipherText, key, iv);

ここで私の質問は、正しいキーを入力したかどうかを AES がどのように認識するかです。ブルート フォース攻撃が発生しないアルゴリズムを使用する方が安全だと思います。言い換えれば、ハッカーがあなたが AES を使用したことを知っている場合、method Aes.Decrypt例外がなくなるまで多くのパスワードを試行し続けることができます。次のアルゴリズムを考えてみましょう。

{2,5,1,6,7}同じバイト配列をボブに送りたいとしましょう。私の暗号化アルゴリズムは次のようになります。

パスワードは = "securePassword";

プレーン テキストの各バイトを反復処理し、パスワードの各文字の ASCII 値に対して Xor 演算子を実行します。たとえば、最初のバイトは2 Xor (ASCII value of 's')次の値になり、次の値は5 Xor (ASCII value of 'e')最後になり{2 Xor 's', 5 Xor 'e', 1 Xor 'c', 6 Xor 'u', 7 Xor 'r'} ます。

このアルゴリズムでは、書き込みキーを持っているかどうかを知ることができないため、解読できないと思います。よく知られているアルゴリズムを使用すると、パスワードがあまり長くない場合、ブルート フォース攻撃が行われます。

*私の質問は、AES などのよく知られた対称暗号化アルゴリズムは、入力したキーが正しいかどうかをどのように認識するのでしょうか? 正しいキーを提供するかどうかわからないアルゴリズムを使用することは、より安全ではありませんか? *

4

3 に答える 3

9

暗号化アルゴリズムは、入力キーが正しいかどうかわかりません! このアルゴリズムは、任意のキーを使用した復号化に問題なく機能します。間違ったキーを使用すると、ゴミになります。暗号化を使用するアプリケーションは、暗号化が完了するとこれを検出できる可能性があります。これは、復号化されたメッセージに無効なパディングが含まれているか、他の方法で不正な形式になっている可能性があるためですが、AES 自体が「例外をスロー」することはありません。

あなたが説明しているアルゴリズムはワンタイムパッドです。その致命的な欠陥は、キーが少なくともメッセージと同じ長さでなければならず、決して再利用できないことです。同じキーが 2 つのメッセージで使用されている場合、2 つのメッセージA ⊕ KB ⊕ KXOR して生成することができますA ⊕ K ⊕ B ⊕ K = A ⊕ B。はメッセージから削除されており、これからメッセージが何であるかを推測できる可能性があります。

于 2013-07-03T17:00:12.290 に答える
3

まず、AES アルゴリズムはまさにそれです。それは単なる数学的な暗号です。正しいキーを使用しているかどうかを知ることはできません。この機能を提供する違いは、通常、暗号プリミティブをキー、IV、および平文/暗号文の 1 つ以上の「ブロック」と組み合わせて結果を生成する事前定義された方法です。これは暗号モードと呼ばれます。

最も一般的なモードの 1 つは、CBC、または暗号ブロック連鎖です。このモードでは、以前に暗号化された暗号文のブロックは、暗号を実行する前に平文の次のブロックと XOR されます (最初のブロックは IV と XOR されます)。このモードでは、平文メッセージの長さがブロック サイズの正確な倍数である必要があり、これはパディングで実現されます。

パディングは、暗号化の「連鎖」モードと組み合わせて、ある種のチェックサムを提供します。最後のブロックは、有効にパディングされたブロックでなければなりません (たまたまブロック サイズの正確な倍数の長さであるメッセージの場合、最後のブロックはまだパディングされています。すべてゼロです)。そうでない場合は、間違った鍵が使用されたか、メッセージが転送中に破損したかのいずれかです (暗号化の連鎖効果は、暗号文に導入されたエラーが平文のそのブロックとその後のすべてのブロックで見られることを意味します)。これは、間違ったキーを使用した場合の例外の原因である可能性が最も高いです。ただし、CBC は選択暗号文攻撃に対して脆弱であることが証明されており、攻撃者が特別に変更された暗号文のブロックを復号化アルゴリズムにフィードして結果を表示することが許可されている場合、キーを知らなくても平文を復元できます。

他のモードには組み込みのメッセージ認証があり、このタイプの攻撃を防ぎます。たとえば、CBC-MAC を使用したカウンターである CCM があります。最初に、メッセージは CBC 暗号化によって実行されることによってハッシュされますが、データの最後のブロックのみが保持されます (カスケード動作を覚えていますか? キー付きハッシュを計算する優れた方法であることがわかります)。次に、メッセージとハッシュ ダイジェストは、カウンター モードを使用して暗号化されます (IV は、連続した値で XOR され、平文の各ブロックで XOR されるナンスが生成されます)。間違ったキーが使用された場合、またはメッセージが転送中に変更された場合、結果のメッセージを再ハッシュすると、ハッシュ ダイジェストと一致しなくなります。正しいキーを持っていることを確認しない限り、どちらが該当するかを判断することは実際には不可能です。

于 2013-07-03T17:04:34.343 に答える
1

しかし、あなたの質問に答えるために、.NET AES プロバイダー、あなたが間違ったキーを使用しているかどうかを知っています。

バイトを暗号化しようとしました:

2,5,1,6,7

次のようなコードを使用します。

var plainText = new byte[] {2,5,1,6,7};
byte[] cipherText;

var key = new Byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
var iv = new Byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

//encrypt plaintext using one key
using (var aes = Aes.Create())
{
   var crypt = aes.CreateEncryptor(key, iv);
   cipherText = crypt.TransformFinalBlock(plainText, 0, plainText.Length);
}

実際には、AES は 16 バイト ブロックでのみ動作します。入力データを実際に暗号化できる長さに変換するために、入力バイトは最初にパディングされます。Aes.NET でクラスを構築する場合:

using (var aes = Aes.Create())
{
}

デフォルトのパディング モードAesは PKCS#7 paddingです。これにより、暗号化された Aes により、plainTextが次のようにパディングされます。

2, 5, 1, 6, 7, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11

そして、これらのbye は次のように暗号化されます。

210, 49, 160, 164, 2, 53, 121, 254, 79, 249, 91, 111, 104, 173, 50, 207

これらの暗号バイトを復号化すると、次のようになります。

byte[] recoveredPlainText;
using (var aes = Aes.Create())
{
   var key = new Byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
   var iv = new Byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
   var crypt = aes.CreateDecryptor(key, iv);
   recoveredPlainText = crypt.TransformFinalBlock(cipherText, 0, cipherText.Length);
}

Aes は、適切な PKCS#7 パディングが存在することを確認します。

2、5、1、6、7、11、11、11、11、11、11、11、11、11、11、11 _

無効なキー (例: {1,0,0, ..., 0}) で復号化しようとすると、有効な PKCS#7 パディングを含まないプレーンテキストになります。

154,203,183,159,52,162,186,41,127,162,152,75,114,109,107,74

そのため、Aes デクリプターは例外をスローします。

無効なキーを使用してバイトを復号化することもできます。次のように設定して、Aes にパディングを検索しないように指示するだけですPadding = PaddingMode.None

byte[] recoveredPlainText;
using (var aes = Aes.Create())
{
   aes.Padding = PaddingMode.None;
   var key = new Byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
   var iv = new Byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
   var crypt = aes.CreateDecryptor(key, iv);
   recoveredPlainText = crypt.TransformFinalBlock(cipherText, 0, cipherText.Length);
}

tl;dr : Paddingを使用したため、それはわかっています。

: すべてのコードはパブリック ドメインにリリースされます。帰属は必要ありません。

于 2013-07-03T20:29:01.453 に答える