Standard library for AES encryption for VB.NET?

18,032

Solution 1

The System.Security.Cryptography namespace contains all the classes you need to perform most standard encryption tasks. Unfortunately, since encryption is a rather complicated topic, the classes are somewhat difficult to work with--especially for beginners. It's sometimes difficult to find a simple working example to start with. But, since I'm nice, I'll provide you with a simple example that you can play with and improve upon :)

The class you probably want to use is called RijndaelManaged. That is the class that implements the typical AES encryption. Here's a sample class that uses that to convert between plain text strings and byte arrays:

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

You should change the salt constant to something else. Ideally, it wouldn't even be a constant, since, to make it as secure as possible, you should use a different salt each time you perform the encryption, but that's a whole other topic.

If you want to have the encrypted value returned as a string instead of as a byte array, you can use Base-64 encoding to convert the byte array to, and from, strings, like this:

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

If you are storing the encrypted value in a text file, XML file, or even a database, it's often easier to just use Base-64, like that.

Solution 2

There exist high-level encryption libraries that handle the subtle details of encryption so you don't make those mistakes, Keyczar, Nacl, GPGME.

I ported Keyczar to .net and it uses AES for it's default symmetric encryption.

You use a command line program to create a key set with a random AES key.

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

In your project to encrypt,

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

And then to decrypt

Using crypter As new Crypter("path_to_key_set")
     Return crypter.Decrypt(ciphertext)
End Using
Share:
18,032
ysj
Author by

ysj

Updated on June 12, 2022

Comments

  • ysj
    ysj almost 2 years

    Is there a standard library to use for AES encryption for VB.NET? I want to encrypt a string with a static private key.

    I googled and found a lot of variations. I don't really know how to determine which algorithms are secure or not.