Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Padding is invalid and cannot be removed Exception while decrypting string using "AesManaged" C#

Please suggest me where i need to update/refactor the code to get rid of exception. I am getting exception while I try to decrypt the encrypted string using following code.

Following line is throwing exception

using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
     // Read the decrypted bytes from the decrypting stream
     // and place them in a string.
     plaintext = srDecrypt.ReadToEnd();
}

public string EncryptAuthenticationTokenAes(string plainText)
{

    byte[] encrypted;
    // Create an AesManaged object
    // with the specified key and IV.
    using (AesManaged aesAlg = new AesManaged())
    {

        // Create a decrytor to perform the stream transform.
        ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
        aesAlg.Padding = PaddingMode.None;
        // Create the streams used for encryption.
        using (MemoryStream msEncrypt = new MemoryStream())
        {
            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            {
                using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                {

                    //Write all data to the stream.
                    swEncrypt.Write(plainText);
                }
                encrypted = msEncrypt.ToArray();
            }
        }
    }


    // Return the encrypted bytes from the memory stream.
    return Convert.ToBase64String(encrypted);

}

public string DecryptPasswordAes(string encryptedString)
{
    //Convert cipher text back to byte array
    byte[] cipherText = Convert.FromBase64String(encryptedString);

    // Declare the string used to hold
    // the decrypted text.
    string plaintext = null;

    // Create an AesManaged object
    // with the specified key and IV.
    using (AesManaged aesAlg = new AesManaged())
    {
        // Create a decrytor to perform the stream transform.
        ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
        aesAlg.Padding = PaddingMode.None;
        // Create the streams used for decryption.
        using (MemoryStream msDecrypt = new MemoryStream(cipherText))
        {
            using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
            {
                using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                {

                    // Read the decrypted bytes from the decrypting stream
                    // and place them in a string.
                    plaintext = srDecrypt.ReadToEnd();
                }
            }
        }

    }

    return plaintext;

}
like image 655
aamir sajjad Avatar asked May 06 '12 10:05

aamir sajjad


People also ask

How do you resolve Padding is invalid and Cannot be removed?

Just set PaddingMode to PaddingMode. Zeros in encryption and decryption.

Can't decrypt data Padding is invalid and Cannot be removed?

The "Internal: Could not decrypt data: Padding is invalid and cannot be removed." error occurs when a different encryption key is used to try and decrypt the encrypted data.

What is PKCS 7 Padding?

PKCS7 padding is a generalization of PKCS5 padding (also known as standard padding). PKCS7 padding works by appending N bytes with the value of chr(N) , where N is the number of bytes required to make the final block of data the same size as the block size.

What is CryptoStream C#?

CryptoStream is designed to perform transformation from a stream to another stream only and allows transformations chaining. For instance you can encrypt a data stream then Base 64 encode the encryption output.


1 Answers

Pretty standard bug when using CryptoStream, you forgot to force it to encrypt the last bytes of the stream. It keeps bytes in an internal buffer until enough of them arrive to emit a block. You must force the last few bytes out. Fix:

    using (var msEncrypt = new MemoryStream())
    using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
    using (var swEncrypt = new StreamWriter(csEncrypt)) {
        swEncrypt.Write(plainText);
        csEncrypt.FlushFinalBlock();
        encrypted = msEncrypt.ToArray();
    }

You got the exception when decrypting it because encrypted is missing the final padding. The real problem is caused by the using statement, you wouldn't have this problem if you waited obtaining the encrypted bytes until after the CryptoStream is closed. But that doesn't work well because the using statement on the StreamWriter also closes the CryptoStream and the MemoryStream. Explicitly using FlushFinalBlock() is the best workaround.

like image 196
Hans Passant Avatar answered Sep 28 '22 05:09

Hans Passant