【问题标题】:vb.net AES decryption returns "data is incomplete block"vb.net AES 解密返回“数据不完整块”
【发布时间】:2015-06-16 20:13:30
【问题描述】:

我知道有关此问题的其他线程 (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 等上的指导,我尝试了其他几种解密方法。没有一个有效,但它们都有不同的问题(通常返回一个空白字符串)。鉴于此版本的代码与我的加密代码非常相似,我想坚持使用它(或者至少在仍然具有功能代码的情况下尽可能接近)。

【问题讨论】:

  • 如果您的val 包含十六进制编码的加密结果,那么我将首先将TTB.GetBytes(val) 替换为适当的StringToByteArray() 函数(例如,查看this answer)。如果仅此一项没有帮助,请将您的 cryptic GDPDB 更改为一些更详细的标识符,因为阅读您的代码并因此很难诊断它。
  • val 是要加密的原始字符串。 GD 和 PDB 的定义包含在函数本身之前。如果有帮助,我可以将它们在线移动,但不会有新信息。
  • 你的意思是“被解密”?无论如何,我不明白:valret 都是文本字符串,但您将它们视为原始字节 - 您首先采用 val 的 UTF-8 表示,最后推送 CryptoStream 的输出(纯二进制)到 StreamReader,然后到 ret。这没有任何意义。特别是,您的 CryptoStream 期望它的输入被正确填充(默认为 PKCS7),input 可能不满足。
  • 'val' 被视为字符串,因此通过TTB.GetBytes(val) 转换为其字节(相信来自CodeProject)。如果StringToByteArray() 是更好的选择,我会切换。 ret 也应该像字符串一样对待。如果 ret = sr.ReadToEnd() 使用 ret 作为 byte(),那不是本意(来自 MSDN msdn.microsoft.com/en-us/library/…)。该功能的整个架构是该文章的抄本。在这一点上,您能否提供一个很好的例子让我开始,因为我没有好的参考资料?
  • 问题是很难理解你到底想完成什么:Encrypt() 函数的输入是什么(在你的例子中省略了),它的输出是什么; Decrypt() 函数的输入是什么(应该与 Encrypt 的输出相同,但谁知道呢?)以及它预期返回的内容是什么?我的意思是你应该提供你测试的确切数据,即。 e. val 的值和您期望的值 ret 应该在末尾。

标签: vb.net encryption cryptography aes


【解决方案1】:

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

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

再次请注意,这只是一个示例。我不支持此处显示的任何类型的保护技术,尤其是因为您的任务仍然未知。上面的代码只是说明了语法和语义——而不是如何正确地做到这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多