Visual Basic Unicode编码错误:某些字符编码不正确

时间:2017-04-15 06:52:03

标签: vb.net encryption unicode character-encoding

因此,我在Visual Basic中创建一个加密的消息传递程序,这是背景故事。当发送消息时,它被编码到Base 64中(在加密并变成字节数组之后),然后使用Unicode将Base 64表示为字符串(实际上没有任何数据被更改),添加了一些填充以区分消息类型,然后字符串被发送到另一台计算机(我检查过,发送的数据与收到的数据完全匹配,因此没有问题)。收到后,base64 / Unicode字符串将变回常规的Unicode字符串(此数据与发送的数据完全匹配,因此没有问题),然后数据被解密,这是问题开始时,它会成功解密并显示,它大部分时间都有效但有时如果你发送一个特定的字符序列,接收端会以不同的方式显示它(就像它们将是亚洲字符一样)。现在举一些例子:

这是加密后的数据,转换为base 64,并添加了填充:

{/} C/1rcE9CwYDEnoaxNVT2Xme/pky6yDRGo3lcG12G/h8= {\}

这是经过重新编码和重新编码的数据:

{/} C/1rcE9CwYDEnoaxNVT2Xme/pky6yDRGo3lcG12G/h8= {\}

正如您所看到的,没有错误,这是加密数据(加密字符串" EncryptionTest"):

Encrypt: EncryptionTest with 0K2V4Y0/aXrnGpcVP1d2JEGKAZDWZWuffXA1Iv0gFbc= got ﴋ火䉏胁黄놆吵延뽧䲦좺䘴禣᭜虝῾

这是收到和解密的数据:

Decrypt: ﴋ火䉏胁黄놆吵延뽧䲦좺䘴禣᭜虝῾ with 0K2V4Y0/aXrnGpcVP1d2JEGKAZDWZWuffXA1Iv0gFbc= got EncryptionTest

它工作得很好,但是如果我发送字符串" Wonderful"这就是:

Encrypt: Wonderful with 0K2V4Y0/aXrnGpcVP1d2JEGKAZDWZWuffXA1Iv0gFbc= got 폮斚䢹뱊袗櫮㓟翔ǔ劇辑頭뷳ﭤ�

Decrypt: 폮斚䢹뱊袗櫮㓟翔ǔ劇辑頭뷳ﭤ� with 0K2V4Y0/aXrnGpcVP1d2JEGKAZDWZWuffXA1Iv0gFbc= got Wonderf牏匢否喏幙‥

出了点问题,但如果我删除" l"在#34; Wondeful":

结束时
Encrypt: Wonderfu with 0K2V4Y0/aXrnGpcVP1d2JEGKAZDWZWuffXA1Iv0gFbc= got 폮斚䢹뱊袗櫮㓟팾甎ᑁᗺ寑핕杷
Decrypt: 폮斚䢹뱊袗櫮㓟팾甎ᑁᗺ寑핕杷 with 0K2V4Y0/aXrnGpcVP1d2JEGKAZDWZWuffXA1Iv0gFbc= got Wonderfu

再次一切正常。在解码来自base64的消息和显示它之间发生错误,所以这必须意味着解密功能是责任,这是我的加密和解密功能,请帮助。

    Function EncryptAESString(data As String, key As String)
    Dim keybytes() As Byte = Convert.FromBase64String(key)
    Dim ivbytes() = Convert.FromBase64String(HashString("TestIV2", "MDA5"))
    Dim encrypted() As Byte
    Using aesAlg As Aes = Aes.Create()
        aesAlg.Padding = PaddingMode.Zeros
        aesAlg.Key = keybytes
        aesAlg.IV = ivbytes
        Dim encryptor As ICryptoTransform = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV)
        Using msEncrypt As New MemoryStream()
            Using csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
                Using swEncrypt As New StreamWriter(csEncrypt, uni)
                    swEncrypt.Write(data)
                End Using
                encrypted = msEncrypt.ToArray()
            End Using
        End Using
    End Using
    DebugPrint("Encrypt: " + data + " with " + key + " got " + uni.GetString(encrypted))
    Return uni.GetString(encrypted)
End Function

Function DecryptAESString(data As String, key As String)
    Dim databyte() As Byte = uni.GetBytes(data)
    Dim keybytes() As Byte = Convert.FromBase64String(key)
    Dim ivbytes() = Convert.FromBase64String(HashString("TestIV2", "MDA5"))
    Dim plaintext As String = Nothing
    Using aesAlg As Aes = Aes.Create()
        aesAlg.Padding = PaddingMode.Zeros
        aesAlg.Key = keybytes
        aesAlg.IV = ivbytes
        Dim decryptor As ICryptoTransform = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV)
        Using msDecrypt As New MemoryStream(databyte)
            Using csDecrypt As New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)
                Using srDecrypt As New StreamReader(csDecrypt, uni)
                    plaintext = srDecrypt.ReadToEnd()
                End Using
            End Using
        End Using
    End Using
    databyte = Nothing
    keybytes = Nothing
    ivbytes = Nothing
    DebugPrint("Decrypt: " + data + " with " + key + " got " + plaintext)
    Return plaintext
End Function

1 个答案:

答案 0 :(得分:0)

您需要将encrypted = msEncrypt.ToArray()移到Using csEncrypt之外,以便写入最后一个块。这基本上意味着您在应用填充之前当前正在生成密文字节,并且写入了明文的最后一个块。

Using msEncrypt As New MemoryStream()
    Using csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
        Using swEncrypt As New StreamWriter(csEncrypt, uni)
            swEncrypt.Write(data)
        End Using
    End Using
    encrypted = msEncrypt.ToArray()
End Using

你的另一个问题是字符串不是二进制数据的容器。某些字节可能会丢失。如果要打印字符串,则需要使用Hex或Base64之类的东西。

在加密过程中,您应该使用Return Convert.ToBase64String(encrypted),在解密过程中,您需要使用相反的函数Dim databyte() As Byte = Convert.FromBase64String(data)