Click here to Skip to main content
15,897,187 members
Articles / Programming Languages / Visual Basic

Encrypting a dataset using AES, including compression

Rate me:
Please Sign up or sign in to vote.
4.98/5 (49 votes)
21 Aug 2015CPOL7 min read 127.4K   4.8K   127  
Article describes how to encrypt a dataset using AES. Optionally the dataset is compressed before the encryption.
''' <summary>
''' This class handles encryption related operations
''' </summary>
Friend Module Cryptography
   Private passwordDigits As System.Text.RegularExpressions.Regex = New System.Text.RegularExpressions.Regex("\d", System.Text.RegularExpressions.RegexOptions.Compiled)
   Private passwordNonWord As System.Text.RegularExpressions.Regex = New System.Text.RegularExpressions.Regex("\W", System.Text.RegularExpressions.RegexOptions.Compiled)
   Private passwordUppercase As System.Text.RegularExpressions.Regex = New System.Text.RegularExpressions.Regex("[A-Z]", System.Text.RegularExpressions.RegexOptions.Compiled)
   Private passwordLowercase As System.Text.RegularExpressions.Regex = New System.Text.RegularExpressions.Regex("[a-z]", System.Text.RegularExpressions.RegexOptions.Compiled)

   ''' <summary>
   ''' This method calculates the strength of the password
   ''' </summary>
   ''' <param name="password">Password to check</param>
   ''' <returns>Password strength between 0 and 100</returns>
   Friend Function PasswordStrength(password As String) As Integer
      Dim strength As Integer = 0

      If (password.Length > 5) Then strength += 5
      If (password.Length > 10) Then strength += 15
      If (passwordDigits.Matches(password).Count >= 1) Then strength += 5
      If (passwordDigits.Matches(password).Count >= 3) Then strength += 15
      If (passwordNonWord.Matches(password).Count >= 1) Then strength += 5
      If (passwordNonWord.Matches(password).Count >= 3) Then strength += 15
      If (passwordUppercase.Matches(password).Count >= 1) Then strength += 5
      If (passwordUppercase.Matches(password).Count >= 3) Then strength += 15
      If (passwordLowercase.Matches(password).Count >= 1) Then strength += 5
      If (passwordLowercase.Matches(password).Count >= 3) Then strength += 15

      Return strength
   End Function

   ''' <summary>
   ''' This method initializes the Aes used to encrypt or decrypt the dataset.
   ''' </summary>
   ''' <param name="username">Username to use for the encryption</param>
   ''' <param name="password">Password to use for the encryption</param>
   ''' <returns>New instance of Aes</returns>
   Private Function InitAes(username As String, password As String) As System.Security.Cryptography.Aes
      Dim aes As System.Security.Cryptography.Aes = New System.Security.Cryptography.AesManaged()
      Dim rfc2898 As System.Security.Cryptography.Rfc2898DeriveBytes = New System.Security.Cryptography.Rfc2898DeriveBytes(password, System.Text.Encoding.Unicode.GetBytes(username))

      aes.Padding = System.Security.Cryptography.PaddingMode.PKCS7
      aes.KeySize = 128
      aes.Key = rfc2898.GetBytes(16)
      aes.IV = rfc2898.GetBytes(16)

      Return aes
   End Function

   ''' <summary>
   ''' Saves the dataset encrypted in specified file
   ''' </summary>
   ''' <param name="dataSet">Dataset to save</param>
   ''' <param name="username">Username for encryption</param>
   ''' <param name="password">Password for encryption</param>
   ''' <param name="fileName">File name where to save</param>
   ''' <param name="compress">Should the file be compressed</param>
   Friend Sub EncryptDataSet(dataSet As System.Data.DataSet, username As String, password As String, fileName As String, compress As Boolean)
      ' Check the parameters
      If dataSet Is Nothing _
         Or String.IsNullOrEmpty(username) _
         Or String.IsNullOrEmpty(password) _
         Or String.IsNullOrEmpty(fileName) Then
         Throw New System.ArgumentNullException("All arguments must be supplied.")
      End If

      ' Save the dataset as encrypted
      Using aes As System.Security.Cryptography.Aes = Cryptography.InitAes(username, password)
         Using fileStream As System.IO.FileStream = New System.IO.FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite, System.IO.FileShare.None)
            Using cryptoStream As System.Security.Cryptography.CryptoStream = New System.Security.Cryptography.CryptoStream(fileStream, aes.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write)
               If (compress) Then
                  ' when compression is requested, use GZip
                  Using zipStream As System.IO.Compression.GZipStream = New System.IO.Compression.GZipStream(cryptoStream, System.IO.Compression.CompressionMode.Compress)
                     dataSet.WriteXml(zipStream, System.Data.XmlWriteMode.WriteSchema)
                     zipStream.Flush()
                  End Using
               Else
                  dataSet.WriteXml(cryptoStream, System.Data.XmlWriteMode.WriteSchema)
                  cryptoStream.FlushFinalBlock()
               End If
            End Using
         End Using
      End Using
   End Sub

   ''' <summary>
   ''' Reads and decrypts the dataset from the given file
   ''' </summary>
   ''' <param name="dataset">Dataset to read</param>
   ''' <param name="username">Username for decryption</param>
   ''' <param name="password">Password for decryption</param>
   ''' <param name="fileName">File name to read</param>
   ''' <param name="compressed">Is the file compressed</param>
   ''' <returns>XmlReadMode used for reading</returns>
   Friend Function DecryptDataSet(dataset As System.Data.DataSet, username As String, password As String, fileName As String, compressed As Boolean) As System.Data.XmlReadMode
      Dim xmlReadMode As System.Data.XmlReadMode

      ' Check the parameters
      If dataset Is Nothing _
         Or String.IsNullOrEmpty(username) _
         Or String.IsNullOrEmpty(password) _
         Or String.IsNullOrEmpty(fileName) Then
         Throw New System.ArgumentNullException("All arguments must be supplied.")
      End If

      ' Read the dataset and encrypt it
      Using aes As System.Security.Cryptography.Aes = Cryptography.InitAes(username, password)
         Using fileStream As System.IO.FileStream = New System.IO.FileStream(fileName, System.IO.FileMode.Open)
            Using cryptoStream As System.Security.Cryptography.CryptoStream = New System.Security.Cryptography.CryptoStream(fileStream, aes.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Read)
               If (compressed) Then
                  ' when decompression is requested, use GZip
                  Using zipStream As System.IO.Compression.GZipStream = New System.IO.Compression.GZipStream(cryptoStream, System.IO.Compression.CompressionMode.Decompress)
                     xmlReadMode = dataset.ReadXml(zipStream, System.Data.XmlReadMode.ReadSchema)
                  End Using
               Else
                  xmlReadMode = dataset.ReadXml(cryptoStream, System.Data.XmlReadMode.ReadSchema)
               End If
                  End Using
         End Using
         End Using

         Return xmlReadMode
   End Function

   ''' <summary>
   ''' Extension method for a dataset to define WriteXml method with encryption
   ''' </summary>
   ''' <param name="dataSet">The dataset</param>
   ''' <param name="fileName">File name to read</param>
   ''' <param name="userName">Username for encryption</param>
   ''' <param name="password">Password for encryption</param>
   ''' <param name="compress">Should the file be compressed</param>
   <System.Runtime.CompilerServices.Extension()>
   Public Sub WriteXml(dataSet As System.Data.DataSet, fileName As String, userName As String, password As String, compress As Boolean)
      ' Check the parameters
      If dataSet Is Nothing _
         Or String.IsNullOrEmpty(userName) _
         Or String.IsNullOrEmpty(password) _
         Or String.IsNullOrEmpty(fileName) Then
         Throw New System.ArgumentNullException("All arguments must be supplied.")
      End If

      ' Encrypt and save the dataset
      Cryptography.EncryptDataSet(dataSet, userName, password, fileName, compress)
   End Sub

   ''' <summary>
   ''' Extension method for a dataset to define ReadXml method with decryption
   ''' </summary>
   ''' <param name="dataSet">The dataset</param>
   ''' <param name="fileName">File name to read</param>
   ''' <param name="userName">Username for decryption</param>
   ''' <param name="password">Password for decryption</param>
   ''' <param name="compressed">Is the file compressed</param>
   ''' <returns>XmlReadMode used for reading</returns>
   <System.Runtime.CompilerServices.Extension()>
   Public Function ReadXml(dataSet As System.Data.DataSet, fileName As String, userName As String, password As String, compressed As Boolean) As System.Data.XmlReadMode
      ' Check the parameters
      If dataSet Is Nothing _
         Or String.IsNullOrEmpty(userName) _
         Or String.IsNullOrEmpty(password) _
         Or String.IsNullOrEmpty(fileName) Then
         Throw New System.ArgumentNullException("All arguments must be supplied.")
      End If

      ' Decrypt the saved dataset
      Return Cryptography.DecryptDataSet(dataSet, userName, password, fileName, compressed)
   End Function
End Module

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Europe Europe
Biography provided

Comments and Discussions