Return to HomePage



Decrypt a string via a block cipher using 3DES (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 code sample demonstrates the use of Triple DES, which should primarily be used for backwards compatibility with other applications and replaced with AES in newer implementations of code.

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

Scenarios

* Application developer desires confidentiality for data in storage or in transit.
* 3DES should only be used in implementations which require backwards compatibility for interaction with applications that do not implement the new NIST encryption standard, AES.



Solution Example


		        Public Function [DecryptString(ByVal] ciphertext As String, [ByVal] sKey() As Byte, [ByVal] sIV() As Byte) As String
		            ' The default 3DES key size under the .NET framework is 192 (168).  The following
		            ' call will create a 3DES 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 tdes As [TripleDESCryptoServiceProvider] = [CType(TripleDESCryptoServiceProvider.Create(),] [TripleDESCryptoServiceProvider)]
	

		            'Set secret key For 3DES algorithm.
		            tdes.Key = sKey
	

		            'Set initialization vector.
		            tdes.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,tdes.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 tdes As [TripleDESCryptoServiceProvider] = [CType(TripleDESCryptoServiceProvider.Create(),] [TripleDESCryptoServiceProvider)]
	

		            'Set secret key For 3DES algorithm.
		            tdes.Key = ASCIIEncoding.ASCII.GetBytes("ASAMPLEKEYWEUSETOENCRYPT")
		            'We don't use an IV because the book doesn't show us an example using a 
		            'more secure, chained mode!
		            ' tdes.IV = ASCIIEncoding.ASCII.GetBytes("SAMPLEIV");
	

		            'Set encryption mode to an unchained value (because the book says so!)
		            tdes.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,tdes.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 block 64 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 tdes As [TripleDESCryptoServiceProvider] = [CType(TripleDESCryptoServiceProvider.Create(),] [TripleDESCryptoServiceProvider)]
	

		            ' 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
		                tdes.GenerateIV()
		                enc = [EncryptString(p1,] tdes.Key, tdes.IV)
		                Console.WriteLine("Encrypted text #{0}: " + enc, i)
		                p2 = [DecryptString(enc,] tdes.Key, tdes.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 3DES encryption keys and initialization vectors are chosen at random during the call to TripleDESCryptoServiceProvider.Create().
* In a real-world implementation Key and IV 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: f9n80d72AC1oD2b9a8yux/66UKaquzQLvQIV0A5xmtqded6hOKY5WFmcqtXOa0KH
Plaintext #0: the quick brown fox jumped over the lazy dog
Encrypted text #1: jloSmkMYW7TWXgnNKiNw/JCzzjIwm1K9DeyaFBbMfO9IOMMFcg9s0x917Bm0mBgg
Plaintext #1: the quick brown fox jumped over the lazy dog
Encrypted text #2: zpRBQWz8ntpONAS+4tJKgEC88ntgj5esTizWUH4h9sQKkZDxxJ4qM6Y9yEugGH8c
Plaintext #2: the quick brown fox jumped over the lazy dog
Encrypted text #3: 4ssPSATxEbOBucRtbDcHq7SLurzknsZijpcMTg0puMthnPmI93mrbRQgfvOzbJEk
Plaintext #3: the quick brown fox jumped over the lazy dog
Encrypted text #4: sxKZ3VDJP6SZw/IwznpH1VgRrEYozcsntVJ6pnw75YqD7xb/WW33xeT4Q7Pf
Plaintext #4: the quick brown fox jumped over the lazy dog

Problem test cases - notice repetitive encrypted value
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Encrypted text #0: z0N6RlMZ2FLwaSQLDkyIHaxEsirAX68xE2cwZcHqh2CyE1zjjoGfMSTnnxOIVO
Plaintext #0: the quick brown fox jumped over the lazy dog
Encrypted text #1: z0N6RlMZ2FLwaSQLDkyIHaxEsirAX68xE2cwZcHqh2CyE1zjjoGfMSTnnxOIVO
Plaintext #1: the quick brown fox jumped over the lazy dog
Encrypted text #2: z0N6RlMZ2FLwaSQLDkyIHaxEsirAX68xE2cwZcHqh2CyE1zjjoGfMSTnnxOIVO
Plaintext #2: the quick brown fox jumped over the lazy dog
Encrypted text #3: z0N6RlMZ2FLwaSQLDkyIHaxEsirAX68xE2cwZcHqh2CyE1zjjoGfMSTnnxOIVO
Plaintext #3: the quick brown fox jumped over the lazy dog
Encrypted text #4: z0N6RlMZ2FLwaSQLDkyIHaxEsirAX68xE2cwZcHqh2CyE1zjjoGfMSTnnxOIVO
Plaintext #4: the quick brown fox jumped over the lazy dog


More Information

* 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
Microsoft Communities