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

时间:2015-03-03 11:49:37

标签: vb.net encryption cryptography aes

我一直得到这个"输入数据不是一个完整的块。"解密时出错。该函数成功加密纯文本并将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

3 个答案:

答案 0 :(得分:2)

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

示例代码:

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

答案 1 :(得分:0)

在使用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 :(得分:0)

您的代码存在多个问题。

在加密功能中:

  1. 错误的构造函数用于MemoryStream,因此它以固定大小创建,无法通过将来的填充进行扩展。您应该使用New MemoryStream(datain.Length)代替。
  2. 发出第一个memorystream.Close(),然后请求memorystream.ToArray()的内容,但没有任何明确的cstream.Close()调用:这样最后一个块,包括填充,实际上并没有被写入memorystream。在提取cstream.Close()数据之前,您应该致电memorystream
  3. 在关闭AesCryptoServiceProviderCryptoStream之前释放MemoryStream资源是非常不合逻辑的,尽管不是禁止的。
  4. 在解密功能中:

    1. 在不考虑填充的情况下,将高估decrypteddata的数据量。您应该根据cryptostream.Read(…)返回的实际值缩小此数组。
    2. 与上述过早AES.Clear()相同的问题。
    3. 虽然加密函数需要文本输入,但解密函数将其结果作为Base64编码的二进制数据返回。你的意思可能是Return Encoding.UTF8.GetString(decrypteddata.ToArray())
    4. 修复这些问题后,我可以毫无错误地运行您的程序。