この質問はStackOverflowでも尋ねられましたが、回答はありませんでした。同じ質問があるので、これはより良い交換になると思いました。
AESCryptoServiceProviderを使用して、暗号化側から復号化側にIVを渡すロジックを実装する前に、大きなZipファイルが正常に復号化されたことがわかりました(私が知る限り)。だから、私は期待していなかったように、なぜこれが機能するのかを確認するために小さなテストを書きました。
次の場所にある暗号化...および復号化...関数の使用: http://msdn.Microsoft.com/en-us/library/system.security.cryptography.aescryptoserviceprovider.aspx
そして次のテスト:
static void TestIV()
{
string plainText = "abcdefghijklmnopqrstuvwxyz0123456789asdfqwerfdsareqw";
byte[] key;
string roundTrip = "";
byte[] encrypted = null;
using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider())
{
key = aes.Key;
Console.WriteLine("encryption Key = " + System.Convert.ToBase64String(aes.Key));
Console.WriteLine("encryption IV = " + System.Convert.ToBase64String(aes.IV));
encrypted = EncryptStringToBytes_Aes(plainText, aes.Key, aes.IV);
Console.WriteLine("cipherText = " + System.Convert.ToBase64String(encrypted));
}
using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider())
{
aes.Key = key;
Console.WriteLine("decryption Key = " + System.Convert.ToBase64String(aes.Key));
Console.WriteLine("decryption IV = " + System.Convert.ToBase64String(aes.IV));
roundTrip = DecryptStringFromBytes_Aes(encrypted, aes.Key, aes.IV);
}
Console.WriteLine("Original: " + plainText);
Console.WriteLine("Round Trip: " + roundTrip);
}
これは私の出力でした:
encryption Key = 0Fnvwk0qzbn6sQ+qUbGDyz0MmpBt5e3vkA+7YCUYTzc=
encryption IV = 7E5iw+226INZNzA6y7wWjQ==
cipherText = YVj3ZsSx9nbOKor6ZGqzyGFxdnaR6KM+qSeQj322+2QyhU9Iu1G3d4xPnj7n0X/wpObvjpFBlHf+9rRFWtPodA==
decryption Key = 0Fnvwk0qzbn6sQ+qUbGDyz0MmpBt5e3vkA+7YCUYTzc=
decryption IV = o//BGrMnXatF5po9dUEnug==
Original: abcdefghijklmnopqrstuvwxyz0123456789asdfqwerfdsareqw
Round Trip: .???;??@u??k?^Gqrstuvwxyz0123456789asdfqwerfdsareqw
私のZipファイルの最初のブロックがおそらく壊れていたことが判明しましたが、とにかく正常に解凍され、私が見たファイルは最初のブロックの一部ではなかったはずです。
これを複数回実行すると、次のcipherTextsが表示されます。
cipherText = ZsvLpvVucn0ekx393Fmk5R/UrzzPmzH4dY32EqVlpHJvAKGRERIUY7LLPGHIuyPikHcGKUWL/mt8eP6RI/Qqcw==
cipherText = 0i5tZ1vQvmU5zMimCBIqCWsQzze8PDEOuOxVYekq8T/IGKu4VuHuZWJ6H4aPjRqmSBQYRDbWff6o3Odjl8Qg8A==
cipherText = En/I32AeAASiq10j7ChNPzclWdj8uc6hdBUk/sp8S9G7ly6QBCPAzJFJCR1c9TWjb1gUbzrCEghUgCoRnlJbGA==
そのため、IVは同じテキストに対して別のcipherTextを正常に作成しているようです。では、不正なIVで復号化する場合、最初のブロックのみが破損することが予想されますか?
AesCryptoServiceProviderはデフォルトでCBCモードを使用しますが、CFBを使用してこれと同じ動作を確認し、ECBを使用した場合、プレーンテキストは完全に同じであることに注意してください(最初のブロックは変換されません)。
最初にいくつかのことをクリアしたいと思います。
あなたが見ているのは、意図された正しい行動です。
ECBはチェーンを使用せず、ブロック暗号をブロックごとにプレーンテキストに適用します。したがって、IVとECBは実際には相互に機能しないため、IVとECBについて説明する意味はありません。
CBC暗号化 から始めましょう。とても簡単です。最初の平文ブロックを受け取り、XORブロックし、それにブロック暗号を適用し、結果の暗号文を受け取り、2番目の平文でXORそれを適用し、ブロック暗号、XOR 3番目の平文ブロックの結果、以下同様。
次に、復号化を見てみましょう。最初の暗号文ブロックを受け取り、それにブロック暗号を適用し、次にXOR IVを使用してブロックします、(ここに注意してください)次に移動します次の暗号文ブロックとそれにブロック暗号を適用し、次にXORprevious暗号文ブロックと一緒に)、などオン。
今、見えますか? IVは最初のブロックで作業する場合にのみ使用されます。そのため、復号化に誤ったIVを使用しても、最初のブロックが正しくなく、次のブロックはすべて正常に復号化されます。
同じロジックを CFB復号化に使用できます
簡単にするために、次のように考えることができます。最初のブロックのIVは実際のIVですが、次のブロックは最初のブロックの暗号文であり、3番目のブロックの「IV」は2番目のブロックの暗号文であり、以下同様です。何だと思う?正しいIVなしで復号化しようとすると、暗号文が既にあるため、最初のブロックを除くすべてのブロックの「IV」がすでにあります。
それはC#の問題ではありません- CBCモード に固有です。 CBCでは、encryptionを実行すると、各ブロックは最初に前の暗号化ブロック(最初のブロックのIVを使用)とXORされ、次にXOR =結果はブロック暗号で処理されます。これは、decryptionの場合、ブロック暗号でブロックを処理し、次にXOR以前の暗号化されたブロック。したがって、ブロックnの復号化プロセスは、暗号化されたブロックnとn-1( "blockn-1"はIVであり、 "blockn"が最初のブロック)ウィキペディアのページの概略図はそれを明確にします:
CBCモードは、全ファイルのマングリングやそのようなものを生成するためのものでは決してなかったことを思い出してください。その役割は、どのソースブロックが互いに同一であるかに関する情報の漏洩を回避することだけです。
成功したZip解凍に関しては、これは Zipファイル形式 では、「中央ディレクトリ」(アーカイブ内のファイルを参照する)がファイルの最初ではなく最後にあるためです。 。最初の16バイトをマングルすると、1つのファイル(たまたまファイルの先頭にあるファイル)のヘッダーのみが損傷します。他のファイルは無傷です。