Return to
HomePage
Decrypt a string via a block cipher using AES (VB.NET)
Applies to
* .NET Framework 2.0
* VB.NET
Summary
The purpose of this code is to demonstrate the proper use of a symmetric block cipher to decrypt strings of text within an application. This test case utilizes AES (Rijndael) which serves as the current NIST encryption standard.
Objectives
* To provide confidentiality of data which is transmitted over insecure or untrusted communication channels.
* To provide confidentiality of data in storage until it is needed by a user or application
Solution Example
Public Function [DecryptString(ByVal] ciphertext As String, [ByVal] sKey() As Byte, [ByVal] sIV() As Byte) As String
' The default AES key size under the .NET framework is 256. The following
' call will create an AES crypto provider and create a random initialization
' vector and key. The crypto mode defaults to CBC ensuring the proper chaining
' of data to mitigate repetition of cipher text blocks.
Dim rijndaelAlg As Rijndael = Rijndael.Create()
'Set secret key For AES algorithm.
rijndaelAlg.Key = sKey
'Set initialization vector.
rijndaelAlg.IV = sIV
'Create a memorystream to which we'll decrypt our input string
Dim ms As [MemoryStream] = New [MemoryStream()]
Dim ecs As [CryptoStream] = New [CryptoStream(ms,rijndaelAlg.CreateDecryptor(),CryptoStreamMode.Write)]
'Because the input string is passed in as a Base64 encoded value we decode prior writing to
'the decryptor stream.
[ecs.Write(Convert.FromBase64String(ciphertext),] 0, [Convert.FromBase64String(ciphertext).Length)]
ecs.Close()
Return [ASCIIEncoding.ASCII.GetString(ms.ToArray())]
End Function
Problem Example
The following example demonstrates an implementation of a Decryption routine containing several common
secure coding issues.
Public Function [ProblematicDecryptString(ByVal] ciphertext As String) As String
Dim rijndaelAlg As Rijndael = Rijndael.Create()
'Set secret key for the AES algorithm.
rijndaelAlg.Key = ASCIIEncoding.ASCII.GetBytes("_A_SAMPLE_KEY_WE_USE_TO_ENCRYPT_")
'We don't use an IV because the book doesn't show us an example using a
'more secure, chained mode! If the book told us to jump off a bridge we probably would.
' rijndaelAlg.IV = ASCIIEncoding.ASCII.GetBytes("SAMPLEIV");
'Set encryption mode to an unchained value (because the book says so!)
rijndaelAlg.Mode = [CipherMode.ECB]
'Create a memorystream to which we'll decrypt our input string
Dim ms As [MemoryStream] = New [MemoryStream()]
Dim ecs As [CryptoStream] = New [CryptoStream(ms,rijndaelAlg.CreateDecryptor(),CryptoStreamMode.Write)]
'Because the input string is passed in as a Base64 encoded value we decode prior writing to
'the decryptor stream.
[ecs.Write(Convert.FromBase64String(ciphertext),] 0, [Convert.FromBase64String(ciphertext).Length)]
ecs.Close()
Return [ASCIIEncoding.ASCII.GetString(ms.ToArray())]
End Function
* Cleartext encryption key can be extracted by any user with access to the source code or compiled code
* Use of a weak encryption (non-random) key, which can be brute-forced using a dictionary attack
* Insecure cipher mode (ECB), performs encryption of each blocks 128 bits independently with no
feedback into subsequent blocks as CBC and other chained modes do. An attacker can rearrange or replace blocks with previous blocks they observe.
* ECB mode does not utilize an initialization vector, yielding the same encrypted value for each plaintext value. An attacker can thus observe patterns in the encrypted blocks and perform known plaintext attacks Note: Initialization vectors need not remain secret however they should be random for each encrypted value of the plaintext)
Test Case
The following classes must be included in any project making use of the sample code provided above:
Imports System
Imports System.Text
Imports System.IO
Imports System.Security.Cryptography
The following test case demonstrates the use of the
DecryptString function
Sub [Main(ByVal] args() As String)
Dim enc As String,p2 As String,probenc As String,probp2 As String = Nothing
Dim aes As Rijndael = Rijndael.Create()
' Test case for string encryption routines
Dim p1 As String = "the quick brown fox jumped over the lazy dog"
' Run our test case multiple times to demonstrate different IV / encrypted text for each
' iteration in when using proper crypto modes.
Console.Out.WriteLine("Solution test cases - notice varied output for static input")
Console.Out.WriteLine("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-")
Dim i As Integer
For i = 0 To 5- 1 Step i + 1
aes.GenerateIV()
enc = [EncryptString(p1,] aes.Key, aes.IV)
Console.WriteLine("Encrypted text #{0}: " + enc, i)
p2 = [DecryptString(enc,] aes.Key, aes.IV)
Console.WriteLine("Plaintext #{0}: " + p2, i)
If Not p1.Equals(p2) Then
Console.Error.WriteLine("Decryption failed")
End If
Next
' Now run out problem test cases
Console.Out.WriteLine("Problem test cases - notice repetitive encrypted value")
Console.Out.WriteLine("-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-")
Dim i As Integer
For i = 0 To 5- 1 Step i + 1
probenc = [ProblematicEncryptString(p1)]
probp2 = [ProblematicDecryptString(probenc)]
Console.WriteLine("Encrypted text #{0}: " + probenc, i)
Console.WriteLine("Plaintext #{0}: " + probp2, i)
Next
End Sub
* In this test case AES encryption keys and initialization vectors are chosen at random during the call to Rijndael.Create().
* In a real-world implementation sKey and sIV should be retrieved from the Data Protection API within application code please refer to code sample demonstrating use of Data Protection API.
Expected Result
Solution test cases - notice varied output for static input
Encrypted text #0: PSQ7SRIFtv3W1GzSdsMCWR6ANZVZ78xjMG2ssQpsfyiWDMY3Wf+15Icd4XDEKhe8
Plaintext #0: the quick brown fox jumped over the lazy dog
Encrypted text #1: feBRJPILiia74FQnOpXlpIICYmieLbujF11yTkQyNitUPl35qf0aVd+VjYxyXVCL
Plaintext #1: the quick brown fox jumped over the lazy dog
Encrypted text #2: DfnDt3dO6eq3tdp3OC/5/zs6GN8jm2SUSqy50d1cwsHmQ4R+XsEttzT/7wlXXwuc
Plaintext #2: the quick brown fox jumped over the lazy dog
Encrypted text #3:
lbU6t2jc5eVNBZEr6jQDEpj4/vfrjcqke/94X6pY8mEBlYJ4qyzUJEtFQf96Cm5W Plaintext #3: the quick brown fox jumped over the lazy dog
Encrypted text #4: /by8DZLmxBpkP5fEbGw8UKXz6bmNa2IPedCgpcSdO65uNAf+ujJ2FV2EsZaTg19A
Plaintext #4: the quick brown fox jumped over the lazy dog
Problem test cases - notice repetitive encrypted value
Encrypted text #0: S/PCsy2/87IRuRzAjeHxXw3XUEfhwZ9Ol1Bai1Hy7RqFq9+V6ZIEHlo1IwRQjCVT
Plaintext #0: the quick brown fox jumped over the lazy dog
Encrypted text #1: S/PCsy2/87IRuRzAjeHxXw3XUEfhwZ9Ol1Bai1Hy7RqFq9+V6ZIEHlo1IwRQjCVT
Plaintext #1: the quick brown fox jumped over the lazy dog
Encrypted text #2: S/PCsy2/87IRuRzAjeHxXw3XUEfhwZ9Ol1Bai1Hy7RqFq9+V6ZIEHlo1IwRQjCVT
Plaintext #2: the quick brown fox jumped over the lazy dog
Encrypted text #3: S/PCsy2/87IRuRzAjeHxXw3XUEfhwZ9Ol1Bai1Hy7RqFq9+V6ZIEHlo1IwRQjCVT
Plaintext #3: the quick brown fox jumped over the lazy dog
Encrypted text #4: S/PCsy2/87IRuRzAjeHxXw3XUEfhwZ9Ol1Bai1Hy7RqFq9+V6ZIEHlo1IwRQjCVT
Plaintext #4: the quick brown fox jumped over the lazy dog
Scenarios
* Application developer desires confidentiality for data in storage or in transit.
More Information
* Although AES defaults to 256-bit key sizes under the .NET framework, even under current cryptography standards, the default 128-bit key-size used by many crypto implementations is still considered secure.
* The test case assumes use of the
DataProtection API implemented within the user code to securely store and retrieve encryption keys.
Additional Resources
* Protecting keys using the DPAPI: http://msdn.microsoft.com/library/en-us/dnpag2/html/paght000005.asp
* Cryptography (.NET): http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGGuidelines0003.asp?frame=true#pagguidelines0003_cryptography
Attributes
*
Applies To: .NET Framework 2.0, VB
*
Category: Cryptography
*
Author: George Gal
Return to
HomePage