AES 解密错误“输入数据不是一个完整的块。” 错误 vb.net

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28831084/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 18:50:59  来源:igfitidea点击:

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

vb.netencryptioncryptographyaes

提问by user3198101

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

我不断收到“输入数据不是一个完整的块”。解密时出错。该函数成功加密纯文本并将 IV 放入文本框中。我正在使用加密数据和文本中的 IV 来解密原始数据,但我不断收到错误消息。我不知道我哪里出错了。这是我的代码

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

回答by ZagNut

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

除非您要手动确保输入是 BlockSize 的倍数(以位为单位),否则请确保指定填充:

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;
}

回答by Crowcoder

I had the same problem until I implemented with ICryptoTransform:

在使用 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)

回答by Anton Samsonov

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 memorystreamdata.
  3. It is quite illogical, although not forbidden, to release the AesCryptoServiceProviderresources before closing both CryptoStreamand MemoryStream.
  1. for 使用了错误的构造函数MemoryStream,因此它以固定大小创建,并且无法通过未来的填充进行扩展。你应该New MemoryStream(datain.Length)改用。
  2. 首先memorystream.Close()发出,然后memorystream.ToArray()请求的内容,但没有任何显式cstream.Close()调用:这样最后的块,包括填充,实际上不会写入memorystream. 您应该cstream.Close()在提取memorystream数据之前调用。
  3. AesCryptoServiceProvider在关闭CryptoStream和之前释放资源是非常不合逻辑的,尽管不是禁止的MemoryStream

In decryption function:

在解密函数中:

  1. The amount of data that will get to decrypteddatais 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.
  1. decrypteddata不考虑填充的情况下高估了将要到达的数据量。您应该根据 返回的实际值缩小此数组cryptostream.Read(…)
  2. AES.Clear()上述早产相同的问题。
  3. 虽然加密函数需要文本输入,但解密函数将其结果作为 Base64 编码的二进制数据返回。你可能的意思是Return Encoding.UTF8.GetString(decrypteddata.ToArray())

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

解决这些问题后,我可以毫无错误地运行您的程序。