AES decryption error “ The input data is not a complete block.” Error vb.net

匿名 (未验证) 提交于 2019-12-03 02:41:02

问题:

I keep getting this "The input data is not a complete block." error while decrypting. The function successfully encrypts plain text and puts the IV in a textbox. I am using the encrypted data and the IV from text to decrypt the original data but I keep getting the error. I have no idea where I have gone wrong. Heres my code

Imports System.IO 'Import file I/O tools Imports System.Security.Cryptography 'Import encryption functionality Imports System.Text 'Import text based processing tools`   Public Class Form1     Private Function AESEncryption(ByVal clearText As String, ByVal key As String) As String         Dim salt As String = tbpassword.Text.Insert(tbpassword.Text.Length - 1, "7?1!")          Dim Md5 As New MD5CryptoServiceProvider()         Dim Encryptionkey As Byte() = Md5.ComputeHash(Encoding.UTF8.GetBytes(key & salt))            Dim AES As New AesCryptoServiceProvider         AES.Key = Encryptionkey         AES.Mode = CipherMode.CBC         tbIV.Text = Convert.ToBase64String(AES.IV)          Dim datain() As Byte = Encoding.UTF8.GetBytes(clearText)          Dim memorystream As New MemoryStream(datain)         Dim cstream As New CryptoStream(memorystream, AES.CreateEncryptor, CryptoStreamMode.Write)         cstream.Write(datain, 0, datain.Length)           AES.Clear()         memorystream.Close()          Return Convert.ToBase64String(memorystream.ToArray())     End Function     Private Function AESdecryption(ByVal encrypteddata As String, ByVal key As String) As String         Dim salt As String = tbpassword.Text.Insert(tbpassword.Text.Length - 1, "7?1!")          Dim Md5 As New MD5CryptoServiceProvider()         Dim Encryptionkey As Byte() = Md5.ComputeHash(Encoding.UTF8.GetBytes(key & salt)) 'uses password and salt to create a hash byte array          Dim EncryptionIn() As Byte = Convert.FromBase64String(encrypteddata)          Dim AES As New AesCryptoServiceProvider         AES.Key = Encryptionkey         AES.Mode = CipherMode.CBC         AES.IV = Convert.FromBase64String(tbIV.Text)          Dim ms As New MemoryStream(EncryptionIn)           Dim cryptostream As New CryptoStream(ms, AES.CreateDecryptor, CryptoStreamMode.Read)         Dim decrypteddata() As Byte         ReDim decrypteddata(EncryptionIn.Length - 1)         cryptostream.Read(decrypteddata, 0, decrypteddata.Length)           AES.Clear()         ms.Close()          Return Convert.ToBase64String(ms.ToArray)      End Function     Private Sub btnencrypt_Click(sender As Object, e As EventArgs) Handles btnencrypt.Click         tbencrypteddata.Text = AESEncryption(tbuserdata.Text, tbpassword.Text)        End Sub      Private Sub btndecrypt_Click(sender As Object, e As EventArgs) Handles Button1.Click         tbdecrypteddata.Text = AESdecryption(tbencrypteddata.Text, tbpassword.Text)     End Sub End Class 

回答1:

I had the same problem until I implemented with ICryptoTransform:

... Dim AES As New AesCryptoServiceProvider AES.Key = Encryptionkey AES.Mode = CipherMode.CBC AES.IV = Convert.FromBase64String(tbIV.Text)  Dim transformer As ICryptoTransform = AES.CreateDecryptor() dim trnsfrmBlock as Byte() = transformer.TransformFinalBlock(EncryptionIn, 0, EncryptionIn.Length)  Return Convert.ToBase64String(trnsfrmBlock) 


回答2:

There are multiple issues with your code.

In encryption function:

  1. Wrong constructor is used for MemoryStream, so it gets created with fixed size and cannot be expanded by future padding. You should use New MemoryStream(datain.Length) instead.
  2. First memorystream.Close() is issued and then the contents of memorystream.ToArray() is requested, ― but without any explicit cstream.Close() invocation: that way the last blocks, including padding, are not actually written to memorystream. You should call cstream.Close() before extracting memorystream data.
  3. It is quite illogical, although not forbidden, to release the AesCryptoServiceProvider resources before closing both CryptoStream and MemoryStream.

In decryption function:

  1. The amount of data that will get to decrypteddata is overestimated without taking padding into account. You should shrink this array based on the actual value returned by cryptostream.Read(…).
  2. Same issue with premature AES.Clear() as above.
  3. While the encryption function expects text input, the decryption function returns its result as a Base64-encoded binary data. You probably meant Return Encoding.UTF8.GetString(decrypteddata.ToArray()) instead.

After fixing those issues, I could run your program without any error.



回答3:

Unless you are going to manually make sure your input is in multiples of BlockSize (in bits), make sure to specify a padding:

Example code:

byte[] Process(byte[] bInput, bool decrypt = false) {     byte[] bOutput = null;      using (var c = System.Security.Cryptography.AesCryptoServiceProvider.Create())     {         c.BlockSize = 128;         c.IV = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf }; // blocksize / 8 = 16 long         c.KeySize = 256;         c.Key = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf }; // key = keysize / 8 = 32 bytes         c.Mode = System.Security.Cryptography.CipherMode.CBC;         c.Padding = System.Security.Cryptography.PaddingMode.PKCS7;         if (decrypt)         {             using (var t = c.CreateDecryptor())             {                 bOutput = t.TransformFinalBlock(bInput, 0, bInput.Length);             }         }         else         {             using (var t = c.CreateEncryptor())             {                 bOutput = t.TransformFinalBlock(bInput, 0, bInput.Length);             }         }     }      return bOutput; } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!