Search code examples
c#encryptionencryption-symmetricrijndael

Decrypting byte array with SymmetricAlgorithm and CryptoStream


My encrypting and decrypting methods:

private static SymmetricAlgorithm GetAlgorithm(string password)
{
    using (Rijndael algorithm = Rijndael.Create())
    {
        using (Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(password, new byte[]
        {
            0x53, 0x6f, 0x64, 0x69, 0x75, 0x6d, 0x20, 0x43, 0x68, 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x65
        }))
        {
            algorithm.Padding = PaddingMode.ISO10126;
            algorithm.Key = rdb.GetBytes(32);
            algorithm.IV = rdb.GetBytes(16);
        }
        return algorithm;
    }
}

public static byte[] EncryptBytes(byte[] clearBytes, string password)
{
    ICryptoTransform encryptor;
    using (SymmetricAlgorithm algorithm = GetAlgorithm(password))
        encryptor = algorithm.CreateEncryptor();
    using (MemoryStream ms = new MemoryStream())
    using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
    {
        cs.Write(clearBytes, 0, clearBytes.Length);
        cs.FlushFinalBlock();
        return ms.ToArray();
    }
}

public static byte[] DecryptBytes(byte[] cipherBytes, string password)
{
    ICryptoTransform decryptor;
    using (SymmetricAlgorithm algorithm = GetAlgorithm(password))
        decryptor = algorithm.CreateDecryptor();
    using (MemoryStream ms = new MemoryStream())
    using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
    {
        cs.Write(cipherBytes, 0, cipherBytes.Length); //here is the exception thrown
        cs.FlushFinalBlock();
        return ms.ToArray();
    }
}

How i call the methods:

byte[] prev = File.ReadAllBytes(path + sourcefile);
byte[] enc = Encryption.EncryptBytes(prev, password);
byte[] dec = Encryption.DecryptBytes(enc, password);

File.WriteAllBytes(path + targetfile, dec);

When i try to decrypt the byte array i get the following exception:

System.Security.Cryptography.CryptographicException
Additional information: padding is invalid and cannot be removed

I already read some possible solutions but none of them solved my problem. The Key and IV (InitialisationVector) are the same, when i encrypt and decrypt so that's definitely not the reason.


Solution

  • Corrected methods:

    ERROR: you were disposing the Rijndael algorithm in the GetAlgorithm(). This is wrong: it is the caller of GetAlgorithm() that must dispose the algorithm (as you were correctly doing)

    private static SymmetricAlgorithm GetAlgorithm(string password)
    {
        Rijndael algorithm = Rijndael.Create();
    
        using (Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(password, new byte[]
        {
            0x53, 0x6f, 0x64, 0x69, 0x75, 0x6d, 0x20, 0x43, 0x68, 0x6c, 0x6f, 0x72, 0x69, 0x64, 0x65
        }))
        {
            algorithm.Padding = PaddingMode.ISO10126;
            algorithm.Key = rdb.GetBytes(32);
            algorithm.IV = rdb.GetBytes(16);
        }
    
        return algorithm;
    }
    

    Small warnings here: you were not disposing the ICryptoTransform.

    public static byte[] EncryptBytes(byte[] clearBytes, string password)
    {
        using (SymmetricAlgorithm algorithm = GetAlgorithm(password))
        using (ICryptoTransform encryptor = algorithm.CreateEncryptor())
        using (MemoryStream ms = new MemoryStream())
        using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
        {
            cs.Write(clearBytes, 0, clearBytes.Length);
            cs.FlushFinalBlock();
            return ms.ToArray();
        }
    }
    
    public static byte[] DecryptBytes(byte[] cipherBytes, string password)
    {
        using (SymmetricAlgorithm algorithm = GetAlgorithm(password))
        using (ICryptoTransform decryptor = algorithm.CreateDecryptor())
        using (MemoryStream ms = new MemoryStream())
        using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
        {
            cs.Write(cipherBytes, 0, cipherBytes.Length); //here is the exception thrown
            cs.FlushFinalBlock();
            return ms.ToArray();
        }
    }