2013-12-19 81 views
1

解密字符串時出現以下異常,但僅在原始字符串(加密前)> 751個字符時出現。它沒有任何問題加密。我怎樣才能避免這個問題?當字符串> 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 

回答

2

我在您的文章測試的代碼,它似乎正常工作(我改變了它的Base64編碼的數據直接返回,而不是將其串聯到QuestionMarkParameterName)和Decrypt(Encrypt(New String("x"C, 800)))工作正常。

這表明在加密數據和隨後解密數據之間會發生一些事情。您將它連接到QuestionMarkParameterName這一事實表明您可能將其放入URL中?如果是這樣,參數數據可能會有最大長度,導致密文截斷導致您在嘗試解密時看到的錯誤。

經過Base64加密(導致輸出的4/3擴展)後,751字節的明文將您置於1024字節的加密數據之下。然而,752個字節會產生一個額外的輸出塊(16個字節),在Base64編碼後產生1024個字節。在完全1KB的輸出中出現問題似乎並非巧合。

它也許值得一提的是,你的方法生成的密鑰和IV可能是不安全的 - 看來你是從密碼中導出密鑰字節時使用固定鹽,這取決於如何使用它降低安全性。第二個問題是你也從密碼中獲得IV。 IV應該是隨機數據,與正在使用的密鑰無關,每個加密應該使用不同的IV。這確保了使用相同密鑰對相同消息的重複加密仍然導致不同的密文。隨機IV可以與密文一起傳輸(未加密)並提取用於解密過程。

+0

謝謝,你是正確的,關於它可能不安全。但是,我不知道如何實現你的建議 - 哪一部分是初始化向量,我怎樣才能每次更改鹽而不傳輸它,或者可以傳輸IV和Salt以及加密刺痛嗎? –

+1

@MrShoubs IV是'rijndaelCipher.CreateEncryptor/Decryptor()'的第二個參數(當前使用的是'secretKey.GetBytes(16)')。我會建議使用這些方法的無參數版本,並且在調用'CreateEncryptor()'之前指定'rijndaelCipher.Key = secretKey.GetBytes(32)'和'rijndaelCipher.GenerateIV()'來設置密鑰/ IV,需要將「rijndaelCipher.IV」的值與密文一起傳送。對於解密,設置密鑰的方式與加密相同,但在調用CreateDecryptor()之前將'rijndaelCipher.IV'設置爲傳輸的IV值。 – Iridium

+0

謝謝,我已經實現了,但鹽怎麼樣?我不認爲我應該傳送這個? –

相關問題