【问题标题】:VB.NET Encrypted string not same as original when decrypted, some text missingVB.NET 解密时加密字符串与原始字符串不同,缺少一些文本
【发布时间】:2015-10-21 03:27:55
【问题描述】:

我正在做一些服务器/客户端编码,我需要加密数据。

我有以下加密和解密类 - 在网上找到了一些代码并对其进行了修改以供我使用。

Secure.vb

Imports System.Security.Cryptography
Imports System.IO
Imports System.Text

Public Class Secure
#Region "Encryption Salt"
Private strSalt = "MyTest"
#End Region

#Region "Enum"
Public Enum CryptoAction
    Encrypt = 1
    Decrypt = 2
End Enum
#End Region

Public Sub New()

End Sub

Private Function CreateKey() As Byte()
    Dim strpassword As String = strSalt

    Dim chrData() As Char = strpassword.ToCharArray
    Dim intLength As Integer = chrData.GetUpperBound(0)
    Dim bytDataToHash(intLength) As Byte

    For i As Integer = 0 To chrData.GetUpperBound(0)
        bytDataToHash(i) = CByte(Asc(chrData(i)))
    Next

    Dim SHA512 As New System.Security.Cryptography.SHA512Managed
    Dim bytResult As Byte() = SHA512.ComputeHash(bytDataToHash)
    Dim bytKey(31) As Byte

    For i As Integer = 0 To 31
        bytKey(i) = bytResult(i)
    Next

    Return bytKey
End Function

Private Function CreateIV() As Byte()
    Dim strPassword As String = strSalt

    Dim chrData() As Char = strPassword.ToCharArray
    Dim intLength As Integer = chrData.GetUpperBound(0)
    Dim bytDataToHash(intLength) As Byte

    For i As Integer = 0 To chrData.GetUpperBound(0)
        bytDataToHash(i) = CByte(Asc(chrData(i)))
    Next

    Dim SHA512 As New System.Security.Cryptography.SHA512Managed
    Dim bytResult As Byte() = SHA512.ComputeHash(bytDataToHash)
    Dim bytIV(15) As Byte

    For i As Integer = 32 To 47
        bytIV(i - 32) = bytResult(i)
    Next

    Return bytIV 'Return the IV.
End Function

Public Function Process(ByVal encString As String, ByVal Direction As CryptoAction, Optional ByVal Encrypted As Boolean = False) As String
    Try
        Dim encBytes() As Byte = Nothing
        If Direction = CryptoAction.Decrypt Then
            encBytes = Convert.FromBase64String(encString)
        Else
            encBytes = New System.Text.UnicodeEncoding().GetBytes(encString)
        End If

        Dim bytBuffer(4096) As Byte
        Dim lngBytesProcessed As Long = 0
        Dim lngStringLength As Long = encBytes.Length
        Dim intBytesInCurrentBlock As Integer = 0
        Dim csCryptoStream As CryptoStream = Nothing
        Dim cspRijndael As New System.Security.Cryptography.RijndaelManaged
        Dim strOutput As String = Nothing
        Dim bytKey() As Byte = CreateKey()
        Dim bytIV() As Byte = CreateIV()
        Dim iStream As New MemoryStream(encBytes)
        Dim oStream As New MemoryStream

        cspRijndael.Padding = PaddingMode.Zeros

        Select Case Direction
            Case CryptoAction.Encrypt
                csCryptoStream = New CryptoStream(oStream, _
                                                  cspRijndael.CreateEncryptor(bytKey, bytIV), _
                                                  CryptoStreamMode.Write)

            Case CryptoAction.Decrypt
                csCryptoStream = New CryptoStream(oStream, _
                cspRijndael.CreateDecryptor(bytKey, bytIV), _
                CryptoStreamMode.Write)
        End Select

        While lngBytesProcessed < lngStringLength
            intBytesInCurrentBlock = iStream.Read(bytBuffer, 0, 4096)
            csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock)
            lngBytesProcessed = lngBytesProcessed + _
                                    CLng(intBytesInCurrentBlock)
        End While

        If Direction = CryptoAction.Decrypt Then
            strOutput = System.Text.Encoding.Unicode.GetString(oStream.ToArray)
        Else
            strOutput = Convert.ToBase64String(oStream.ToArray)
        End If

        csCryptoStream.Close()
        iStream.Close()
        oStream.Close()

        Return strOutput
    Catch ex As Exception
        Return ex.Message
    End Try
End Function
End Class

那么当做以下事情时:

Sub Main()

    Dim TestString As String = "<DebugResponse text=""Received Test""/>"

    Console.WriteLine("Original string: " & vbCrLf & TestString & vbCrLf)

    Dim Encrypter As New Secure

    Dim encrypted As String = Encrypter.Process(TestString, Secure.CryptoAction.Encrypt)

    Console.WriteLine("Encrypted string: " & vbCrLf & encrypted & vbCrLf)

    Dim decrypted As String = Encrypter.Process(encrypted, Secure.CryptoAction.Decrypt)

    Console.WriteLine("Decrypted string: " & vbCrLf & decrypted)

    Console.ReadLine()

End Sub

解密字符串的结果会返回

<DebugResponse text="Received Te

为什么? 我看不到错误在哪里:(

【问题讨论】:

  • 有趣。我可以看到它只是 16 字节的完整块,但我不知道为什么。感觉就像流没有被正确冲洗但冲洗似乎没有帮助......

标签: vb.net encryption cryptography


【解决方案1】:

问题是我在 cmets 中怀疑流没有被正确刷新。写完之后你需要打电话给[FlushFinalBlock][1]

文档对此的原因不是很清楚,但我想这是因为加密是在 16 字节块上工作的,它显然无法加密一个块,直到它拥有所有数据。虽然它有一个部分块(就像您完成编写时的情况一样),但您需要调用 FlushFinalBlock 告诉它该部分块实际上是完整数据。

因此,总而言之,将 csCryptoStream.FlushFinalBlock 放在写入流的 while 循环之后。

【讨论】:

  • 谢谢 :) 昨天确实给我带来了一些麻烦 - 现在在 while 循环之后添加 csCryptoStream.FlushFinalBlock 后它可以工作了 :)
  • 优秀。很高兴有帮助。 :)
猜你喜欢
  • 2014-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-30
  • 1970-01-01
  • 2012-07-01
  • 2018-08-26
相关资源
最近更新 更多