当字符串>“要解密的数据长度无效” 751个字符

时间:2013-12-19 11:46:35

标签: .net encryption cryptography .net-2.0 rijndaelmanaged

我在解密字符串时遇到以下异常,但只有在原始字符串(加密前)为>时才会出现这种情况。 751个字符。加密没有任何问题。我该如何避免这个问题?

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: 

我花了一段时间看这个,因为它似乎是关于堆栈溢出的一个常见问题,但是我认为它们中的任何一个都不能解决我的问题,如果我错过了某些内容,我会道歉。

bug report here,但特殊字符似乎不是问题。

我使用的方法是:

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

1 个答案:

答案 0 :(得分:2)

我测试了帖子中的代码,它似乎工作正常(我将其更改为直接返回Base64编码数据,而不是将其连接到QuestionMarkParameterName)和{{ 1}}工作正常。

这表明在加密数据和随后解密数据之间会发生一些事情。您将其与Decrypt(Encrypt(New String("x"C, 800)))QuestionMark连接的事实表明您可能将其放入网址中?如果是这样,参数数据上可能存在最大长度,导致密文截断,导致您在尝试解密时看到的错误。

在Base64加密后(导致输出的4/3扩展),751字节的明文使您只需要1024字节的加密数据。但是,752字节会产生一个额外的块(16字节)输出,在Base64编码后产生1024字节。在1KB的输出中遇到问题似乎并非巧合。

可能还值得一提的是,生成密钥和IV的方法可能不安全 - 从密码中导出密钥字节时,您似乎使用固定的盐,这取决于使用密码的方式可能会减少安全。第二个问题是您还从密码中导出IV。 IV应该是随机数据,与使用的密钥无关,每个加密应使用不同的IV。这确保了使用相同密钥对相同消息的重复加密仍然导致不同的密文。随机IV可以与密文一起传输(未加密)并提取出来用于解密过程。