我尝试使用AesCryptoServiceProvider来加密数据,并通过字节数组传递。
运行此代码,您将看到默认数据长度为32 * 8bit,这是我设置的,运行完美。
然后,您可以将长度设置为您想要的任何其他长度。例如,33,表示数据的总长度(33 * 8bit)不是128bit的整数倍。
所以在AES之前,它需要填充到48 * 8bit。
然而, .Net丢弃了最后一个不完整的块。我认为这就是我在解密时遇到异常的原因。
嗯,当我处理AesCryptoServiceProvider类时有什么不对吗? 或者这是一个需要避免的问题? 我该怎么做才能解决这个问题并使用AES来加密数据?
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography
Module Module1
Private intKeySize As Integer = 256
Private Const c_intBlockSize As Integer = 128 'AES ONLY use 128bit block
Private pdmPaddingMode As PaddingMode = PaddingMode.PKCS7
Private cpmCipherMode As CipherMode = CipherMode.CFB
Private Const c_strDefault As String = "D49303DCDF5AAE2B128001EA48D19D04"
Sub Main()
prpPaddingMode = PaddingMode.ANSIX923 'you can set differen padding to test
Dim setlength As Integer = 32
tgA:
Dim objRandom As New System.Random(Now.Millisecond)
Dim inp(setlength - 1) As Byte
For i As Integer = 0 To inp.GetUpperBound(0) 'Random data generated as test data
inp(i) = CByte(objRandom.Next(0, 255))
Next i
BytesShow(inp, "Input")
Dim outp() As Byte = EncryptString_Aes(inp, NewKey(c_strDefault), Hex2Byte(c_strDefault)) 'I use c_strDefault as the IV and Key
BytesShow(outp, "Encrypted")
'The two lines below meet an exception probably becuase the final block lost in encryption
'Dim dep() As Byte = DecryptString_Aes(outp, NewKey(c_strDefault), Hex2Byte(c_strDefault))
'BytesShow(dep, "Decrypted")
Console.WriteLine("===========" & vbCrLf & "Finished, please press any key to continue:")
Console.ReadKey()
Console.WriteLine("===========" & vbCrLf & "===========" & vbCrLf & "What's Next Test Data Length?")
setlength = CInt(Console.ReadLine())
GoTo tgA
End Sub
Public Function EncryptString_Aes(ByVal plainByte() As Byte, ByVal Key() As Byte, ByVal IV() As Byte) As Byte()
Dim encrypted As Byte()
Using aesAlg As New AesCryptoServiceProvider()
aesAlg.Mode = prpCipherMode
aesAlg.Padding = prpPaddingMode
aesAlg.BlockSize = prpBlockSize
aesAlg.Key = Key
If aesAlg.Mode <> CipherMode.ECB Then
aesAlg.IV = IV
End If
Dim encryptor As ICryptoTransform = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV)
Dim msEncrypt As New MemoryStream()
Using csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
'Using swEncrypt As New StreamWriter(csEncrypt, Encoding.UTF8)
' swEncrypt.Write(plainText)
'End Using
Debug.WriteLine(aesAlg.Mode.ToString)
Debug.WriteLine(aesAlg.Padding.ToString)
csEncrypt.Write(plainByte, 0, plainByte.Length)
encrypted = msEncrypt.ToArray()
End Using
End Using
Return encrypted
End Function
Public Function DecryptString_Aes(ByVal cipherByte() As Byte, ByVal Key() As Byte, ByVal IV() As Byte) As Byte()
Dim msOut As New MemoryStream()
Using aesAlg As New AesCryptoServiceProvider()
aesAlg.Mode = prpCipherMode
aesAlg.Padding = prpPaddingMode
aesAlg.BlockSize = prpBlockSize
aesAlg.Key = Key
If aesAlg.Mode <> CipherMode.ECB Then
aesAlg.IV = IV
End If
Dim decryptor As ICryptoTransform = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV)
Using msDecrypt As New MemoryStream(cipherByte)
Using csDecrypt As New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)
'Using srDecrypt As New StreamReader(csDecrypt, Encoding.UTF8)
' decrypted = srDecrypt.ReadToEnd()
'End Using
Debug.WriteLine(aesAlg.Mode.ToString)
Debug.WriteLine(aesAlg.Padding.ToString)
Dim bytBuffer(1023) As Byte
Dim intCount As Integer
Do
intCount = csDecrypt.Read(bytBuffer, 0, bytBuffer.Length)
msOut.Write(bytBuffer, 0, intCount)
Debug.WriteLine("intCount = " & intCount.ToString)
Loop While intCount > 0
End Using
End Using
'Dim msDecrypt As New MemoryStream()
'Using csEncrypt As New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write)
' 'Using swEncrypt As New StreamWriter(csDecrypt, Encoding.UTF8)
' ' swEncrypt.Write(plainText)
' 'End Using
' csEncrypt.Write(cipherByte, 0, cipherByte.Length)
' decrypted = msDecrypt.ToArray()
'End Using
End Using
Return msOut.ToArray()
End Function
Public Sub BytesShow(ByRef bytin() As Byte)
BytesShow(bytin, "ByteArray_Show_End")
End Sub
Public Sub BytesShow(ByRef bytin() As Byte, ByRef msg As String)
For i As Integer = 0 To bytin.GetUpperBound(0) '测试用的数据用随机数值
Select Case (i Mod 16)
Case 0
Console.Write(i.ToString.PadLeft(5) & "#) " & bytin(i).ToString("x2"))
Case 15
Console.WriteLine(" " & bytin(i).ToString("x2"))
Case Else
Console.Write(" " & bytin(i).ToString("x2"))
End Select
Next i
Console.WriteLine(" (#Total: " & (bytin.GetUpperBound(0) + 1).ToString & "#)" & vbCrLf & "===================" & msg)
End Sub
Public Function getSha512HashBytes(ByVal strInput As String) As Byte()
Dim bytData As Byte()
Using Sha512Hasher As New SHA512CryptoServiceProvider
bytData = Sha512Hasher.ComputeHash(Encoding.UTF8.GetBytes(strInput))
End Using
Return bytData
End Function
Public Function NewKey(ByVal StringKey As String) As Byte()
Dim objRfc2898 As New Rfc2898DeriveBytes(StringKey, getSha512HashBytes(StringKey), 1000)
Dim bytKey As Byte() = objRfc2898.GetBytes(CInt(prpKeySize / 8))
objRfc2898.Reset()
objRfc2898.Dispose()
Return bytKey
End Function
Public Function Hex2Byte(ByVal StringValue As String) As Byte()
Dim bytValue((StringValue.Length \ 2) - 1) As Byte
For i As Integer = 0 To ((StringValue.Length \ 2) - 1)
bytValue(i) = CByte("&H" & Microsoft.VisualBasic.Mid(StringValue, ((i * 2) + 1), 2))
Next i
Return bytValue
End Function
Friend Property prpKeySize() As Integer
Get
Return intKeySize
End Get
Set(value As Integer)
Select Case value
Case 128, 192, 256
intKeySize = value
Case Else
Throw New CryptographicException("The key size is not one of the KeySize values.")
End Select
End Set
End Property
Friend ReadOnly Property prpBlockSize As Integer
Get
Return c_intBlockSize
End Get
End Property
Friend Property prpPaddingMode As PaddingMode
Get
Return pdmPaddingMode
End Get
Set(value As PaddingMode)
Select Case value
Case PaddingMode.ANSIX923, PaddingMode.ISO10126, PaddingMode.PKCS7, PaddingMode.Zeros, PaddingMode.None
pdmPaddingMode = value
Case Else
Throw New CryptographicException("The padding mode is not one of the supported PaddingMode values.")
End Select
End Set
End Property
Friend Property prpCipherMode As CipherMode
Get
Return cpmCipherMode
End Get
Set(value As CipherMode)
Select Case value
Case CipherMode.CBC, CipherMode.CFB, CipherMode.ECB
cpmCipherMode = value
Case Else
Throw New CryptographicException("The cipher mode is not one of the supported CipherMode values.")
End Select
End Set
End Property
End Module
无论如何,感谢大家花时间阅读本文并帮助我解决问题。此致。
答案 0 :(得分:0)
确定。我发现了。
将数据写入csEncrypt(CryptoStream类)后,
csEncrypt.Write(plainByte, 0, plainByte.Length)
我们应该关闭流,让.Net知道&#34;全部,你已经获得了所有数据。&#34;
csEncrypt.Close()
然后,最后一个不完整的块被填充和加密。这时,我们可以阅读结果。
encrypted = msEncrypt.ToArray()
所以,总代码是这样的:
csEncrypt.Write(plainByte, 0, plainByte.Length)
csEncrypt.Close()
encrypted = msEncrypt.ToArray()