Home Dashboard Directory Help
Search

CrypoStream encountering "Length of the data to decrypt is invalid" when decrypting certain values by HeartOfGold


Status: 

Closed
 as By Design Help for as By Design


0
0
Sign in
to vote
Type: Bug
ID: 325676
Opened: 1/31/2008 7:41:06 AM
Access Restriction: Public
0
Workaround(s)
view
0
User(s) can reproduce this bug

Description

Note: this issue was originally reported on at http://forums.asp.net/t/1209796.aspx and has subsequently been confirmed as an issue on VS 2008 by XiaoYong Dai, Microsoft Online Community Support. (see forum thread for details)


Summary:

After successfully encrypting certain values using the CrypoStream object, subsequent decryption generates an error "Length of the data to decrypt is invalid". This problem is intermitent and only occurs when encrypting / decrypting specific values.

This issue has been confirmed for the "Rijndael" algorithm, but may also be an problem in "DES" as well.

The bug may be related to the encryption key that is used. When unusual characters such as "/", "%", "$" are present in the key, the error seems to occur more often. It has not been possible to reproduce the error when 'regular' characters (a-z, A-Z, 0-9) are used.

This issue was originally uncovered on VS2005.
Details
Sign in to post a comment.
Posted by Charan49 on 10/3/2013 at 11:51 PM
We have been using the this algorithm from last 2 years, All of a sudden we have got this error, The data is encrypts fine . but while decryption we got this error. This also happened for a particular data. Not sure what was that data. Not able to reproduce also.

Below is the code which i am using

public string EncryptData(string inputData)
        {
            byte[] encodedInput = System.Text.Encoding.Unicode.GetBytes(inputData);
            byte[] encodePwd = System.Text.Encoding.Unicode.GetBytes(_password);
            byte[] encodedSalt = System.Text.Encoding.Unicode.GetBytes(_salt);

            string outputDate = string.Empty;
            PasswordDeriveBytes pwdBytes = new PasswordDeriveBytes(encodedSalt, encodePwd);

            MemoryStream ms = new MemoryStream();
            Rijndael alg = Rijndael.Create();

            alg.Key = pwdBytes.GetBytes(32);
            alg.IV = pwdBytes.GetBytes(16);

            CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(encodedInput, 0, encodedInput.Length);
            cs.Close();

            byte[] encryptedData = ms.ToArray();

            return Convert.ToBase64String(encryptedData);

        }

        public string DecryptData(string encrptedInput)
        {
            byte[] encodedString = Convert.FromBase64String(encrptedInput);
            byte[] encodePwd = System.Text.Encoding.Unicode.GetBytes(_password);
            byte[] encodedSalt = System.Text.Encoding.Unicode.GetBytes(_salt);
            MemoryStream ms = null;
            CryptoStream cs = null;

            try
            {
                PasswordDeriveBytes pwdBytes = new PasswordDeriveBytes(encodedSalt, encodePwd);

                ms = new MemoryStream();
                Rijndael obj = Rijndael.Create();

                obj.Key = pwdBytes.GetBytes(32);
                obj.IV = pwdBytes.GetBytes(16);

                cs = new CryptoStream(ms, obj.CreateDecryptor(), CryptoStreamMode.Write);
                cs.Write(encodedString, 0, encodedString.Length);

                cs.Close();

                byte[] decrptionData = ms.ToArray();

                string outputData = System.Text.Encoding.Unicode.GetString(decrptionData);
                return outputData;
            }
            catch (Exception ex)
            {
                ms = null;
                throw ex;
            }
            finally
            {
                ms = null;
                cs = null;
            }
        }
    }
Posted by HeartOfGold on 2/24/2008 at 5:48 AM
Thanks so much for the analysis and tips. I'm glad it turned out to be something I was doing rather than something bigger.

The additional tips are great to and I'll adjust my code accordingly.
Posted by Microsoft on 2/14/2008 at 11:28 AM
Hi Sheldon,

The problem here is not with the crypto types, but with the code used to convert the ciphertext to a base64 string. This conversion is dropping data, and therefore you're decryption code doesn't have the complete final block causing the error.

If you change the code which currently reads:

            // get the output and trim the '\0' bytes
            byte[] bytOut = ms.GetBuffer();
            int i = 0;
            for (i = 0; i < bytOut.Length; i++)
                if (bytOut[i] == 0)
                    break;

            // convert into Base64 so that the result can be used in xml
            strTmpOutputString = System.Convert.ToBase64String(bytOut, 0, i);

To be:

            // get the output
            byte[] bytOut = ms.ToArray();
            strTmpOutputString = System.Convert.ToBase64String(bytOut);

You'll find that the data is no longer missing on the other end.

As a heads up, this code is doing a few other things which aren't 100% recommended. For instance, ASCII encoding is a 7 bit encoding, so if you had data or a password that used that upper bit you'd be broken because that bit would get dropped. In this case it didn't matter, but UTF8 encoding will preserve all bits.

The IV and Key used for encryption / decryption should not match -- the IV is considered public information, and using both as the same makes your ciphertext suceptable to attack.

To convert from a string to a key, you probably don't want to be just using an Encoding and adding on blank bits -- your key will have significantly lower security than would be expected from a key of that number of bits. Instead you can use a class like Rfc2898DeriveBytes which converts passwords to strong keys.

-Shawn Farkas [MS]
Posted by Microsoft on 1/31/2008 at 10:36 PM
Thanks for your feedback. We are escalating this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue.

Thank you,
Visual Studio Product Team
Sign in to post a workaround.