Solved

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

Posted on 2011-09-13
3
1,218 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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
International Data Corporation (IDC) prognosticates that before the current the year gets over disbursing on IT framework products to be sent in cloud environs will be $37.1B.
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…
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 …

863 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

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now