【问题标题】:Standard library for AES encryption for VB.NET?用于 VB.NET 的 AES 加密的标准库?
【发布时间】:2013-05-07 13:21:19
【问题描述】:

是否有用于 VB.NET 的 AES 加密的标准库?我想用静态私钥加密一个字符串。

我搜索了一下,发现了很多变化。我真的不知道如何确定哪些算法是安全的。

【问题讨论】:

  • 你有没有看过System.Security.Cryptography命名空间?
  • @Oded 嘿.. 我刚刚遇到了那个网站.. msdn.microsoft.com/en-us/library/… 我真的不知道如何处理那里的示例.. =x
  • @ysj 你能提供比“我真的不知道该怎么做”更多的内容吗? ...如果您有特殊问题,您会在这里找到帮助...
  • “我想尝试使用静态私钥加密字符串。...我真的不知道如何确定他们的算法是否安全”如果您存储了静态私钥在您的应用程序中,那么它是不安全的,因为人们可以从您的应用程序中提取它(因此用于加密它的算法并不重要)。您将如何使用这些加密数据?

标签: vb.net encryption aes


【解决方案1】:

System.Security.Cryptography 命名空间包含执行大多数标准加密任务所需的所有类。不幸的是,由于加密是一个相当复杂的主题,因此这些课程有些难以使用——尤其是对于初学者。有时很难找到一个简单的工作示例来开始。但是,既然我很好,我会为您提供一个简单的示例,您可以使用和改进:)

您可能想要使用的类称为RijndaelManaged。那是实现典型 AES 加密的类。这是一个示例类,它使用它在纯文本字符串和字节数组之间进行转换:

Public Class Aes256Encrypter
    Public Function Encrypt(ByVal plainText As String, ByVal secretKey As String) As Byte()
        Dim encryptedPassword As Byte()
        Using outputStream As MemoryStream = New MemoryStream()
            Dim algorithm As RijndaelManaged = getAlgorithm(secretKey)
            Using cryptoStream As CryptoStream = New CryptoStream(outputStream, algorithm.CreateEncryptor(), CryptoStreamMode.Write)
                Dim inputBuffer() As Byte = Encoding.Unicode.GetBytes(plainText)
                cryptoStream.Write(inputBuffer, 0, inputBuffer.Length)
                cryptoStream.FlushFinalBlock()
                encryptedPassword = outputStream.ToArray()
            End Using
        End Using
        Return encryptedPassword
    End Function

    Public Function Decrypt(ByVal encryptedBytes As Byte(), ByVal secretKey As String) As String
        Dim plainText As String = Nothing
        Using inputStream As MemoryStream = New MemoryStream(encryptedBytes)
            Dim algorithm As RijndaelManaged = getAlgorithm(secretKey)
            Using cryptoStream As CryptoStream = New CryptoStream(inputStream, algorithm.CreateDecryptor(), CryptoStreamMode.Read)
                Dim outputBuffer(0 To CType(inputStream.Length - 1, Integer)) As Byte
                Dim readBytes As Integer = cryptoStream.Read(outputBuffer, 0, CType(inputStream.Length, Integer))
                plainText = Encoding.Unicode.GetString(outputBuffer, 0, readBytes)
            End Using
        End Using
        Return plainText
    End Function

    Private Function getAlgorithm(ByVal secretKey As String) As RijndaelManaged
        Const salt As String = "put your salt here"
        Const keySize As Integer = 256

        Dim keyBuilder As Rfc2898DeriveBytes = New Rfc2898DeriveBytes(secretKey, Encoding.Unicode.GetBytes(salt))
        Dim algorithm As RijndaelManaged = New RijndaelManaged()
        algorithm.KeySize = keySize
        algorithm.IV = keyBuilder.GetBytes(CType(algorithm.BlockSize / 8, Integer))
        algorithm.Key = keyBuilder.GetBytes(CType(algorithm.KeySize / 8, Integer))
        algorithm.Padding = PaddingMode.PKCS7
        Return algorithm
    End Function
End Class

您应该将salt 常量更改为其他值。理想情况下,它甚至不是一个常数,因为为了使其尽可能安全,您应该在每次执行加密时使用不同的盐,但这是另一个话题。

如果您希望将加密值返回为字符串而不是字节数组,您可以使用 Base-64 编码将字节数组转换为字符串和从字符串转换,如下所示:

Public Class Aes256Base64Encrypter
    Public Function Encrypt(ByVal plainText As String, ByVal secretKey As String) As String
        Dim encryptedPassword As String = Nothing
        Using outputStream As MemoryStream = New MemoryStream()
            Dim algorithm As RijndaelManaged = getAlgorithm(secretKey)
            Using cryptoStream As CryptoStream = New CryptoStream(outputStream, algorithm.CreateEncryptor(), CryptoStreamMode.Write)
                Dim inputBuffer() As Byte = Encoding.Unicode.GetBytes(plainText)
                cryptoStream.Write(inputBuffer, 0, inputBuffer.Length)
                cryptoStream.FlushFinalBlock()
                encryptedPassword = Convert.ToBase64String(outputStream.ToArray())
            End Using
        End Using
        Return encryptedPassword
    End Function

    Public Function Decrypt(ByVal encryptedBytes As String, ByVal secretKey As String) As String
        Dim plainText As String = Nothing
        Using inputStream As MemoryStream = New MemoryStream(Convert.FromBase64String(encryptedBytes))
            Dim algorithm As RijndaelManaged = getAlgorithm(secretKey)
            Using cryptoStream As CryptoStream = New CryptoStream(inputStream, algorithm.CreateDecryptor(), CryptoStreamMode.Read)
                Dim outputBuffer(0 To CType(inputStream.Length - 1, Integer)) As Byte
                Dim readBytes As Integer = cryptoStream.Read(outputBuffer, 0, CType(inputStream.Length, Integer))
                plainText = Encoding.Unicode.GetString(outputBuffer, 0, readBytes)
            End Using
        End Using
        Return plainText
    End Function

    Private Function getAlgorithm(ByVal secretKey As String) As RijndaelManaged
        Const salt As String = "put your salt here"
        Const keySize As Integer = 256

        Dim keyBuilder As Rfc2898DeriveBytes = New Rfc2898DeriveBytes(secretKey, Encoding.Unicode.GetBytes(salt))
        Dim algorithm As RijndaelManaged = New RijndaelManaged()
        algorithm.KeySize = keySize
        algorithm.IV = keyBuilder.GetBytes(CType(algorithm.BlockSize / 8, Integer))
        algorithm.Key = keyBuilder.GetBytes(CType(algorithm.KeySize / 8, Integer))
        algorithm.Padding = PaddingMode.PKCS7
        Return algorithm
    End Function
End Class

如果您将加密值存储在文本文件、XML 文件甚至数据库中,通常使用 Base-64 会更容易,就像这样。

【讨论】:

  • -1 您的代码中的随机加盐并不是一个真正不同的主题,也不是理想情况下的必要条件,您正在从与密钥相同的输入生成 IV,因此任何重复使用的具有恒定加盐的密码将始终有相同的IV。这破坏了 CBC 的语义安全性——IV 必须是每个键唯一且不可预测的,这是 CBC 的基本规则。
  • 你为我节省了很多时间。谢谢你的回答。
【解决方案2】:

存在处理加密细节的高级加密库,因此您不会犯这些错误,KeyczarNaclGPGME

我移植了Keyczar to .net,它使用 AES 作为默认对称加密。

您使用命令行程序使用随机 AES 密钥创建密钥集。

:> KeyczarTool.exe create --location=path_to_key_set --purpose=crypt
:> KeyczarTool.exe addkey --location=path_to_key_set --status=primary

在你的项目中进行加密,

Using encrypter As New Encrypter("path_to_key_set")
     Return encrypter.Encrypt(plaintext)
End Using

然后解密

Using crypter As new Crypter("path_to_key_set")
     Return crypter.Decrypt(ciphertext)
End Using

【讨论】:

    猜你喜欢
    • 2019-01-02
    • 1970-01-01
    • 2011-08-24
    • 1970-01-01
    • 2011-02-28
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多