vb.net AES解密返回“数据不完整块”

时间:2015-06-15 12:40:08

标签: vb.net encryption cryptography aes

我知道这个问题上的另一个主题(AES decryption error " The input data is not a complete block." Error vb.net),但是我要么没有正确地实现那里提供的解决方案,要么那些关于我这个问题的特定变体的内容没有涵盖解决方案。无论如何,我从以下代码中得到了不完整的块错误

Private GD As System.Security.Cryptography.Aes = System.Security.Cryptography.Aes.Create
Private PDB As New System.Security.Cryptography.Rfc2898DeriveBytes(EK, New Byte() {&H49, &H76, &H61, &H6E, &H20, &H4D, &H65, &H64, &H76, &H65, &H64, &H65, &H76})

Public Function Decrypt(ByVal val As String) As String
    Dim ret As String = Nothing
    Dim TTB As New System.Text.UTF8Encoding

    Try
        Dim input() As Byte = TTB.GetBytes(val)

        Using ms As New System.IO.MemoryStream(input)
            Using cs As New System.Security.Cryptography.CryptoStream(ms, GD.CreateDecryptor(PDB.GetBytes(32), PDB.GetBytes(16)), Security.Cryptography.CryptoStreamMode.Read)
                Using sr As New System.IO.StreamReader(cs)
                    ret = sr.ReadToEnd()
                End Using
            End Using
        End Using

        input = nothing
    Catch ex As Exception
        EL.AddErr("Encountered an error while decrypting the provided text for " & FName & ". Error Details: " & ex.Message, path)
    End Try

    Return ret
End Function

EK是我的钥匙,我不会包括在内。它只是一个字符串,没什么特别的。

我已经根据MSDN网站上的指导,DreamInCode等尝试了其他几种方法来解密。没有工作,但它们都有不同的问题(通常返回一个空白字符串)。看到这个版本的代码与我的加密代码密切相关,我想坚持下去(至少尽可能接近我的功能代码)。

1 个答案:

答案 0 :(得分:1)

尽管有所有评论,我仍然不了解你的意图。因此,下面的示例代码可能无法提供您确切想要的内容,但至少应该了解如何使用加密函数。特别是,与您的方法最显着的区别在于加密密钥和初始化向量是针对所有消息计算的,而不是每次都重新评估,因为后者容易出现同步错误 - 例如当您重用单个加密对象时与多方通信,或者在传输时丢失某些消息。

Public Shared Sub Test()

    ' Note: You should not actually hard-code any sensitive information in your source files, ever!
    Dim sKeyPreimage As String = "MySuperPassword"
    Dim oMyCrypto As New MyCrypto(sKeyPreimage)

    Dim sPlaintext As String = "My super secret data"
    Dim sEncrypted As String = oMyCrypto.EncryptText(sPlaintext)
    Dim sDecrypted As String = oMyCrypto.DecryptText(sEncrypted)

    Console.Out.WriteLine("Plaintext: {0}", sPlaintext) ' "My super secret data"
    Console.Out.WriteLine("Encrypted: {0}", sEncrypted) ' "72062997872DC4B4D1BCBF48D5D30DF0D498B20630CAFA28D584CCC3030FC5F1"
    Console.Out.WriteLine("Decrypted: {0}", sDecrypted) ' "My super secret data"

End Sub

Public Class MyCrypto

    Private Shared TextEncoding As Text.Encoding = Text.Encoding.UTF8

    Private CipherEngine As System.Security.Cryptography.SymmetricAlgorithm

    ' Note: Unlike in the question, same key and IV are reused for all messages.
    Private CipherKey() As Byte
    Private CipherIV() As Byte

    Public Sub New(ByVal sKeyPreimage As String)

        Dim abKeyPreimage() As Byte = TextEncoding.GetBytes(sKeyPreimage)
        Dim abKeySalt() As Byte = TextEncoding.GetBytes("Ivan Medvedev")

        Const KeyDerivationRounds As Integer = 1 << 12
        Dim oKeyDerivationEngine As New System.Security.Cryptography.Rfc2898DeriveBytes(abKeyPreimage, abKeySalt, KeyDerivationRounds)

        Me.CipherEngine = System.Security.Cryptography.Aes.Create()
        Me.CipherEngine.Padding = Security.Cryptography.PaddingMode.PKCS7
        Me.CipherKey = oKeyDerivationEngine.GetBytes(Me.CipherEngine.KeySize >> 3)
        Me.CipherIV = oKeyDerivationEngine.GetBytes(Me.CipherEngine.BlockSize >> 3)

    End Sub

    Public Function Encrypt(ByVal abPlaintext() As Byte) As Byte()

        Dim abCiphertext() As Byte

        Using hStreamSource As New System.IO.MemoryStream(abPlaintext),
                hStreamCipher As New System.Security.Cryptography.CryptoStream(
                    hStreamSource,
                    Me.CipherEngine.CreateEncryptor(Me.CipherKey, Me.CipherIV),
                    Security.Cryptography.CryptoStreamMode.Read),
                hStreamTarget As New System.IO.MemoryStream

            hStreamCipher.CopyTo(hStreamTarget)
            abCiphertext = hStreamTarget.ToArray()

        End Using

        Return abCiphertext
    End Function

    Public Function Decrypt(ByVal abCiphertext() As Byte) As Byte()

        Dim abPlaintext() As Byte

        Using hStreamSource As New System.IO.MemoryStream(abCiphertext),
                hStreamCipher As New System.Security.Cryptography.CryptoStream(
                    hStreamSource,
                    Me.CipherEngine.CreateDecryptor(Me.CipherKey, Me.CipherIV),
                    Security.Cryptography.CryptoStreamMode.Read),
                hStreamTarget As New System.IO.MemoryStream

            hStreamCipher.CopyTo(hStreamTarget)
            abPlaintext = hStreamTarget.ToArray()

        End Using

        Return abPlaintext
    End Function

    Public Function EncryptText(ByVal sPlaintext As String) As String
        Dim abPlaintext() As Byte = TextEncoding.GetBytes(sPlaintext)
        Dim abCiphertext() As Byte = Me.Encrypt(abPlaintext)
        Dim sCiphertext As String = Hex.Format(abCiphertext)
        Return sCiphertext
    End Function

    Public Function DecryptText(ByVal sCiphertext As String) As String
        Dim abCiphertext() As Byte = Hex.Parse(sCiphertext)
        Dim abPlaintext() As Byte = Me.Decrypt(abCiphertext)
        Dim sPlaintext As String = TextEncoding.GetChars(abPlaintext)
        Return sPlaintext
    End Function

End Class

Public Class Hex

    Public Shared Function Format(ByVal abValue() As Byte) As String
        Dim asChars(0 To abValue.Length * 2 - 1) As Char
        Dim ndxChar As Integer = 0
        For ndxByte As Integer = 0 To abValue.Length - 1
            Dim bNibbleHi As Byte = abValue(ndxByte) >> 4, bNibbleLo As Byte = CByte(abValue(ndxByte) And &HFUS)
            asChars(ndxChar) = Convert.ToChar(If(bNibbleHi <= 9, &H30US + bNibbleHi, &H37US + bNibbleHi)) : ndxChar += 1
            asChars(ndxChar) = Convert.ToChar(If(bNibbleLo <= 9, &H30US + bNibbleLo, &H37US + bNibbleLo)) : ndxChar += 1
        Next
        Return New String(asChars)
    End Function

    Public Shared Function Parse(ByVal sValue As String) As Byte()

        If String.IsNullOrEmpty(sValue) Then Return New Byte() {}
        If (sValue.Length Mod 2) > 0 Then Return Nothing

        Dim ndxText As Integer = 0
        Dim ndxByteMax As Integer = (sValue.Length \ 2) - 1
        Dim abValue(0 To ndxByteMax) As Byte

        Try
            For ndxByte As Integer = 0 To ndxByteMax
                abValue(ndxByte) = Convert.ToByte(sValue.Substring(ndxText, 2), 16)
                ndxText += 2
            Next
        Catch ex As Exception
            Return Nothing
        End Try

        Return abValue
    End Function

End Class

请再次注意,这只是一个例子。我不支持此处显示的任何保护技术,特别是因为您的任务仍然未知。上面的代码简单地说明了语法和语义 - 而不是如何正确地执行它。