How to create symmetric encryption utility class in ASP.NET in VB.NET

Symmetric encryption algorithms use one key for encrypting and decrypting data. You can create a utility class that performs the encryption and decryption of sensitive data:

Imports System

Imports System.IO

Imports System.Text

Imports System.Security.Cryptography

 

Public NotInheritable Class SymmetricEncryptionUtility

Private Sub New()

End Sub

Private Shared _ProtectKey As Boolean

Private Shared _AlgorithmName As String

‘ You can use this property to specify the name of the algorithm (DES, TripleDES, Rijndael and RC2 )

Public Shared Property AlgorithmName() As String

Get

Return _AlgorithmName

End Get

Set(value As String)

_AlgorithmName = value

End Set

End Property

‘ You can use this property to specify whether the key should be protected through the DPAPI.

Public Shared Property ProtectKey() As Boolean

Get

Return _ProtectKey

End Get

Set(value As Boolean)

_ProtectKey = value

End Set

End Property

Public Shared Sub GenerateKey(TargetFile As String)

End Sub

Public Shared Sub ReadKey(Algorithm As SymmetricAlgorithm, KeyFile As String)

End Sub

Public Shared Function EncryptData(Data As String, KeyFile As String) As Byte()

End Function

Public Shared Function DecryptData(Data As Byte(), KeyFile As String) As String

End Function

End Class

 

Because the class is a utility class with static members only, you can make it a static class. To use this class, you must:

1. Set the algorithm name.

2. Generate a key if none exists.

3. Call the EncryptData and DecryptData methods, which internally call the ReadKey method for initializing the algorithm.

 

You can generate encryption keys through the algorithm classes and the GenerateKey() method looks like this:

 

Public Shared Sub GenerateKey(TargetFile As String)

‘ Create the algorithm

Dim Algorithm As SymmetricAlgorithm = SymmetricAlgorithm.Create(AlgorithmName)

Algorithm.GenerateKey()

 

‘ Get the key

Dim Key As Byte() = Algorithm.Key

 

If ProtectKey Then

‘ Use DPAPI to encrypt key

Key = ProtectedData.Protect(Key, Nothing, DataProtectionScope.LocalMachine)

End If

‘ Store the key in a file called key.config

Using fs As New FileStream(targetFile, FileMode.Create)

fs.Write(Key, 0, Key.Length)

End Using

End Sub

 

The ReadKey method reads the key from the file created by the GenerateKey method, as follows:

 

Public Shared Sub ReadKey(Algorithm As SymmetricAlgorithm, KeyFile As String)

Dim Key As Byte()

Using Fs As New FileStream(KeyFile, FileMode.Open)

Key = New Byte(Fs.Length – 1) {}

Fs.Read(Key, 0, CInt(Fs.Length))

End Using

If ProtectKey Then

Algorithm.Key = ProtectedData.Unprotect(Key, Nothing, DataProtectionScope.LocalMachine)

Else

Algorithm.Key = Key

End If

End Sub

 

You can use EncryptData method to encrypt a string to a byte array:

 

Public Shared Function EncryptData(Data As String, KeyFile As String) As Byte()

 

‘ Convert string data to byte array, because all the encryption functions of the algorithms

‘ require byte arrays as input parameters, by using Encoding class of System.Text namespace

 

Dim ClearData As Byte() = System.Text.Encoding.UTF8.GetBytes(Data)

 

‘ Create the algorithm according to the AlgorithmName property of the class.

‘ This value can be one of the names RC2, Rijndael, DES, or TripleDES.

‘ The factory method of the SymmetricAlgorithm creates the appropriate instance, while you can register

‘ additional cryptography classes through the <cryptographySettings> section in the machine.config file.

 

Dim Algorithm As SymmetricAlgorithm = SymmetricAlgorithm.Create(AlgorithmName)

ReadKey(Algorithm, KeyFile)

 

‘ Encrypt information. In this case you use memory stream as the target of your encryption operation

Dim Target As New MemoryStream()

 

‘ Generate a random initialization vector (IV) to use for the algorithm

Algorithm.GenerateIV()

Target.Write(Algorithm.IV, 0, Algorithm.IV.Length)

 

‘ Encrypt actual data

Dim Cs As New CryptoStream(Target, Algorithm.CreateEncryptor(), CryptoStreamMode.Write)

Cs.Write(ClearData, 0, ClearData.Length)

Cs.FlushFinalBlock()

 

‘ Return the encrypted stream of data as a byte array

Return Target.ToArray()

End Function

 

 

Important note:

In the code above GenerateIV method is used. If your application exchanges the same information multiple times between a client and a server, simple encryption will always result in the same encrypted representation of the information. This makes brute-force attacks easier. To add some sort of random information, symmetric algorithms support IV. These IVs are not only added to the encrypted stream of bytes themselves but are also used as input for encrypting the first block of data. When you are using the CryptoStream for encrypting information, you should call the FlushFinalBlock method to make sure that the last block of encrypted data is written appropriately to the target. You have to add the IV itself to the encrypted set of bytes because you need the information later to be able to decrypt the encrypted content entirely.

You can use DecryptData method to decrypt a byte array to a string:

 

Public Shared Function DecryptData(Data As Byte(), KeyFile As String) As String

‘ Create the algorithm

Dim Algorithm As SymmetricAlgorithm = SymmetricAlgorithm.Create(AlgorithmName)

ReadKey(Algorithm, KeyFile)

 

‘ Decrypt information

Dim Target As New MemoryStream()

 

‘ Read IV and initialize the algorithm with it

Dim ReadPos As Integer = 0

Dim IV As Byte() = New Byte(Algorithm.IV.Length – 1) {}

Array.Copy(Data, IV, IV.Length)

Algorithm.IV = IV

ReadPos += Algorithm.IV.Length

 

Dim Cs As New CryptoStream(Target, Algorithm.CreateDecryptor(), CryptoStreamMode.Write)

Cs.Write(Data, ReadPos, Data.Length – ReadPos)

Cs.FlushFinalBlock()

 

‘ Get the bytes from the memory stream and convert them to text

Return Encoding.UTF8.GetString(Target.ToArray())

End Function