Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
217 views
in Technique[技术] by (71.8m points)

c# - Reading from a cryptostream to the end of the stream

I'm having some trouble with the code below. I have a file in a temporary location which is in need of encryption, this function encrypts that data which is then stored at the "pathToSave" location.

On inspection is does not seem to be handling the whole file properly - There are bits missing from my output and I suspect it has something to do with the while loop not running through the whole stream.

As an aside, if I try and call CryptStrm.Close() after the while loop I receive an exception. This means that if I attempt to decrypt the file, I get a file already in use error!

Tried all the usual and Ive looked on here at similar issues, any help would be great.

Thanks

public void EncryptFile(String tempPath, String pathToSave)
    {
        try
        {
            FileStream InputFile = new FileStream(tempPath, FileMode.Open, FileAccess.Read);
            FileStream OutputFile = new FileStream(pathToSave, FileMode.Create, FileAccess.Write);

            RijndaelManaged RijCrypto = new RijndaelManaged();

            //Key
            byte[] Key = new byte[32] { ... };

            //Initialisation Vector
            byte[] IV = new byte[32] { ... };

            RijCrypto.Padding = PaddingMode.None;
            RijCrypto.KeySize = 256;
            RijCrypto.BlockSize = 256;
            RijCrypto.Key = Key;
            RijCrypto.IV = IV;

            ICryptoTransform Encryptor = RijCrypto.CreateEncryptor(Key, IV);

            CryptoStream CryptStrm = new CryptoStream(OutputFile, Encryptor, CryptoStreamMode.Write);

            int data;
            while (-1 != (data = InputFile.ReadByte()))
            {
                CryptStrm.WriteByte((byte)data);
            }
        }
        catch (Exception EncEx)
        {
            throw new Exception("Encoding Error: " + EncEx.Message);
        }
    }

EDIT:

I've made the assumption that my problem is with Encryption. My Decrypt might be the culprit

        public String DecryptFile(String encryptedFilePath)
    {
        FileStream InputFile = new FileStream(encryptedFilePath, FileMode.Open, FileAccess.Read);

        RijndaelManaged RijCrypto = new RijndaelManaged();

        //Key
        byte[] Key = new byte[32] { ... };

        //Initialisation Vector
        byte[] IV = new byte[32] { ... };

        RijCrypto.Padding = PaddingMode.None;
        RijCrypto.KeySize = 256;
        RijCrypto.BlockSize = 256;
        RijCrypto.Key = Key;
        RijCrypto.IV = IV;

        ICryptoTransform Decryptor = RijCrypto.CreateDecryptor(Key, IV);

        CryptoStream CryptStrm = new CryptoStream(InputFile, Decryptor, CryptoStreamMode.Read);

        String OutputFilePath = Path.GetTempPath() + "myfile.name";
        StreamWriter OutputFile = new StreamWriter(OutputFilePath);

        OutputFile.Write(new StreamReader(CryptStrm).ReadToEnd());

        CryptStrm.Close();
        OutputFile.Close();

        return OutputFilePath;
    }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Well, there are several things going wrong here.

1. Your setting the size of the IV too large. If you have a key size of 256, the IV for Rijndael is 16 bytes. If you try to set the key with more bytes than that you will get an exception. IV size should be set to Block size / 8 see MSDN so the IV size you have is correct.

  1. You have a padding mode of None. Unless your data is exactly the correct block size, then you are going to have problems. You probably want to pick a padding mode.
  2. You typically need to call FlushFInalBlock when done writing to the crypto stream when you are encrypting to ensure all of the data is written to the stream.

I am posting some sample code using memory streams to show the encrypting and decrypting.

var tempData = "This is the text to encrypt. It's not much, but it's all there is.";

using (var rijCrypto = new RijndaelManaged())
{
    byte[] encryptedData;
    rijCrypto.Padding = System.Security.Cryptography.PaddingMode.ISO10126;
    rijCrypto.KeySize = 256;

    using (var input = new MemoryStream(Encoding.Unicode.GetBytes(tempData)))
    using (var output = new MemoryStream())
    {
        var encryptor = rijCrypto.CreateEncryptor();

        using (var cryptStream = new CryptoStream(output, encryptor, CryptoStreamMode.Write))
        {
            var buffer = new byte[1024];
            var read = input.Read(buffer, 0, buffer.Length);
            while (read > 0)
            {
                cryptStream.Write(buffer, 0, read);
                read = input.Read(buffer, 0, buffer.Length);
            }
            cryptStream.FlushFinalBlock();
            encryptedData = output.ToArray();
        }
    }

    using (var input = new MemoryStream(encryptedData))
    using (var output = new MemoryStream())
    {
        var decryptor = rijCrypto.CreateDecryptor();
        using (var cryptStream = new CryptoStream(input, decryptor, CryptoStreamMode.Read))
        {
            var buffer = new byte[1024];
            var read = cryptStream.Read(buffer, 0, buffer.Length);
            while (read > 0)
            {
                 output.Write(buffer, 0, read);
                 read = cryptStream.Read(buffer, 0, buffer.Length);
            }
            cryptStream.Flush();
            var result = Encoding.Unicode.GetString(output.ToArray());
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...