问题
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:
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;
}
回答2:
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)
回答3:
There are multiple issues with your code.
In encryption function:
- Wrong constructor is used for
MemoryStream
, so it gets created with fixed size and cannot be expanded by future padding. You should useNew MemoryStream(datain.Length)
instead. - First
memorystream.Close()
is issued and then the contents ofmemorystream.ToArray()
is requested, — but without any explicitcstream.Close()
invocation: that way the last blocks, including padding, are not actually written tomemorystream
. You should callcstream.Close()
before extractingmemorystream
data. - It is quite illogical, although not forbidden, to release the
AesCryptoServiceProvider
resources before closing bothCryptoStream
andMemoryStream
.
In decryption function:
- 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 bycryptostream.Read(…)
. - Same issue with premature
AES.Clear()
as above. - 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.
来源:https://stackoverflow.com/questions/28831084/aes-decryption-error-the-input-data-is-not-a-complete-block-error-vb-net