3

CryptoStream.NETクラスの癖のように見えるものに困惑しています。そのDispose()メソッドは、暗号文の末尾を超えて読み取って、パディングすべきではないパディングを探しCryprographicException、結果として a をスローします。

以下の C# プログラムは、数バイトを暗号化し、暗号文配列のサイズを変更して、暗号文の末尾の後に (無意味な) バイトが増えるようにしてから、復号化を試みます。顕著な点は次のとおりです。

  • 暗号文は 8 バイトで、1 つの 3DES 暗号ブロックです。に 6 バイトしか書き込みませんCryptoStream(PaddingMode.PKCS7デフォルト) ため、ブロック内の残りの 2 バイトはパディング値 0x02 で埋められます。
  • その後、暗号文配列は 16 バイト (2 つの 3DES ブロック) にサイズ変更されます。2 番目のブロックは、初期化されていないナンセンスであり、有効な暗号出力ではありません。
  • 復号化するとき、私はCryptoStream;から正確に 6 バイトを読み取りました。意味のない部分に復号化するように要求しているわけではありません。また、平文の最後に到達したタイミングを把握するためにパディングを認識することに依存していません。

問題は、復号化が呼び出されたときにCryptoStream(ブロックDispose()の最後で自動的に)、 「Bad Data」というメッセージが表示されることです。そのスタック トレースは、それが を実行していたことを示しており、実際の暗号化されたデータに対応する 8 バイトだけでなく、16 バイトすべてが から消費されました。usingCryptographicExceptionCryptoStream.FlushFinalBlock()ciphertextStream

配列のサイズを変更する行を削除するciphertextと、プログラムは正しく動作します。また、tripleDes.Padding = PaddingMode.None復号化する前に実行すると、プログラムも正しく動作しますが、基本的にはパディング バイトが平文の一部になるため、実行したくありません。明らかに、問題はパディングに関連しています。私が知る限り、その 2 番目のブロックは復号化されておりPKCS7、最後に有効なスタイルのパディングが見つかることを期待しています。

CryptoStreamから1 つのブロックを復号化する必要があるだけの読み取りを行っているだけであり、そのブロックは正しくパディングされた最終ブロックであり、CryptoStreamそれ以上読み取らずに を閉じると、なぜストリームは別のブロックを読み取る必要があると考えるのでしょうか。さらにパディングを探しますか?の一部としてより多くの入力を消費しようとしているのはなぜDispose()ですか?


using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] plaintext = { 0, 1, 2, 3, 4 };

            using (SymmetricAlgorithm tripleDes = TripleDESCryptoServiceProvider.Create())
            {
                // Encrypt the plaintext
                byte[] ciphertext;
                using (MemoryStream ciphertextStream = new MemoryStream())
                {
                    using (ICryptoTransform encryptor = tripleDes.CreateEncryptor())
                    {
                        using (CryptoStream cryptoStream = new CryptoStream(ciphertextStream, encryptor, CryptoStreamMode.Write))
                        {
                            cryptoStream.WriteByte((byte)plaintext.Length);
                            cryptoStream.Write(plaintext, 0, plaintext.Length);
                            cryptoStream.FlushFinalBlock();
                        }
                    }

                    ciphertext = ciphertextStream.ToArray();
                }

                // *** Add some non-ciphertext garbage to the end ***
                Array.Resize(ref ciphertext, ciphertext.Length + 8);

                // Now decrypt it again
                byte[] decryptedPlaintext;
                using (MemoryStream ciphertextStream = new MemoryStream(ciphertext, false))
                {
                    using (ICryptoTransform decryptor = tripleDes.CreateDecryptor())
                    {
                        using (CryptoStream cryptoStream = new CryptoStream(ciphertextStream, decryptor, CryptoStreamMode.Read))
                        {
                            int length = cryptoStream.ReadByte();

                            decryptedPlaintext = new byte[length];

                            int i = 0;
                            while (i < length)
                            {
                                int bytesRead = cryptoStream.Read(decryptedPlaintext, i, (length - i));
                                if (bytesRead == 0) break;
                                else i += bytesRead;
                            }
                        }  // CryptographicException: "Bad Data"
                    }
                }

                System.Diagnostics.Debug.Assert(decryptedPlaintext.SequenceEqual(plaintext));
            }
        }
    }
}
4

1 に答える 1

3

ストリームの最後に意図的にゴミを追加していて、なぜストリームがゴミを詰まらせているのか疑問に思っています。

暗号化では、攻撃者が卑劣なことを試みていないことを確認するために、すべてを非常に注意深くチェックする必要があります。PKCS7パディングを指定した場合、ストリームは最後にPKCS7パディングをチェックする権利があり、ストリームの最後に正しいパディングが見つからない場合は例外をスローする権利があります。

ストリームには、実際の暗号文がストリームの最後ではなく、ストリームの途中で終了していることを知る方法がありません。どのようにそれが知ることを期待しますか?暗号では、ルールはすべての異常にフラグを立てることであり、ストリームの(見かけの)端での誤ったパディングは、ドキュメントが例外を引き起こすとあなたに告げるものです。

于 2011-09-14T11:39:44.370 に答える