exception when decrypting with Rijndael

2.1k views Asked by At

I have some code that decrypts a password with Rijndael

public static string DecryptPassword(string encrypted) {
    using (MemoryStream ms = new MemoryStream())
    using (RijndaelManaged rijndaelManaged = new RijndaelManaged())
    using (ICryptoTransform cryptoTransform = rijndaelManaged.CreateDecryptor(mGlobalKey, mGlobalVector))
    using (CryptoStream cs = new CryptoStream(ms, cryptoTransform, CryptoStreamMode.Read)) {
        byte[] encryptedBytes = Convert.FromBase64String(encrypted);
        cs.Write(encryptedBytes, 0, encryptedBytes.Length);
        cs.FlushFinalBlock();
        return Encoding.Unicode.GetString(ms.GetBuffer(), 0, (int)ms.Length);
    }
}

The problem is that disposing the cryptostream causes an exception

System.IndexOutOfRangeException : Index was outside the bounds of the array.
at System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast)  
at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)  
at System.Security.Cryptography.CryptoStream.FlushFinalBlock()  
at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing)  
at System.IO.Stream.Close()  
at System.IO.Stream.Dispose()  

I found some links to similar problems but no solutions.

Is it safe to just remove the Disposing of the cryptostream or will that just cause the finalizer to blow up at a later time?

2

There are 2 answers

0
Paras Shah On

Although I couldn’t find a good solution, I found these two work-arounds: A. Don’t make the Encrypt/Decrypt function static (C#) / shared (VB). (You’ll have to change the code to instantiate RijndaelSimple object, and then call the Encrypt/Decrypt functions. Possible cause: NOT sure, but possibly CryptoStream is not using memory stream in a thread-safe way B. It seems that exception is thrown ONLY when cipherText is an empty string. In 1.1, the function used to return an empty string when cipherText is an empty string. So simply add this code as the first line in the Decrypt function: if (string.IsNullOrEmpty(cipherText)) return "";

I went with the option B as // (It would be an efficient soln, as it only fails when cipherText="" // (Efficient as it would still be a static function, and it will Not have to Decrypt when cipherText="")

0
Brad Divine On

You are creating the steam in CryptoStreamMode.Read mode, and attempting to write to it.