«Длина данных для расшифровки недопустима.» исключение во время расшифровки Rijndael - PullRequest
4 голосов
/ 10 мая 2009

Я получаю "Длина данных для расшифровки неверна." исключение, когда я пытаюсь расшифровать поток памяти. Я новичок, не могу понять, что не так. что не так?

public bool EncryptStream()
    {

        string password = @"myKey123"; // Your Key Here
        UnicodeEncoding UE = new UnicodeEncoding();
        byte[] key = UE.GetBytes(password);

        s_EncryptedStream = new MemoryStream();
        int NoOfBytes;
        byte[] b_Buffer = new byte[8192];

        s_MemoryStream.Seek(0, SeekOrigin.Begin);

        RijndaelManaged RMCrypto = new RijndaelManaged();

        s_CrytpoStream = new CryptoStream(s_EncryptedStream,
            RMCrypto.CreateEncryptor(key, key),
            CryptoStreamMode.Write);

        while (s_MemoryStream.Length < s_MemoryStream.Position)
        {
            NoOfBytes = s_MemoryStream.Read(b_Buffer, 0, 8192);
            s_CrytpoStream.Write(b_Buffer, 0, NoOfBytes);
        }

        s_MemoryStream.Seek(0, SeekOrigin.Begin);

        while (s_EncryptedStream.Position < s_EncryptedStream.Length)
        {
            NoOfBytes = s_EncryptedStream.Read(b_Buffer, 0, 8192);
            s_MemoryStream.Write(b_Buffer, 0, NoOfBytes);

        }
        s_CrytpoStream.Flush();
        s_CrytpoStream.Close();

        return true;

    }


    public bool DecryptStream()
    {


        string password = @"myKey123"; // Your Key Here

        UnicodeEncoding UE = new UnicodeEncoding();
        byte[] key = UE.GetBytes(password);

        int NoOfBytes;
        byte[] b_Buffer = new byte[8192];

        s_DecryptedStream = new MemoryStream();


        RijndaelManaged RMCrypto = new RijndaelManaged();

        s_CrytpoStream = new CryptoStream(s_MemoryStream,
            RMCrypto.CreateDecryptor(key, key),
            CryptoStreamMode.Read);

        s_MemoryStream.Seek(0, SeekOrigin.Begin);

        while (s_MemoryStream.Length > s_MemoryStream.Position)
        {
            NoOfBytes = s_CrytpoStream.Read(b_Buffer, 0, 8192);
            s_DecryptedStream.Write(b_Buffer, 0, NoOfBytes);
        }

        s_DecryptedStream.Seek(0, SeekOrigin.Begin);
        s_MemoryStream.Seek(0, SeekOrigin.Begin);

        while (s_DecryptedStream.Position < s_DecryptedStream.Length)
        {
            NoOfBytes = s_DecryptedStream.Read(b_Buffer, 0, 8192);
            s_MemoryStream.Write(b_Buffer, 0, NoOfBytes);

        }

        s_CrytpoStream.Flush();
        s_CrytpoStream.Close();

        return true;

    }

Ответы [ 3 ]

6 голосов
/ 10 мая 2009

Для начала это условие цикла никогда не подходит:

while (s_MemoryStream.Length < s_MemoryStream.Position)

Как позиция может быть за пределами длины?

Вместо того, чтобы использовать длину потока, обычным шаблоном для копирования потока является повторное считывание, пока возвращаемое значение не станет положительным. В любом случае, поскольку вы делаете это дважды в этом коде, вы можете также инкапсулировать его:

public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[8192];
    int read;
    while ( (read = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        output.Write(buffer, 0, read);
    }
}

Также лучше использовать using операторы для очистки строк. Кроме того, свойство Encoding.Unicode означает, что вам не нужно создавать новый UnicodeEncoding самостоятельно. Кроме того, я обычно нахожу, что установка свойства Position более читаема, чем использование Seek Наконец, нет смысла в методе, возвращающем значение, если оно всегда будет true. Итак, ваш код станет:

public void EncryptStream()
{
    string password = @"myKey123"; // Your Key Here
    byte[] key = Encoding.Unicode.GetBytes(password);

    s_EncryptedStream = new MemoryStream();
    s_MemoryStream.Position = 0;

    RijndaelManaged RMCrypto = new RijndaelManaged();

    using (Stream crytpoStream = new CryptoStream(s_EncryptedStream,
        RMCrypto.CreateEncryptor(key, key),
        CryptoStreamMode.Write))
    {
        CopyStream(s_MemoryStream, cryptoStream);
    }

    s_MemoryStream.Position = 0;
    s_EncryptedStream.Position = 0;
    CopyStream(s_EncryptedStream, s_MemoryStream);
}

public void DecryptStream()
{
    string password = @"myKey123"; // Your Key Here
    byte[] key = Encoding.Unicode.GetBytes(password);

    s_DecryptedStream = new MemoryStream();
    s_MemoryStream.Position = 0;

    RijndaelManaged RMCrypto = new RijndaelManaged();

    using (Stream crytpoStream = new CryptoStream(s_MemoryStream,
        RMCrypto.CreateDecryptor(key, key),
        CryptoStreamMode.Read))
    {
        CopyStream(cryptoStream, s_DecryptedStream);
    }

    s_DecryptedStream.Position = 0;
    s_MemoryStream.Position = 0;

    CopyStream(s_DecryptedStream, s_MemoryStream);
}

Даже после внесения изменений в этот код вы чувствуете, что здесь слишком много нелокальных переменных. Я не могу понять, почему любой из этого должен быть в переменных экземпляра. Сделайте поток для шифрования или дешифрования параметра (вместе с паролем) и верните поток памяти с зашифрованными / дешифрованными данными или просто байтовый массив.

1 голос
/ 11 мая 2009

Вам может потребоваться вызвать метод FlushFinalBlock на CryptoStream после того, как вы закончили чтение входных данных. (т.е. crytpoStream.FlushFinalBlock() после CopyStream)

0 голосов
/ 29 мая 2009

Я нашел решение и разместил его в моем новом блоге

constotech.blogspot.com / 2009/05 / нетто-шифрования с использованием-symmetricalgorithm.html

...