AES 解密错误 " The input data is not a complete block." 错误 vb.net



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

除非您要手动确保您的输入是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;
}

在实现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)

您的代码存在多个问题。

在加密功能中:

  1. MemoryStream使用了错误的构造函数,因此它是以固定大小创建的,不能通过未来的填充进行扩展。您应该使用New MemoryStream(datain.Length)
  2. 首先发出memorystream.Close(),然后请求memorystream.ToArray()的内容,但没有任何明确的cstream.Close()调用:这样,包括填充在内的最后块实际上就不会写入memorystream。在提取memorystream数据之前,您应该调用cstream.Close()
  3. 在关闭CryptoStreamMemoryStream之前释放AesCryptoServiceProvider资源是非常不合逻辑的,尽管这不是禁止的

在解密功能中:

  1. 在不考虑填充的情况下,将到达decrypteddata的数据量被高估了。您应该根据cryptostream.Read(…)返回的实际值来收缩此数组
  2. 与上述过早AES.Clear()的问题相同
  3. 当加密函数期望文本输入时,解密函数将其结果作为Base64编码的二进制数据返回。你可能是指Return Encoding.UTF8.GetString(decrypteddata.ToArray())

在修复了这些问题之后,我可以运行您的程序而不会出现任何错误。

相关内容

最新更新