11

I have error from CryptoStream:

Padding is invalid and cannot be removed.

Code

public MemoryStream EncrypteBytes(Stream inputStream, string passPhrase, string saltValue)
{
    RijndaelManaged RijndaelCipher = new RijndaelManaged();
    RijndaelCipher.Padding = PaddingMode.PKCS7;
    RijndaelCipher.Mode = CipherMode.CBC;
    byte[] salt = Encoding.ASCII.GetBytes(saltValue);
    PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, salt, "SHA1", 2);

    ICryptoTransform Encryptor = RijndaelCipher.CreateEncryptor(password.GetBytes(32), password.GetBytes(16));
    MemoryStream memoryStream = new MemoryStream();
    CryptoStream cryptoStream = new CryptoStream(memoryStream, Encryptor, CryptoStreamMode.Write);
    var buffer = new byte[1024];
    var read = inputStream.Read(buffer, 0, buffer.Length);
    while (read > 0)
    {
        cryptoStream.Write(buffer, 0, read);
        read = inputStream.Read(buffer, 0, buffer.Length);
    }

    cryptoStream.FlushFinalBlock();
    memoryStream.Position = 0;
    return memoryStream;
}

// Example usage: DecryptBytes(encryptedBytes, "SensitivePhrase", "SodiumChloride");
public byte[] DecrypteBytes(MemoryStream memoryStream, string passPhrase, string saltValue)
{
    RijndaelManaged RijndaelCipher = new RijndaelManaged();
    RijndaelCipher.Padding = PaddingMode.PKCS7;

    RijndaelCipher.Mode = CipherMode.CBC;
    byte[] salt = Encoding.ASCII.GetBytes(saltValue);
    PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, salt, "SHA1", 2);

    ICryptoTransform Decryptor = RijndaelCipher.CreateDecryptor(password.GetBytes(32), password.GetBytes(16));


    CryptoStream cryptoStream = new CryptoStream(memoryStream, Decryptor, CryptoStreamMode.Read);
    byte[] plainBytes = new byte[memoryStream.Length];

    int DecryptedCount = cryptoStream.Read(plainBytes, 0, plainBytes.Length);

    return plainBytes;
}
Community
  • 1
  • 1
no camer
  • 185
  • 1
  • 3
  • 15
  • 1
    You're either using a different `passPhrase` or a different `saltValue` (or both) between encrypting and decrypting, as your code seems to work for me. – Iridium May 01 '14 at 12:51
  • You might be interested in [`Stream.CopyTo`](http://msdn.microsoft.com/en-us/library/dd782932.aspx) to simplify your code. If your messages are short (they seem to be since you're using `MemoryStream`) you can throw out all those streams entirely and just use `encryptor.TransformFinalBlock` – CodesInChaos May 01 '14 at 14:15

4 Answers4

18

Use PaddingMode.Zeros to fix problem , Following code:

   public byte[] EncryptFile(Stream input, string password, string salt)
            {

                // Essentially, if you want to use RijndaelManaged as AES you need to make sure that:
                // 1.The block size is set to 128 bits
                // 2.You are not using CFB mode, or if you are the feedback size is also 128 bits

                var algorithm = new RijndaelManaged { KeySize = 256, BlockSize = 128 };
                var key = new Rfc2898DeriveBytes(password, Encoding.ASCII.GetBytes(salt));

                algorithm.Key = key.GetBytes(algorithm.KeySize / 8);
                algorithm.IV = key.GetBytes(algorithm.BlockSize / 8);
                algorithm.Padding = PaddingMode.Zeros;

                using (Stream cryptoStream = new MemoryStream())
                using (var encryptedStream = new CryptoStream(cryptoStream, algorithm.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    CopyStream(input, encryptedStream);

                    return ReadToEnd(cryptoStream);
                }
            }

            public byte[] DecryptFile(Stream input, Stream output, string password, string salt)
            {
                // Essentially, if you want to use RijndaelManaged as AES you need to make sure that:
                // 1.The block size is set to 128 bits
                // 2.You are not using CFB mode, or if you are the feedback size is also 128 bits
                var algorithm = new RijndaelManaged { KeySize = 256, BlockSize = 128 };
                var key = new Rfc2898DeriveBytes(password, Encoding.ASCII.GetBytes(salt));

                algorithm.Key = key.GetBytes(algorithm.KeySize / 8);
                algorithm.IV = key.GetBytes(algorithm.BlockSize / 8);
                algorithm.Padding = PaddingMode.Zeros;

                try
                {
                    using (var decryptedStream = new CryptoStream(output, algorithm.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        CopyStream(input, decryptedStream);
                        return ReadToEnd(output);
                    }
                }
                catch (CryptographicException ex)
                {
                    throw new InvalidDataException("Please supply a correct password");
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
            }

I hop help you.

Amir Movahedi
  • 1,802
  • 3
  • 29
  • 52
  • 2
    Hi @amir do you have the CopyStream and ReadToEnd function for this code , i tried some alternates for it and getting some bug while decryption. – Aravind Apr 03 '15 at 13:20
11

Please check your pass phrase - it should be same in both methods EncrypteBytes and DecrypteBytes. If both are not same, then it will generate the error.

Lars A. Brekken
  • 24,405
  • 3
  • 25
  • 27
Dhaval Patel
  • 7,471
  • 6
  • 37
  • 70
1

My problem was I was taking the encryped output in bytes and converting it to a string. The string back to byte array (for decrypting) was not the same. I was using UTF8Encoding, then I tried ASCIIEnconding. Neither worked.

Convert.FromBase64String/ToBase64String worked fine, got rid of the padding issues and actually decrypted the data.

Tod
  • 2,070
  • 21
  • 27
-1

It's work

using (FileStream fs = new FileStream( absolute, FileMode.Open )) {
    // create a CryptoStream in read mode
    using (CryptoStream cryptoStream = new CryptoStream( fs, decryptor, CryptoStreamMode.Read )) {
        int readLength = ( int )fs.Length;
        byte[] buffer = new byte[readLength];
        cryptoStream.Read( buffer, 0, readLength );
        using (MemoryStream ms = new MemoryStream( buffer )) {
            BinaryFormatter bf = new BinaryFormatter( );
            settings = ( SettingsJson )bf.Deserialize( ms );// Deserialize SettingsJson array
        }
    }
    fs.Close( );
}
Rajib Chy
  • 800
  • 10
  • 22