VB.Net 中的简单加密/解密

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7982933/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 15:46:22  来源:igfitidea点击:

simple encrypting / decrypting in VB.Net

vb.netencryptionrijndaelmanagedcryptostream

提问by nttaylor

I'm trying to figure out how to encrypt / decrypt a string in VB.Net.

我想弄清楚如何在 VB.Net 中加密/解密字符串。

I followed the example given hereand wrote the following code (below). There's a text box, an "encrypt" button, and a "decrypt" button. The idea is to type something into the text box ("like 'hello world'"), click "encrypt", and see the encrypted version appear in the text box. Clicking "decrypt" should then take you back to the original string.

我按照此处给出的示例编写了以下代码(如下)。有一个文本框、一个“加密”按钮和一个“解密”按钮。这个想法是在文本框中输入一些东西(“像'hello world'”),点击“加密”,然后看到加密版本出现在文本框中。单击“解密”应该会带您回到原始字符串。

But when I try to encrypt I get an error when I try to "FlushFinalBlock". The error is: "Length of the data to encrypt is invalid".

但是当我尝试加密时,当我尝试“FlushFinalBlock”时出现错误。错误是:“要加密的数据长度无效”。

The "decrypt" part is a total shot in the dark, as the example quoted above only deals with encryption, not decryption. I'm sure it's wrong, but since I can't get "encrypt" to work I haven't tested it yet.

“解密”部分完全是一头雾水,因为上面引用的例子只涉及加密,而不是解密。我确定这是错误的,但由于我无法“加密”工作,因此我还没有对其进行测试。

Can anyone tell me why this doesn't work?

谁能告诉我为什么这不起作用?

Imports System.Data.SqlClient
Imports System.IO
Imports System.Security.Cryptography

Public Class Form1

  Private cryptObj As RijndaelManaged
  Private KEY_128 As Byte() = {42, 1, 52, 67, 231, 13, 94, 101, 123, 6, 0, 12, 32, 91, 4, 111, 31, 70, 21, 141, 123, 142, 234, 82, 95, 129, 187, 162, 12, 55, 98, 23}
  Private IV_128 As Byte() = {234, 12, 52, 44, 214, 222, 200, 109, 2, 98, 45, 76, 88, 53, 23, 78}
  Private enc As System.Text.UTF8Encoding = New System.Text.UTF8Encoding()

  Private Sub btnEncrypt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEncrypt.Click
    Dim sPlainText As String = Me.TextBox1.Text
    If Not String.IsNullOrEmpty(sPlainText) Then
      Dim bPlainText As Byte() = Me.enc.GetBytes(Me.TextBox1.Text)
      Dim ms As MemoryStream = New MemoryStream()
      Dim cs As CryptoStream = New CryptoStream(ms, cryptObj.CreateEncryptor(), CryptoStreamMode.Write)
      cs.Write(bPlainText, 0, sPlainText.Length)
      cs.FlushFinalBlock()
      Me.TextBox1.Text = Me.enc.GetString(ms.ToArray())
    End If
  End Sub

  Private Sub btnDecrypt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDecrypt.Click
    Dim sCipherText = Me.TextBox1.Text
    Dim ms As MemoryStream = New MemoryStream()
    Dim cs As CryptoStream = New CryptoStream(ms, cryptObj.CreateDecryptor(), CryptoStreamMode.Read)
    cs.Read(Me.enc.GetBytes(sCipherText), 0, sCipherText.Length)
    Me.TextBox1.Text = Me.enc.GetString(ms.ToArray())
  End Sub

  Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Me.cryptObj = New RijndaelManaged()
    Me.cryptObj.BlockSize = 128
    Me.cryptObj.KeySize = 128
    Me.cryptObj.Mode = CipherMode.ECB
    Me.cryptObj.Padding = PaddingMode.None
    Me.cryptObj.Key = KEY_128
    Me.cryptObj.IV = IV_128
  End Sub

End Class

回答by nttaylor

Ultimately I found the answer here:

最终我在这里找到了答案:

http://www.obviex.com/samples/Encryption.aspx

http://www.obviex.com/samples/Encryption.aspx

His example seems a little over-complicated. I'm sure it represents a more general and flexible case, but I was able to do away with the "saltPhrase", the "initVector", and the use of "PasswordDeriveBytes", which apparently is deprecated anyway, but I also avoided its nastily named replacement: Rfc2898DeriveBytes.

他的例子似乎有点过于复杂。我确信它代表了一个更通用和更灵活的情况,但我能够取消“saltPhrase”、“initVector”和“PasswordDeriveBytes”的使用,这显然已被弃用,但我也避免了它命名替换:Rfc2898DeriveBytes。

The following lets you enter a string of any length, encrypt it, and re-decrypt it.

下面让您输入任意长度的字符串,对其进行加密,然后重新解密。

Imports System.Data.SqlClient
Imports System.IO
Imports System.Security.Cryptography

Public Class Form1

  Private enc As System.Text.UTF8Encoding
  Private encryptor As ICryptoTransform
  Private decryptor As ICryptoTransform

  Private Sub btnEncrypt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEncrypt.Click
    Dim sPlainText As String = Me.TextBox1.Text
    If Not String.IsNullOrEmpty(sPlainText) Then
      Dim memoryStream As MemoryStream = New MemoryStream()
      Dim cryptoStream As CryptoStream = New CryptoStream(memoryStream, Me.encryptor, CryptoStreamMode.Write)
      cryptoStream.Write(Me.enc.GetBytes(sPlainText), 0, sPlainText.Length)
      cryptoStream.FlushFinalBlock()
      Me.TextBox1.Text = Convert.ToBase64String(memoryStream.ToArray())
      memoryStream.Close()
      cryptoStream.Close()
    End If
  End Sub

  Private Sub btnDecrypt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDecrypt.Click
    Dim cypherTextBytes As Byte() = Convert.FromBase64String(Me.TextBox1.Text)
    Dim memoryStream As MemoryStream = New MemoryStream(cypherTextBytes)
    Dim cryptoStream As CryptoStream = New CryptoStream(memoryStream, Me.decryptor, CryptoStreamMode.Read)
    Dim plainTextBytes(cypherTextBytes.Length) As Byte
    Dim decryptedByteCount As Integer = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length)
    memoryStream.Close()
    cryptoStream.Close()
    Me.TextBox1.Text = Me.enc.GetString(plainTextBytes, 0, decryptedByteCount)
  End Sub

  Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Dim KEY_128 As Byte() = {42, 1, 52, 67, 231, 13, 94, 101, 123, 6, 0, 12, 32, 91, 4, 111, 31, 70, 21, 141, 123, 142, 234, 82, 95, 129, 187, 162, 12, 55, 98, 23}
    Dim IV_128 As Byte() = {234, 12, 52, 44, 214, 222, 200, 109, 2, 98, 45, 76, 88, 53, 23, 78}
    Dim symmetricKey As RijndaelManaged = New RijndaelManaged()
    symmetricKey.Mode = CipherMode.CBC

    Me.enc = New System.Text.UTF8Encoding
    Me.encryptor = symmetricKey.CreateEncryptor(KEY_128, IV_128)
    Me.decryptor = symmetricKey.CreateDecryptor(KEY_128, IV_128)
  End Sub

End Class

回答by Richard Avenia

Here is an example of an Encryption class based on my NextLevelEncryptionlibrary.

这是基于我的NextLevelEncryption库的加密类的示例。

Public Class Encryption
''' <summary>
''' Encrypt text using AES Algorithm
''' </summary>
''' <param name="text">Text to encrypt</param>
''' <param name="password">Password with which to encrypt</param>
''' <returns>Returns encrypted text</returns>
''' <remarks></remarks>
Public Shared Function Encrypt(text As String, password As String) As String
    Dim AES As New System.Security.Cryptography.RijndaelManaged
    Dim Hash_AES As New System.Security.Cryptography.MD5CryptoServiceProvider
    Dim encrypted As String = ""
    Dim hash(31) As Byte
        Dim temp As Byte() = Hash_AES.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(password))
        Array.Copy(temp, 0, hash, 0, 16)
        Array.Copy(temp, 0, hash, 15, 16)
        AES.Key = hash
        AES.Mode = Security.Cryptography.CipherMode.ECB
        Dim DESEncrypter As System.Security.Cryptography.ICryptoTransform = AES.CreateEncryptor
        Dim Buffer As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(text)
        encrypted = Convert.ToBase64String(DESEncrypter.TransformFinalBlock(Buffer, 0, Buffer.Length))
        Return encrypted
End Function

''' <summary>
''' Decrypt text using AES Algorithm
''' </summary>
''' <param name="text">Text to decrypt</param>
''' <param name="password">Password with which to decrypt</param>
''' <returns>Returns decrypted text</returns>
''' <remarks></remarks>
Public Shared Function Decrypt(text As String, password As String) As String
    Dim AES As New System.Security.Cryptography.RijndaelManaged
    Dim Hash_AES As New System.Security.Cryptography.MD5CryptoServiceProvider
    Dim decrypted As String = ""
    Dim hash(31) As Byte
        Dim temp As Byte() = Hash_AES.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(password))
        Array.Copy(temp, 0, hash, 0, 16)
        Array.Copy(temp, 0, hash, 15, 16)
        AES.Key = hash
        AES.Mode = Security.Cryptography.CipherMode.ECB
        Dim DESDecrypter As System.Security.Cryptography.ICryptoTransform = AES.CreateDecryptor
        Dim Buffer As Byte() = Convert.FromBase64String(text)
        decrypted = System.Text.ASCIIEncoding.ASCII.GetString(DESDecrypter.TransformFinalBlock(Buffer, 0, Buffer.Length))
    Return decrypted
End Function
End Class

To use it all you have to do is call the function Encrypt("Your text to encrypt here","Your password")and Decrypt(""Your text to encrypt here","Your password").

要使用它,您只需调用函数Encrypt("Your text to encrypt here","Your password")Decrypt(""Your text to encrypt here","Your password").

For more information head over to https://nextlevelencryption.codeplex.com/

有关更多信息,请访问https://nextlevelencryption.codeplex.com/

回答by Joel Coehoorn

The issue I spotted is on this line in your encryption code:

我发现的问题在您的加密代码中的这一行:

Me.TextBox1.Text = Me.enc.GetString(ms.ToArray())

Me.TextBox1.Text = Me.enc.GetString(ms.ToArray())

The problem is that this assumes your byte array already isa UTF-8 string, just carved up as a byte array, when in fact it should be random bytes and likely includes unprintable characters. It's not valid utf-8 data. What you want to do instead is base-64 encode that byte array using the Convert.ToBase64String()function.

问题在于,这假设您的字节数组已经是一个 UTF-8 字符串,只是被分割为一个字节数组,而实际上它应该是随机字节并且可能包含不可打印的字符。它不是有效的 utf-8 数据。您想要做的是使用Convert.ToBase64String()函数对该字节数组进行 base-64 编码。

Then, your decryption needs to correctly convert that base 64 string back to a byte array, using the Convert.FromBase64String()method.

然后,您的解密需要使用Convert.FromBase64String()方法将该 base 64 字符串正确转换回字节数组。

回答by competent_tech

Your encryption looks mostly correct, but I am not sure if the UTF8 encoding or other settings on the encryption object is throwing you off. Here is the heart of the encryption method that we use, tailored slightly to your code:

您的加密看起来基本正确,但我不确定加密对象上的 UTF8 编码或其他设置是否会让您失望。这是我们使用的加密方法的核心,根据您的代码稍微定制:

' Return the encrypted bytes from the memory stream.
Dim aoBytes As Byte() = Nothing

' Declare the RijndaelManaged object used to encrypt the data.
Using oEncryptor As New RijndaelManaged
    Try
        ' Initialize the encryptor with the specified key and initialization vector
        oEncryptor.Key = KEY_128
        oEncryptor.IV = IV_128

        ' Declare the streams used to encrypt to an in memory array of bytes.
        Using msEncrypt As New MemoryStream
            ' Create the streams used for encryption.
            Using csEncrypt As New CryptoStream(msEncrypt, oEncryptor.CreateEncryptor(), CryptoStreamMode.Write)
                Using swEncrypt As New StreamWriter(csEncrypt)
                    ' Write all data to the stream.
                    swEncrypt.Write(Me.TextBox1.Text)
                End Using

                ' Retrieve the bytes
                aoBytes = msEncrypt.ToArray()
            End Using

        End Using
    Finally
        ' Clear the RijndaelManaged object.
        If oEncryptor IsNot Nothing Then
            oEncryptor.Clear()
        End If
    End Try
End Using

If aoBytes IsNot Nothing Then
    Me.TextBox1.Text = System.Convert.ToBase64String(aoBytes)
Else
    Me.TextBox1.Text = String.Empty
End If

And the decryption is:

解密是:

Dim sDecryptedValue As String = ""

' Declare the RijndaelManaged object used to encrypt the data.
Using oDecryptor As New RijndaelManaged
    Try
        ' Initialize the encryptor with the specified key and a default initialization vector
        oDecryptor.Key = KEY_128
        oDecryptor.IV = IV_128

        Using msDecrypt As New MemoryStream(System.Convert.FromBase64String(Me.TextBox1.Text))
            ' Create the streams used for encryption.
            Using csDecrypt As New CryptoStream(msDecrypt, oDecryptor.CreateDecryptor(), CryptoStreamMode.Read)
                Using srDecrypt As New StreamReader(csDecrypt)
                    ' Write all data to the stream.
                    sDecryptedValue = srDecrypt.ReadToEnd()
                End Using
            End Using
        End Using
    Finally
        ' Clear the RijndaelManaged object.
        If oDecryptor IsNot Nothing Then
            oDecryptor.Clear()
        End If
    End Try
End Using

Me.TextBox1.Text = sDecryptedValue

One minor difference is that we accept a string key and intializaton vector from the caller and clean them up as follows.

一个细微的区别是我们接受来自调用者的字符串键和初始化向量,并按如下方式清理它们。

InitializationVector cleanup:

初始化向量清理:

If sInitializationVector.Length > 16 Then
    ' Trim the IV if it is too long
    sInitializationVector = sInitializationVector.Substring(0, 16)
ElseIf sInitializationVector.Length < 16 Then
    ' Pad the IV if it is too short
    sInitializationVector = sInitializationVector.PadRight(16)
End If

oDecryptor.IV = System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(sInitializationVector)

Encryption key cleanup:

加密密钥清理:

oDecryptor.Key = GetLegalEncryptionKey(sKey, oDecryptor)

Public Function GetLegalEncryptionKey(ByVal sKey As String, ByVal oEncryptor As RijndaelManaged) As Byte()

Dim sTemp As String

If oEncryptor.LegalKeySizes.Length > 0 Then
    Dim wSize As Integer
    ' key sizes are in bits

    With oEncryptor.LegalKeySizes(0)
        wSize = .MinSize
        Do While sKey.Length * 8 > wSize AndAlso .SkipSize > 0 AndAlso wSize < .MaxSize
            wSize += oEncryptor.LegalKeySizes(0).SkipSize
        Loop
    End With
    Dim wTotalChars As Integer

    wTotalChars = CInt(wSize / 8)
    If sKey.Length > wTotalChars Then
        sTemp = sKey.Substring(0, wTotalChars)
    Else
        sTemp = sKey.PadRight(wTotalChars, " "c)
    End If
Else
    sTemp = sKey
End If

' convert the secret key to byte array
Return System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(sTemp)

End Function

结束函数