Decryption Exception - length of the data to decrypt is invalid

43,949

Your problem is string cipher_Tx = Encoding.Default.GetString(x_ciphertext, 0, x_ciphertext.Length);.

x_ciphertext is not a valid byte representation of text, it has many unpresentable characters and when you do your byte[] to string conversion you are loosing information. The correct way to do it is use a string format that is designed to represent binary data using something like Convert.ToBase64String(byte[]) and Convert.FromBase64String(string).

string cipher_Tx = Convert.ToBase64String(x_ciphertext)

x_encryptor.Dispose();

x_alg.Clear();
byte[] cipher = Convert.FromBase64String(cipher_Tx)

That being said, there is a lot of other "odd" things about your code, for example you don't use using statements and you really should. Also that whole conversion to string and back is totally unnecessary, just return x_ciphertext. There may be other problems with the code too (like where did the strings for Key and IV come from) and many other best practices (like you should be generating a random IV and writing it out in to the output and the key should be generated using a key derivation function not straight from user text), but I stopped checking after I found the string conversion issue.

Share:
43,949
Kevin Morocco
Author by

Kevin Morocco

Updated on July 09, 2022

Comments

  • Kevin Morocco
    Kevin Morocco almost 2 years

    I am working in a C# application. We have common methods to store data on a file. These methods encrypt the data and store them on the file system. when we need the data, ReadData method decrypts the data and returns me plain text.

    This code works fine in normal cases if size of the text in small. but for a example text given below, the decryption code is throwing exception - length of the data to decrypt is invalid.

    The exception occurs at line

            // close the CryptoStream
            x_cryptostream.Close();
    

    I tried different ways but no luck. Can some pls help.

    Why am I encrypting already encrypted data - I am just trying to store in a file using common method of the huge application. The common methods storedata(key,data) nad readdata(key) do the encryption/decryption I can't avoid.

       public static byte[] Decrypt(byte[] ciphertext, string Key, string IV)
        {
            byte[] k = Encoding.Default.GetBytes(Key);
            byte[] iv = Encoding.Default.GetBytes(IV);
    
            // create the encryption algorithm
            SymmetricAlgorithm x_alg = SymmetricAlgorithm.Create("Rijndael");
            x_alg.Padding = PaddingMode.PKCS7;
    
            // create an ICryptoTransform that can be used to decrypt data
            ICryptoTransform x_decryptor = x_alg.CreateDecryptor(k, iv);
    
            // create the memory stream
            MemoryStream x_memory_stream = new MemoryStream();
    
            // create the CryptoStream that ties together the MemoryStream and the 
            // ICryptostream
            CryptoStream x_cryptostream = new CryptoStream(x_memory_stream,
            x_decryptor, CryptoStreamMode.Write);
    
            // write the ciphertext out to the cryptostream
            x_cryptostream.Write(ciphertext, 0, ciphertext.Length);
    
            // close the CryptoStream
            x_cryptostream.Close();
    
            // get the plaintext from the MemoryStream
            byte[] x_plaintext = x_memory_stream.ToArray();
    

    Below is the code of encrypt method.

            public static byte[] Encrypt(string strplain, string Key, string IV)
            {
            byte[] k = Encoding.Default.GetBytes(Key);
            byte[] iv = Encoding.Default.GetBytes(IV);
    
            byte[] plaintext = Encoding.Default.GetBytes(strplain);
    
            // create the encryption algorithm
            SymmetricAlgorithm x_alg = SymmetricAlgorithm.Create("Rijndael");
            x_alg.Padding = PaddingMode.PKCS7;
            // create an ICryptoTransform that can be used to encrypt data
            ICryptoTransform x_encryptor = x_alg.CreateEncryptor(k, iv);
    
            // create the memory stream
            MemoryStream x_memory_stream = new MemoryStream();
    
            // create the CryptoStream that ties together the MemoryStream and
            // the ICryptostream
            CryptoStream x_cryptostream = new CryptoStream(x_memory_stream,
            x_encryptor, CryptoStreamMode.Write);
    
            // write the plaintext out to the cryptostream
            x_cryptostream.Write(plaintext, 0, plaintext.Length);
    
            // close the CryptoStream
            x_cryptostream.Close();
    
            // get the ciphertext from the MemoryStream
            byte[] x_ciphertext = x_memory_stream.ToArray();
    
            // close memory stream
            x_memory_stream.Close();
    
            // convert from array to string
            string cipher_Tx = Encoding.Default.GetString(x_ciphertext, 
                0, x_ciphertext.Length);
    
            x_encryptor.Dispose();
    
            x_alg.Clear();
            byte[] cipher = Encoding.Default.GetBytes(cipher_Tx);
    
            return cipher;
        }  
    
  • Kevin Morocco
    Kevin Morocco about 10 years
    Thanks for trying to help. Truly appreciate it I modified my code but this doesn't resolve the exception I mentioned. Key and IV is passed by the ReadData/StoreData methods. This code is written several years ago. I believe this is something to do with blocks of data decryption algorithm uses not matching with the size or something.
  • Scott Chamberlain
    Scott Chamberlain about 10 years
    Well you seem to really like using Encoding.Default. and I am willing to bet almost every use of it is wrong. I would check the other parts of the program for similar issues.
  • Kevin Morocco
    Kevin Morocco about 10 years
    I looked at entire code related to encrypt decrypt and changed all the lines of Encoding.Default to Convert.FromBase64String/Convert.ToBase64String. I still get length of the data to decrypt is invalid exception.
  • Jim Flood
    Jim Flood about 10 years
    There is no reason to convert to Base 64 and back. Look at byte[] x_ciphertext and then byte[] cipher -- they are exactly the same value. Just return x_ciphertext -- you already have it.
  • Kevin Morocco
    Kevin Morocco about 10 years
    Thanks. I accidentally deleted padding. I think changing encoding to Convert.FromBase64String(cipher_Tx) and adding x_alg.Padding = PaddingMode.PKCS7 fixed the issue.