Question

I get the following exception when decrypting a string, but it only occurs when the original string (before encryption) is > 751 characters. It didn't have any problems encrypting. How can I avoid this problem?

System.Security.Cryptography.CryptographicException occurred
  Message="Length of the data to decrypt is invalid."
  Source="mscorlib"
  StackTrace:
       at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)    at System.Security.Cryptography.CryptoStream.Read(Byte[] buffer, Int32 offset, Int32 count)    at VHC.Reporting.View.QueryString.QueryStringObsuficator.Decrypt(String inputText) in E:\Kiln_Repository\Reports\DevExpress_New\VHC_Reporting\VHC.Reporting.View\Classes\QueryString\QueryStringObsuficator.vb:line 159
  InnerException: 

I have spent a while looking at this as there it seems to be a common question on stack overflow, however I don't think any of them cover my question, apologies if I have missed something.

There's a bug report here, but special characters don't seem to be the problem.

The methods I use are:

Public Shared Function Encrypt(ByVal inputText As String) As String
    Dim rijndaelCipher As New RijndaelManaged()
    Dim plainText As Byte() = Encoding.Unicode.GetBytes(inputText)
    Dim SecretKey As New Rfc2898DeriveBytes(EncryptionKey, SALT)

    Using encryptor As ICryptoTransform = rijndaelCipher.CreateEncryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16))
        Using memoryStream As New MemoryStream()
            Using cryptoStream As New CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)
                cryptoStream.Write(plainText, 0, plainText.Length)
                cryptoStream.FlushFinalBlock()
                Return String.Concat(QuestionMark, ParameterName, Convert.ToBase64String(memoryStream.ToArray()))
            End Using
        End Using
    End Using
End Function


Private Shared Function Decrypt(ByVal inputText As String) As String
    Dim rijndaelCipher As New RijndaelManaged()
    Dim encryptedData As Byte() = Convert.FromBase64String(inputText)
    Dim secretKey As New Rfc2898DeriveBytes(EncryptionKey, SALT)

    Using decryptor As ICryptoTransform = rijndaelCipher.CreateDecryptor(secretKey.GetBytes(32), secretKey.GetBytes(16))
        Using memoryStream As New MemoryStream(encryptedData)
            Using cryptoStream As New CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)
                Dim plainText As Byte() = New Byte(encryptedData.Length - 1) {}
                Dim decryptedCount As Integer = cryptoStream.Read(plainText, 0, plainText.Length)
                Return Encoding.Unicode.GetString(plainText, 0, decryptedCount)
            End Using
        End Using
    End Using
End Function
Was it helpful?

Solution

I tested the code in your post and it seems to work correctly (I changed it to return the Base64 encoded data directly, rather than concatenating it to the QuestionMark and ParameterName), and Decrypt(Encrypt(New String("x"C, 800))) worked fine.

This suggests that something is going on between your encrypting the data and subsequently decrypting it. The fact that you're concatenating it to QuestionMark and ParameterName suggests that you are perhaps putting it in a URL? If so there is likely a maximum length on the parameter data which is resulting in truncation of the ciphertext causing the error you're seeing when attempting to decrypt.

After Base64 encryption (which results in a 4/3 expansion of the output) 751 bytes of plaintext puts you just under 1024 bytes of encrypted data. However 752 bytes results in an additional block (16 bytes) of output, which after Base64 encoding results in 1024 bytes. It seems no coincidence that you're having problems at exactly 1KB of output.

It's probably also worth mentioning that your method for generating both the key and IV are potentially insecure - it appears that you are using a fixed salt when deriving the key bytes from the password which, depending on how this is being used could reduce security. The second problem is that you are also deriving the IV from the password. The IV should be random data, unrelated to the key being used, and a different IV should be used for every encryption. This ensures that repeated encryption of the same message with the same key still results in distinct ciphertext. The random IV can be transmitted (unencrypted) along with the ciphertext and extracted for use in the decryption process.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top