5

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.

Chad
  • 1,531
  • 3
  • 20
  • 46
ysj
  • 339
  • 2
  • 5
  • 12
  • 4
    Did you even look at the [System.Security.Cryptography](http://msdn.microsoft.com/en-us/library/system.security.cryptography.aspx) namespace? – Oded May 07 '13 at 13:24
  • See http://stackoverflow.com/questions/273452/using-aes-encryption-in-c-sharp – George Johnston May 07 '13 at 13:24
  • @Oded hey.. I came across that site just now.. http://msdn.microsoft.com/en-us/library/system.security.cryptography.aes.aspx I don't really know what to do with the example there.. =x – ysj May 07 '13 at 13:34
  • @ysj can you provide a little more than "I don't really know what to do" ? ... if you have a particular problem, you will find help here ... – DarkSquirrel42 May 07 '13 at 14:14
  • "I wanted to try encrypting a string with a static private key. ... I don't really know how to determine whether their algorithm is secured or not" If you have a static private key stored in your app, then it isn't secure as people can extract it from your application (so the algorithm used to encrypt it doesn't really matter). How are you going to use this encrypted data? – Idle_Mind May 07 '13 at 14:36
  • @Idle_Mind that's the point. That application is purposely made vulnerable to such attacks =x – ysj May 07 '13 at 15:37

2 Answers2

9

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.

Steven Doggart
  • 43,358
  • 8
  • 68
  • 105
  • 1
    -1 Random salt with your code isn't really a different topic nor merely ideally necessary, you are generating your IV from the same input as your key, thus any reused password with a constant salt will always have the same IV. This breaks semantic security of CBC -- an IV must be unique per key and unpredictable, that's a basic rule for CBC. – jbtule May 07 '13 at 18:07
  • You saved me a lot of time. Thank you for your answer. –  Nov 28 '15 at 04:54
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
jbtule
  • 31,383
  • 12
  • 95
  • 128