0

I tried to implement this code to encrypt and decrypt streams. Everything worked fine until I implemented buffer. Than when I try decrypting, an 'Invalid padding' error is thrown.

Does anyone know why this happens. Or is there another way of encrypting/decrypting stream and use buffer?

public static void EncryptStringToBytes_Aes(Stream source, Stream target, byte[] Key, byte[] IV, int iterations, int buffer = 4096)
    {
        // Check arguments.
        if (Key == null || Key.Length <= 0)
            throw new ArgumentNullException("Key");
        if (IV == null || IV.Length <= 0)
            throw new ArgumentNullException("IV");
        // Create an Aes object
        // with the specified key and IV.
        using (System.Security.Cryptography.Aes aesAlg = System.Security.Cryptography.Aes.Create())
        {
            aesAlg.Key = Key;
            aesAlg.IV = IV;

            // Create a decryptor to perform the stream transform.
            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

            Rfc2898DeriveBytes iterator = new Rfc2898DeriveBytes(Encoding.ASCII.GetString(Key), 64, iterations);
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(target, iterations);
            formatter.Serialize(target, IV);
            formatter.Serialize(target, iterator.Salt);
            Key = iterator.GetBytes(64);

            // Create the streams used for encryption.
            using (CryptoStream csEncrypt = new CryptoStream(target, encryptor, CryptoStreamMode.Write))
            using (BinaryReader reader = new BinaryReader(source))
            using (BinaryWriter writer = new BinaryWriter(csEncrypt))
                //Write all data to the stream.
                while (reader.BaseStream.Position != reader.BaseStream.Length)
                    writer.Write(reader.ReadBytes(buffer));
        }
    }

    public static void DecryptStringFromBytes_Aes(Stream source, Stream target, byte[] Key, int buffer = 4096)
    {
        // Check arguments.
        if (Key == null || Key.Length <= 0)
            throw new ArgumentNullException("Key");

        // Create an Aes object
        // with the specified key and IV.
        using (System.Security.Cryptography.Aes aesAlg = System.Security.Cryptography.Aes.Create())
        {
            BinaryFormatter formatter = new BinaryFormatter();
            int iterations = (int)formatter.Deserialize(source);
            aesAlg.IV = formatter.Deserialize(source) as byte[];
            byte[] salt = formatter.Deserialize(source) as byte[];
            Rfc2898DeriveBytes iterator = new Rfc2898DeriveBytes(Key, salt, iterations);
            aesAlg.Key = iterator.GetBytes(32);

            // Create a decryptor to perform the stream transform.
            ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

            // Create the streams used for decryption.
            using (CryptoStream csDecrypt = new CryptoStream(source, decryptor, CryptoStreamMode.Read))
            using (BinaryReader reader = new BinaryReader(csDecrypt))
            using (BinaryWriter writer = new BinaryWriter(target))
                // Read the decrypted bytes from the decrypting stream
                // and place them in a string.
                while (source.Position != source.Length)
                    writer.Write(reader.ReadBytes(buffer));
        }
    }
daralim
  • 183
  • 10
  • 2
    The key you're using for encrypting is not the same key you're using to decrypt - when encrypting you use the `Key` parameter directly (`aesAlg.Key = Key;`) but when decrypting, you're deriving the key bytes from `Rfc2898DeriveBytes` (`aesAlg.Key = iterator.GetBytes(32);`). You do seem to be doing the same key derivation in the encrypt side, but you never use the result. – Iridium Feb 19 '18 at 08:48
  • Thanks for the answer, @Iridium, but the problem is something else. It seems like CryptoStream class has problems processing FileStream when decrypting (in this code). When I test this code with MemoryStream, it works, when I want to use files, it doesn't. For anyone looking for encrypting files, look here: https://stackoverflow.com/questions/9237324/encrypting-decrypting-large-files-net – daralim Feb 19 '18 at 21:33
  • No, it isn't "something else", the issue is exactly as I described in my original comment. With this bug fixed, your code works as expected. – Iridium Feb 20 '18 at 17:54

0 Answers0