使用 Rjindael 解密文本文件
Decrypting a Text File Using Rjindael
我已经使用this guide将txtCode.Text
的值加密到一个文本文件中,然后隐藏 - 加密数据的值将用作数据库的密码,所以我需要读取这个值,解密它,然后将它传递到连接字符串中。
然而,在本指南中,解密是通过键入一个值,创建一个 bytKey
和 bytIV
,然后将 newl 键入的字符串的加密结果与中的值进行比较来完成的文本文件。显然我不能在每次需要打开数据库的时候都要求用户输入密码,那么如何使用这段代码实现解密呢?
解密和加密数据的代码是
Public Sub EncryptOrDecryptFile(ByVal strInputFile As String, ByVal strOutputFile As String, _
ByVal bytKey() As Byte, ByVal bytIV() As Byte, ByVal Direction As CryptoAction)
Try
fsInput = New System.IO.FileStream(strInputFile, FileMode.Open, FileAccess.Read)
fsOutput = New System.IO.FileStream(strOutputFile, FileMode.OpenOrCreate, FileAccess.Write)
fsOutput.SetLength(0)
Dim bytBuffer(4096) As Byte
Dim lngBytesProcessed As Long = 0
Dim lngFileLength As Long = fsInput.Length
Dim intBytesInCurrentBlock As Integer
Dim csCryptoStream As CryptoStream
Dim cspRijndael As New System.Security.Cryptography.RijndaelManaged
Select Case Direction
Case CryptoAction.ActionEncrypt
csCryptoStream = New CryptoStream(fsOutput, _
cspRijndael.CreateEncryptor(bytKey, bytIV), _
CryptoStreamMode.Write)
Case CryptoAction.ActionDecrypt
csCryptoStream = New CryptoStream(fsOutput, _
cspRijndael.CreateDecryptor(bytKey, bytIV), _
CryptoStreamMode.Write)
End Select
While lngBytesProcessed < lngFileLength
intBytesInCurrentBlock = fsInput.Read(bytBuffer, 0, 4096)
csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock)
lngBytesProcessed = lngBytesProcessed + _
CLng(intBytesInCurrentBlock)
End While
csCryptoStream.Close()
fsInput.Close()
fsOutput.Close()
Catch ex As Exception
errorLog(ex)
End Try
End Sub
我需要使用这个或另一个子例程来读取文件、解密数据,然后将其存储在一个变量中以传递到连接字符串中 - 这可以做到吗?如果是,怎么做?
在对你的代码进行了多次尝试后,我决定放弃它——它太旧了,效率低下而且不安全(因为 )。
这是一段更高效的代码,我修改并改进了我的旧 class - 称为 Aes256Stream
。它派生自 CryptoStream
并将自动为您处理 IV。
'+---------------------------------------------------------------------------------+'
'| === Aes256Stream === |'
'| |'
'| Created by Vincent "Visual Vincent" Bengtsson |'
'| Website: https://www.mydoomsite.com/ |'
'| |'
'| |'
'| === COPYRIGHT LICENSE === |'
'| |'
'| Copyright (c) 2016-2017, Vincent Bengtsson |'
'| All rights reserved. |'
'| |'
'| Redistribution and use in source and binary forms, with or without |'
'| modification, are permitted provided that the following conditions are met: |'
'| |'
'| 1. Redistributions of source code must retain the above copyright notice, this |'
'| list of conditions and the following disclaimer. |'
'| 2. Redistributions in binary form must reproduce the above copyright notice, |'
'| this list of conditions and the following disclaimer in the documentation |'
'| and/or other materials provided with the distribution. |'
'| |'
'| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |'
'| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |'
'| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |'
'| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR |'
'| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |'
'| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |'
'| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |'
'| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |'
'| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |'
'| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |'
'+---------------------------------------------------------------------------------+'
Imports System.IO
Imports System.Security.Cryptography
Imports System.Runtime.InteropServices
Public Class Aes256Stream
Inherits CryptoStream
#Region "Fields"
Private _underlyingStream As Stream
Private AES As RijndaelManaged
Private Transform As ICryptoTransform
#End Region
#Region "Properties"
''' <summary>
''' Gets the block size, in bits, used by the stream's AES algorithm.
''' </summary>
''' <remarks></remarks>
Public ReadOnly Property BlockSize As Integer
Get
Return AES.BlockSize
End Get
End Property
''' <summary>
''' Gets the key size, in bits, used by the stream's AES algorithm.
''' </summary>
''' <remarks></remarks>
Public ReadOnly Property KeySize As Integer
Get
Return AES.KeySize
End Get
End Property
''' <summary>
''' Gets the length in bytes of the underlying stream.
''' </summary>
''' <remarks></remarks>
Public Overrides ReadOnly Property Length As Long
Get
Return _underlyingStream.Length
End Get
End Property
''' <summary>
''' Gets or sets the position within the underlying stream.
''' </summary>
''' <remarks></remarks>
Public Overrides Property Position As Long
Get
If _underlyingStream.CanSeek = False Then Throw New NotSupportedException("The underlying stream doesn't support seeking!")
Return _underlyingStream.Position
End Get
Set(value As Long)
If _underlyingStream.CanSeek = False Then Throw New NotSupportedException("The underlying stream doesn't support seeking!")
_underlyingStream.Position = value
End Set
End Property
''' <summary>
''' Gets the underlying stream.
''' </summary>
''' <remarks></remarks>
Public ReadOnly Property UnderlyingStream As Stream
Get
Return _underlyingStream
End Get
End Property
#End Region
#Region "Constructors"
Private Sub New(ByVal UnderlyingStream As Stream, _
ByVal AES As RijndaelManaged, _
ByVal CryptoTransform As ICryptoTransform, _
ByVal Mode As CryptoStreamMode)
MyBase.New(UnderlyingStream, CryptoTransform, Mode)
Me._underlyingStream = UnderlyingStream
Me.AES = AES
Me.Transform = CryptoTransform
End Sub
#End Region
#Region "Methods"
#Region "Instance"
''' <summary>
''' Sets the length of the underlying stream.
''' </summary>
''' <param name="value">The desired length of underlying stream in bytes.</param>
''' <remarks></remarks>the
Public Overrides Sub SetLength(value As Long)
_underlyingStream.SetLength(value)
End Sub
#End Region
#Region "Shared"
''' <summary>
''' Creates an AES-256 encryption stream.
''' </summary>
''' <param name="UnderlyingStream">The underlying stream to write the encrypted data to.</param>
''' <param name="Key">The encryption key to use when encrypting the data (automatically padded or truncated to KeySize/8 bytes).</param>
''' <remarks></remarks>
Public Shared Function CreateEncryptionStream(ByVal UnderlyingStream As Stream, ByVal Key As Byte()) As Aes256Stream
Dim AES As New RijndaelManaged
AES.KeySize = 256
AES.BlockSize = 128
AES.Key = Aes256Stream.PadOrTruncate(Key, AES.KeySize / 8)
AES.GenerateIV()
AES.Mode = CipherMode.CBC
AES.Padding = PaddingMode.PKCS7
'Write the IV to the underlying stream.
If UnderlyingStream.CanWrite = True Then
Dim LengthIV As Byte() = BitConverter.GetBytes(AES.IV.Length) 'Convert the IV.Length Integer to a byte array.
UnderlyingStream.Write(LengthIV, 0, LengthIV.Length) 'Write the length of the IV.
UnderlyingStream.Write(AES.IV, 0, AES.IV.Length) 'Write the IV.
Else
Throw New IOException("Underlying stream is not writable!")
End If
Return New Aes256Stream(UnderlyingStream, AES, AES.CreateEncryptor(), CryptoStreamMode.Write)
End Function
''' <summary>
''' Creates an AES-256 decryption stream.
''' </summary>
''' <param name="UnderlyingStream">The underlying stream to decrypt the data from.</param>
''' <param name="Key">The encryption key to use when encrypting the data (automatically padded or truncated to KeySize/8 bytes).</param>
''' <remarks></remarks>
Public Shared Function CreateDecryptionStream(ByVal UnderlyingStream As Stream, ByVal Key As Byte()) As Aes256Stream
Dim AES As New RijndaelManaged
AES.KeySize = 256
AES.BlockSize = 128
AES.Key = Aes256Stream.PadOrTruncate(Key, AES.KeySize / 8)
'Read the IV from the underlying stream.
If UnderlyingStream.CanRead = True Then
Dim BytesReadIV As Integer = 0
Dim BufferIV As Byte() = New Byte(Marshal.SizeOf(GetType(Integer)) - 1) {}
Dim LengthIV As Integer
'Read the IV's length.
While BytesReadIV < BufferIV.Length
Dim BytesRead As Integer = UnderlyingStream.Read(BufferIV, BytesReadIV, BufferIV.Length - BytesReadIV)
BytesReadIV += BytesRead
If BytesRead = 0 AndAlso BytesReadIV < BufferIV.Length Then _
Throw New IOException("End of stream reached before IV could be parsed!")
End While
'Convert the bytes to an Integer.
LengthIV = BitConverter.ToInt32(BufferIV, 0)
'Reset the variables.
BytesReadIV = 0
BufferIV = New Byte(LengthIV - 1) {}
'Read the IV.
While BytesReadIV < BufferIV.Length
Dim BytesRead As Integer = UnderlyingStream.Read(BufferIV, BytesReadIV, BufferIV.Length - BytesReadIV)
BytesReadIV += BytesRead
If BytesRead = 0 AndAlso BytesReadIV < BufferIV.Length Then _
Throw New IOException("End of stream reached before IV could be parsed!")
End While
'Set the IV.
AES.IV = BufferIV
Else
Throw New IOException("Underlying stream is not readable!")
End If
AES.Mode = CipherMode.CBC
AES.Padding = PaddingMode.PKCS7
Return New Aes256Stream(UnderlyingStream, AES, AES.CreateDecryptor(), CryptoStreamMode.Read)
End Function
Private Shared Function PadOrTruncate(ByVal Input As Byte(), ByVal PreferredLength As Integer) As Byte()
If Input.Length < PreferredLength Then 'Pad with zeros.
Dim PreviousLength As Integer = Input.Length
Array.Resize(Input, Input.Length + (PreferredLength - Input.Length))
For i = PreviousLength To Input.Length - 1
Input(i) = 0
Next
Return Input
ElseIf Input.Length > PreferredLength Then 'Truncate.
Array.Resize(Input, PreferredLength)
Return Input
End If
Return Input 'Do nothing.
End Function
#End Region
#End Region
#Region "Dispose()"
Protected Overrides Sub Dispose(disposing As Boolean)
MyBase.Dispose(disposing)
If disposing Then
Try
If Transform IsNot Nothing Then
Transform.Dispose()
Transform = Nothing
End If
Catch
End Try
Try
If AES IsNot Nothing Then
AES.Dispose()
AES = Nothing
End If
Catch
End Try
End If
End Sub
#End Region
End Class
要记住的两个主要事项是:
CreateEncryptionStream()
创建一个 只写 流来执行加密。
CreateDecryptionStream()
创建一个 只读 流用于执行解密。
正在执行加密
执行加密的最简单示例只需要您创建一个新的Aes256Stream
并写入:
Using AesStream As Aes256Stream = Aes256Stream.CreateEncryptionStream(<output stream>, <encryption key>)
AesStream.Write(<buffer>, <offset>, <length>)
End Using
备注:
<output stream>
是加密数据 到 的流(例如 FileStream
)。
<encryption key>
是加密数据时使用的密钥(作为字节数组)。
<buffer>
、<offset>
和 <length>
的行为就像 write to a regular stream.
正在执行解密
同样,执行解密的最简单示例只需要您创建一个新的 Aes256Stream
并从中读取:
Using AesStream As Aes256Stream = Aes256Stream.CreateDecryptionStream(<input stream>, <decryption key>)
Dim DecryptedData As Byte() = New Byte(AesStream.Length - 1) {}
AesStream.Read(DecryptedData, 0, DecryptedData.Length)
End Using
备注:
<input stream>
是解密数据 来自 的流(例如 FileStream
)。
<decryption key>
(与上面的<encryption key>
相同)。
AesStream.Length
等于调用 <input stream>.Length
(AesStream.Position
和 <input stream>.Position
也是如此)。
供您使用
以下是调整代码以使用它的方法...
方法:
''' <summary>
''' Encrypts data to a file.
''' </summary>
''' <param name="File">The file to encrypt data to.</param>
''' <param name="Data">The data to encrypt.</param>
''' <param name="Key">The key to use to perform the encryption.</param>
''' <remarks></remarks>
Public Sub EncryptFile(ByVal File As String, ByVal Data As Byte(), ByVal Key As Byte())
Using OutputStream As New FileStream(File, FileMode.Create, FileAccess.Write, FileShare.None)
Using AesStream As Aes256Stream = Aes256Stream.CreateEncryptionStream(OutputStream, Key)
AesStream.Write(Data, 0, Data.Length)
End Using
End Using
End Sub
''' <summary>
''' Decrypts a file and returns the decrypted data.
''' </summary>
''' <param name="File">The file to decrypt.</param>
''' <param name="Key">The key to use to perform the decryption.</param>
''' <remarks></remarks>
Public Function DecryptFile(ByVal File As String, ByVal Key As Byte()) As Byte()
Using InputStream As New FileStream(File, FileMode.Open, FileAccess.Read, FileShare.Read)
Using DecryptedStream As New MemoryStream
Using AesStream As Aes256Stream = Aes256Stream.CreateDecryptionStream(InputStream, Key)
Dim Buffer As Byte() = New Byte(4096 - 1) {}
While AesStream.Position < AesStream.Length
Dim BytesRead As Integer = AesStream.Read(Buffer, 0, Buffer.Length)
DecryptedStream.Write(Buffer, 0, BytesRead)
End While
Return DecryptedStream.ToArray()
End Using
End Using
End Using
End Function
用法示例:
Dim Key As Byte() = System.Text.Encoding.UTF8.GetBytes("verysecretpassword") 'If you actually use a password here do hash it first!
Dim TextToEncrypt As String = "Hello World! How are you?"
Dim DataToEncrypt As Byte() = System.Text.Encoding.UTF8.GetBytes(TextToEncrypt)
EncryptFile("encrypted.txt", DataToEncrypt, Key)
Dim DecryptedData As Byte() = DecryptFile("encrypted.txt", Key)
Dim DecryptedText As String = System.Text.Encoding.UTF8.GetString(DecryptedData)
在线测试
可在此处找到此代码的在线可测试版本:https://dotnetfiddle.net/PXaJF8
我已经使用this guide将txtCode.Text
的值加密到一个文本文件中,然后隐藏 - 加密数据的值将用作数据库的密码,所以我需要读取这个值,解密它,然后将它传递到连接字符串中。
然而,在本指南中,解密是通过键入一个值,创建一个 bytKey
和 bytIV
,然后将 newl 键入的字符串的加密结果与中的值进行比较来完成的文本文件。显然我不能在每次需要打开数据库的时候都要求用户输入密码,那么如何使用这段代码实现解密呢?
解密和加密数据的代码是
Public Sub EncryptOrDecryptFile(ByVal strInputFile As String, ByVal strOutputFile As String, _
ByVal bytKey() As Byte, ByVal bytIV() As Byte, ByVal Direction As CryptoAction)
Try
fsInput = New System.IO.FileStream(strInputFile, FileMode.Open, FileAccess.Read)
fsOutput = New System.IO.FileStream(strOutputFile, FileMode.OpenOrCreate, FileAccess.Write)
fsOutput.SetLength(0)
Dim bytBuffer(4096) As Byte
Dim lngBytesProcessed As Long = 0
Dim lngFileLength As Long = fsInput.Length
Dim intBytesInCurrentBlock As Integer
Dim csCryptoStream As CryptoStream
Dim cspRijndael As New System.Security.Cryptography.RijndaelManaged
Select Case Direction
Case CryptoAction.ActionEncrypt
csCryptoStream = New CryptoStream(fsOutput, _
cspRijndael.CreateEncryptor(bytKey, bytIV), _
CryptoStreamMode.Write)
Case CryptoAction.ActionDecrypt
csCryptoStream = New CryptoStream(fsOutput, _
cspRijndael.CreateDecryptor(bytKey, bytIV), _
CryptoStreamMode.Write)
End Select
While lngBytesProcessed < lngFileLength
intBytesInCurrentBlock = fsInput.Read(bytBuffer, 0, 4096)
csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock)
lngBytesProcessed = lngBytesProcessed + _
CLng(intBytesInCurrentBlock)
End While
csCryptoStream.Close()
fsInput.Close()
fsOutput.Close()
Catch ex As Exception
errorLog(ex)
End Try
End Sub
我需要使用这个或另一个子例程来读取文件、解密数据,然后将其存储在一个变量中以传递到连接字符串中 - 这可以做到吗?如果是,怎么做?
在对你的代码进行了多次尝试后,我决定放弃它——它太旧了,效率低下而且不安全(因为
这是一段更高效的代码,我修改并改进了我的旧 class - 称为 Aes256Stream
。它派生自 CryptoStream
并将自动为您处理 IV。
'+---------------------------------------------------------------------------------+'
'| === Aes256Stream === |'
'| |'
'| Created by Vincent "Visual Vincent" Bengtsson |'
'| Website: https://www.mydoomsite.com/ |'
'| |'
'| |'
'| === COPYRIGHT LICENSE === |'
'| |'
'| Copyright (c) 2016-2017, Vincent Bengtsson |'
'| All rights reserved. |'
'| |'
'| Redistribution and use in source and binary forms, with or without |'
'| modification, are permitted provided that the following conditions are met: |'
'| |'
'| 1. Redistributions of source code must retain the above copyright notice, this |'
'| list of conditions and the following disclaimer. |'
'| 2. Redistributions in binary form must reproduce the above copyright notice, |'
'| this list of conditions and the following disclaimer in the documentation |'
'| and/or other materials provided with the distribution. |'
'| |'
'| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |'
'| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |'
'| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |'
'| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR |'
'| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |'
'| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |'
'| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |'
'| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |'
'| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |'
'| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |'
'+---------------------------------------------------------------------------------+'
Imports System.IO
Imports System.Security.Cryptography
Imports System.Runtime.InteropServices
Public Class Aes256Stream
Inherits CryptoStream
#Region "Fields"
Private _underlyingStream As Stream
Private AES As RijndaelManaged
Private Transform As ICryptoTransform
#End Region
#Region "Properties"
''' <summary>
''' Gets the block size, in bits, used by the stream's AES algorithm.
''' </summary>
''' <remarks></remarks>
Public ReadOnly Property BlockSize As Integer
Get
Return AES.BlockSize
End Get
End Property
''' <summary>
''' Gets the key size, in bits, used by the stream's AES algorithm.
''' </summary>
''' <remarks></remarks>
Public ReadOnly Property KeySize As Integer
Get
Return AES.KeySize
End Get
End Property
''' <summary>
''' Gets the length in bytes of the underlying stream.
''' </summary>
''' <remarks></remarks>
Public Overrides ReadOnly Property Length As Long
Get
Return _underlyingStream.Length
End Get
End Property
''' <summary>
''' Gets or sets the position within the underlying stream.
''' </summary>
''' <remarks></remarks>
Public Overrides Property Position As Long
Get
If _underlyingStream.CanSeek = False Then Throw New NotSupportedException("The underlying stream doesn't support seeking!")
Return _underlyingStream.Position
End Get
Set(value As Long)
If _underlyingStream.CanSeek = False Then Throw New NotSupportedException("The underlying stream doesn't support seeking!")
_underlyingStream.Position = value
End Set
End Property
''' <summary>
''' Gets the underlying stream.
''' </summary>
''' <remarks></remarks>
Public ReadOnly Property UnderlyingStream As Stream
Get
Return _underlyingStream
End Get
End Property
#End Region
#Region "Constructors"
Private Sub New(ByVal UnderlyingStream As Stream, _
ByVal AES As RijndaelManaged, _
ByVal CryptoTransform As ICryptoTransform, _
ByVal Mode As CryptoStreamMode)
MyBase.New(UnderlyingStream, CryptoTransform, Mode)
Me._underlyingStream = UnderlyingStream
Me.AES = AES
Me.Transform = CryptoTransform
End Sub
#End Region
#Region "Methods"
#Region "Instance"
''' <summary>
''' Sets the length of the underlying stream.
''' </summary>
''' <param name="value">The desired length of underlying stream in bytes.</param>
''' <remarks></remarks>the
Public Overrides Sub SetLength(value As Long)
_underlyingStream.SetLength(value)
End Sub
#End Region
#Region "Shared"
''' <summary>
''' Creates an AES-256 encryption stream.
''' </summary>
''' <param name="UnderlyingStream">The underlying stream to write the encrypted data to.</param>
''' <param name="Key">The encryption key to use when encrypting the data (automatically padded or truncated to KeySize/8 bytes).</param>
''' <remarks></remarks>
Public Shared Function CreateEncryptionStream(ByVal UnderlyingStream As Stream, ByVal Key As Byte()) As Aes256Stream
Dim AES As New RijndaelManaged
AES.KeySize = 256
AES.BlockSize = 128
AES.Key = Aes256Stream.PadOrTruncate(Key, AES.KeySize / 8)
AES.GenerateIV()
AES.Mode = CipherMode.CBC
AES.Padding = PaddingMode.PKCS7
'Write the IV to the underlying stream.
If UnderlyingStream.CanWrite = True Then
Dim LengthIV As Byte() = BitConverter.GetBytes(AES.IV.Length) 'Convert the IV.Length Integer to a byte array.
UnderlyingStream.Write(LengthIV, 0, LengthIV.Length) 'Write the length of the IV.
UnderlyingStream.Write(AES.IV, 0, AES.IV.Length) 'Write the IV.
Else
Throw New IOException("Underlying stream is not writable!")
End If
Return New Aes256Stream(UnderlyingStream, AES, AES.CreateEncryptor(), CryptoStreamMode.Write)
End Function
''' <summary>
''' Creates an AES-256 decryption stream.
''' </summary>
''' <param name="UnderlyingStream">The underlying stream to decrypt the data from.</param>
''' <param name="Key">The encryption key to use when encrypting the data (automatically padded or truncated to KeySize/8 bytes).</param>
''' <remarks></remarks>
Public Shared Function CreateDecryptionStream(ByVal UnderlyingStream As Stream, ByVal Key As Byte()) As Aes256Stream
Dim AES As New RijndaelManaged
AES.KeySize = 256
AES.BlockSize = 128
AES.Key = Aes256Stream.PadOrTruncate(Key, AES.KeySize / 8)
'Read the IV from the underlying stream.
If UnderlyingStream.CanRead = True Then
Dim BytesReadIV As Integer = 0
Dim BufferIV As Byte() = New Byte(Marshal.SizeOf(GetType(Integer)) - 1) {}
Dim LengthIV As Integer
'Read the IV's length.
While BytesReadIV < BufferIV.Length
Dim BytesRead As Integer = UnderlyingStream.Read(BufferIV, BytesReadIV, BufferIV.Length - BytesReadIV)
BytesReadIV += BytesRead
If BytesRead = 0 AndAlso BytesReadIV < BufferIV.Length Then _
Throw New IOException("End of stream reached before IV could be parsed!")
End While
'Convert the bytes to an Integer.
LengthIV = BitConverter.ToInt32(BufferIV, 0)
'Reset the variables.
BytesReadIV = 0
BufferIV = New Byte(LengthIV - 1) {}
'Read the IV.
While BytesReadIV < BufferIV.Length
Dim BytesRead As Integer = UnderlyingStream.Read(BufferIV, BytesReadIV, BufferIV.Length - BytesReadIV)
BytesReadIV += BytesRead
If BytesRead = 0 AndAlso BytesReadIV < BufferIV.Length Then _
Throw New IOException("End of stream reached before IV could be parsed!")
End While
'Set the IV.
AES.IV = BufferIV
Else
Throw New IOException("Underlying stream is not readable!")
End If
AES.Mode = CipherMode.CBC
AES.Padding = PaddingMode.PKCS7
Return New Aes256Stream(UnderlyingStream, AES, AES.CreateDecryptor(), CryptoStreamMode.Read)
End Function
Private Shared Function PadOrTruncate(ByVal Input As Byte(), ByVal PreferredLength As Integer) As Byte()
If Input.Length < PreferredLength Then 'Pad with zeros.
Dim PreviousLength As Integer = Input.Length
Array.Resize(Input, Input.Length + (PreferredLength - Input.Length))
For i = PreviousLength To Input.Length - 1
Input(i) = 0
Next
Return Input
ElseIf Input.Length > PreferredLength Then 'Truncate.
Array.Resize(Input, PreferredLength)
Return Input
End If
Return Input 'Do nothing.
End Function
#End Region
#End Region
#Region "Dispose()"
Protected Overrides Sub Dispose(disposing As Boolean)
MyBase.Dispose(disposing)
If disposing Then
Try
If Transform IsNot Nothing Then
Transform.Dispose()
Transform = Nothing
End If
Catch
End Try
Try
If AES IsNot Nothing Then
AES.Dispose()
AES = Nothing
End If
Catch
End Try
End If
End Sub
#End Region
End Class
要记住的两个主要事项是:
CreateEncryptionStream()
创建一个 只写 流来执行加密。CreateDecryptionStream()
创建一个 只读 流用于执行解密。
正在执行加密
执行加密的最简单示例只需要您创建一个新的Aes256Stream
并写入:
Using AesStream As Aes256Stream = Aes256Stream.CreateEncryptionStream(<output stream>, <encryption key>)
AesStream.Write(<buffer>, <offset>, <length>)
End Using
备注:
<output stream>
是加密数据 到 的流(例如FileStream
)。<encryption key>
是加密数据时使用的密钥(作为字节数组)。<buffer>
、<offset>
和<length>
的行为就像 write to a regular stream.
正在执行解密
同样,执行解密的最简单示例只需要您创建一个新的 Aes256Stream
并从中读取:
Using AesStream As Aes256Stream = Aes256Stream.CreateDecryptionStream(<input stream>, <decryption key>)
Dim DecryptedData As Byte() = New Byte(AesStream.Length - 1) {}
AesStream.Read(DecryptedData, 0, DecryptedData.Length)
End Using
备注:
<input stream>
是解密数据 来自 的流(例如FileStream
)。<decryption key>
(与上面的<encryption key>
相同)。AesStream.Length
等于调用<input stream>.Length
(AesStream.Position
和<input stream>.Position
也是如此)。
供您使用
以下是调整代码以使用它的方法...
方法:
''' <summary>
''' Encrypts data to a file.
''' </summary>
''' <param name="File">The file to encrypt data to.</param>
''' <param name="Data">The data to encrypt.</param>
''' <param name="Key">The key to use to perform the encryption.</param>
''' <remarks></remarks>
Public Sub EncryptFile(ByVal File As String, ByVal Data As Byte(), ByVal Key As Byte())
Using OutputStream As New FileStream(File, FileMode.Create, FileAccess.Write, FileShare.None)
Using AesStream As Aes256Stream = Aes256Stream.CreateEncryptionStream(OutputStream, Key)
AesStream.Write(Data, 0, Data.Length)
End Using
End Using
End Sub
''' <summary>
''' Decrypts a file and returns the decrypted data.
''' </summary>
''' <param name="File">The file to decrypt.</param>
''' <param name="Key">The key to use to perform the decryption.</param>
''' <remarks></remarks>
Public Function DecryptFile(ByVal File As String, ByVal Key As Byte()) As Byte()
Using InputStream As New FileStream(File, FileMode.Open, FileAccess.Read, FileShare.Read)
Using DecryptedStream As New MemoryStream
Using AesStream As Aes256Stream = Aes256Stream.CreateDecryptionStream(InputStream, Key)
Dim Buffer As Byte() = New Byte(4096 - 1) {}
While AesStream.Position < AesStream.Length
Dim BytesRead As Integer = AesStream.Read(Buffer, 0, Buffer.Length)
DecryptedStream.Write(Buffer, 0, BytesRead)
End While
Return DecryptedStream.ToArray()
End Using
End Using
End Using
End Function
用法示例:
Dim Key As Byte() = System.Text.Encoding.UTF8.GetBytes("verysecretpassword") 'If you actually use a password here do hash it first!
Dim TextToEncrypt As String = "Hello World! How are you?"
Dim DataToEncrypt As Byte() = System.Text.Encoding.UTF8.GetBytes(TextToEncrypt)
EncryptFile("encrypted.txt", DataToEncrypt, Key)
Dim DecryptedData As Byte() = DecryptFile("encrypted.txt", Key)
Dim DecryptedText As String = System.Text.Encoding.UTF8.GetString(DecryptedData)
在线测试
可在此处找到此代码的在线可测试版本:https://dotnetfiddle.net/PXaJF8