Solved

MVC AES (RijndaelManaged) Encryption - Padding is invalid and cannot be removed"

Posted on 2011-09-13
3
1,222 Views
Last Modified: 2012-05-12
Greetings,

Encrypting and displaying a string of the results works fine, but the decryption in the attached code gives me the "Padding is invalid and cannot be removed" CryptographyException. I have done tons of searching on the web, and per many posts' suggestions I have added a machineKey to the global web.config file, and have set .Padding mode to ANSIX923, PKCS7, ISO10126 and None, and I get  the error every time.

If it matters, I am creating the Key in the Global.asax.cs file like so (called from Application_Start():

public static void GenerateAESKey()
        {
            AESSTuff.AES = new RijndaelManaged();
            AESSTuff.AES.Padding = PaddingMode.None;
            AESSTuff.AES.Mode = CipherMode.CBC;
            AESSTuff.AES.KeySize = 256;
            AESSTuff.AES.GenerateKey();
            AESSTuff.AES.GenerateIV();
        }
    }

    public static class AESSTuff
    {
        public static RijndaelManaged AES { get; set; }
    }

Open in new window


Now the code that is giving me the error:

using System;
using System.IO;
using System.Security.Cryptography;

namespace AESEncryption.Services
{
    public class CryptoService
    {

        public string EncryptData(string myData)
        {
            byte[] t = EncryptStringToBytesAES(myData, AESSTuff.AES.Key, AESSTuff.AES.IV);
            return Convert.ToBase64String(t);
        }

        public string DecryptData(string myData)
        {
            byte[] t = Convert.FromBase64String(myData);
            return DecryptStringFromBytesAES(t, AESSTuff.AES.Key, AESSTuff.AES.IV);
        }

        private static byte[] EncryptStringToBytesAES(string dataToEncrypt, byte[] key, byte[] IV)
        {
            MemoryStream msEncrypt = null;

            RijndaelManaged aesAlgorithm = null;

            aesAlgorithm = new RijndaelManaged();
            aesAlgorithm.Key = key;
            aesAlgorithm.IV = IV;

            ICryptoTransform encryptor = aesAlgorithm.CreateEncryptor(aesAlgorithm.Key, aesAlgorithm.IV);

            msEncrypt = new MemoryStream();
            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            {
                using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                {
                    swEncrypt.Write(dataToEncrypt);
                    swEncrypt.Flush();
                    return msEncrypt.ToArray();
                }
            }
        }

        private static string DecryptStringFromBytesAES(byte[] cipherText, byte[] key, byte[] IV)
        {
            RijndaelManaged aesAlgorithm = null;
            aesAlgorithm = new RijndaelManaged();
            aesAlgorithm.Key = key;
            aesAlgorithm.IV = IV;

            ICryptoTransform decyptor = aesAlgorithm.CreateDecryptor(aesAlgorithm.Key, aesAlgorithm.IV);

            using (MemoryStream msDecrypt = new MemoryStream(cipherText))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decyptor, CryptoStreamMode.Read))
                {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {
                        return srDecrypt.ReadToEnd();
                    }
                }
            }
        }
    }
}

Open in new window


There is nothing proprietary about this code, meaning I can attach the entire project if that helps anyone in helping me.

I have been at this for two days now, and am no closer to a solution.

Any ideas?
0
Comment
Question by:David_Graves
  • 3
3 Comments
 

Author Comment

by:David_Graves
ID: 36531647
Also, I typoed the 3rd tag in the list of tags for this post and have no idea how to remove it.
0
 

Author Comment

by:David_Graves
ID: 36531721
If it matters, the string to be encrypted is simply being entered on a form, and the encryption method above is being called via AJAX. The decryption method is being called via the encryption method's AJAX success: statement.

   function Submit() {
        var dataToEncrypt = $('#DataToEncrypt').attr('value');
        alert("Submitted: " + dataToEncrypt);
        EncryptData(dataToEncrypt);
        return false;
    };
    function EncryptData(dataToEncrypt) {
        alert("EncryptData: " + dataToEncrypt);
        $.ajax(
            {
                type: 'POST',
                url: '@Url.Action("EncryptData", "Crypto")',
                dataType: 'html',
                data: { data: dataToEncrypt },
                success: function (data) { $('#encryptedString').html(data); DecryptData(data); },
                error: function (req, status, error) {
                    alert(error);
                }
            });
    };
    function DecryptData(dataToDecrypt) {
        alert("DataToDecrypt:" + dataToDecrypt);
        $.ajax(
        {
            type: 'POST',
            url: '@Url.Action("DecryptData", "Crypto")',
            dataType: 'html',
            data: { data: dataToDecrypt },
            success: function (data) { $('#decryptedString').html(data); }
        });
    };

Open in new window

0
 

Accepted Solution

by:
David_Graves earned 0 total points
ID: 36531888
And... I figured it out.

I added a .Close() for the StreamWriter just before I returned my data in the encryption routine.

                    swEncrypt.Write(dataToEncrypt);
                    swEncrypt.Flush();
                    swEncrypt.Close();
                    return msEncrypt.ToArray();

Open in new window


I discovered it from the first answer in this thread. Shawn Farka mentions something about ensuring the stream gets closed at the right time so that the padding is written properly.
0

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Encryption for Business Encryption (https://en.wikipedia.org/wiki/Encryption) ensures the safety of our data when sending emails. In most cases, to read an encrypted email you must enter a secret key that will enable you to decrypt the email. T…
The article shows the basic steps of integrating an HTML theme template into an ASP.NET MVC project
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

773 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question