Search code examples
c#c#-4.0encryptionencryption-symmetric

How to avoid AESManaged (C#) "Length of the data to decrypt is invalid."


I am using "AesManaged" for encryption and decryption of protected data in web application. in my scenario, i am creating a token based on "Email + CurrentDate" when user login, and send it in encrypted format back to the user(Encryption is done using AESManaged class), and when user invokes next server side method for example "Show Report", the user/client applicaiton will also send that encrypted token with the request. At server side i decrypt the token, and after peforming conditional logic based on decrypted token, it is decided whether the given user have access to this method or not(a kind of authorization check).

It is behaving fine(as expected) for basic flow with user providing the correct encrypted string which he gets from server or it is of same lenght but user replaces characters in the encrypted string.

However, the problem arises, when user get a string of (for example) 54 character but send only 7 character to server. then following exception occurs.

I want to avoid this exception even if the user provides invalid data. so, basically string should always be decrypted, and if it is invalid token, then i can restrict access to the resource. how can I achieve this? your answer will be appreciated.

Exception Details:

Specific code block where exception occur.

 // 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))
                        {
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }

Exception: "Length of the data to decrypt is invalid."

Exception Details:

Target Site: {Byte[] TransformFinalBlock(Byte[], Int32, Int32)}

Declaring Type: {Name = "RijndaelManagedTransform" FullName = "System.Security.Cryptography.RijndaelManagedTransform"}

Name: TransformFinalBlock

Note: i am providing same key and iv for both encryption and decryption method.

Code:

public string EncryptAuthenticationTokenAes(string plainText, byte[] Key, byte[] IV)
        {


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


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

                // 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, byte[] Key, byte[] IV)
        {
            // becuase it is base64, if mod4>0 then it is consider as invalid token
            int mod4 = encryptedString.Length % 4;
            if (mod4 > 0)
            {
                return string.Empty;
            }
            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())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

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

                // 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))
                        {
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }

            }

            return plaintext;
        }

Solution

  • try this

               // 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))
                        {
                            if (encryptedString.Length != aesAlg.BlockSize)
                            {
                                // Handle invalid token here.
                            }
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }