Introduction
There are many, many examples of how to do encryption and decryption in .NET. So why one more? Well, for one thing, I find that the majority of good code examples of any type are issued in C#. This isn't surprising, since those from a C++ or Java background will have an easier transition to C# than a similarly experienced Visual Basic developer moving to VB.NET. It will take time for the VB.NET community to develop into what the C++ and Java community already has at its disposal. So, I thought that a solid, simple VB.NET example would do well.
Overview
This code example does four things that I think are missing from the examples that I have seen so far:
- It's written in Visual Basic .NET. Not that it is in any way superior or inferior to C#, but most of the other examples (and all of the good ones) were done in C#.
- It uses the UTF-8 encoder to ensure that the strings which are encrypted or decrypted are in an 8-bit format. Many examples that I see use the ASCII encoding, which is a 7-bit format. When you combine this with TripleDES (which uses 3, 8-bit blocks for the key), you can get yourself into situations where you cannot decrypt something you encrypted.
- It uses the
Convert
object's Base-64 methods to make sure that the encrypted text is output in such a way that it can be easily stored in text files and/or database fields without the risk of your encrypted content being inadvertently modified by implicit conversions.
- It centralizes the actual encryption and decryption functionality into a single method, thus eliminating what would otherwise be 99% redundant code.
The Code
The complete cTripleDES
class in VB.NET:
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography
Friend Class cTripleDES
Private m_des As New TripleDESCryptoServiceProvider
Private m_utf8 As New UTF8Encoding
Private m_key() As Byte
Private m_iv() As Byte
Public Sub New(ByVal key() As Byte, ByVal iv() As Byte)
Me.m_key = key
Me.m_iv = iv
End Sub
Public Function Encrypt(ByVal input() As Byte) As Byte()
Return Transform(input, m_des.CreateEncryptor(m_key, m_iv))
End Function
Public Function Decrypt(ByVal input() As Byte) As Byte()
Return Transform(input, m_des.CreateDecryptor(m_key, m_iv))
End Function
Public Function Encrypt(ByVal text As String) As String
Dim input() As Byte = m_utf8.GetBytes(text)
Dim output() As Byte = Transform(input, _
m_des.CreateEncryptor(m_key, m_iv))
Return Convert.ToBase64String(output)
End Function
Public Function Decrypt(ByVal text As String) As String
Dim input() As Byte = Convert.FromBase64String(text)
Dim output() As Byte = Transform(input, _
m_des.CreateDecryptor(m_key, m_iv))
Return m_utf8.GetString(output)
End Function
Private Function Transform(ByVal input() As Byte, _
ByVal CryptoTransform As ICryptoTransform) As Byte()
Dim memStream As MemoryStream = New MemoryStream
Dim cryptStream As CryptoStream = New _
CryptoStream(memStream, CryptoTransform, _
CryptoStreamMode.Write)
cryptStream.Write(input, 0, input.Length)
cryptStream.FlushFinalBlock()
memStream.Position = 0
Dim result(CType(memStream.Length - 1, System.Int32)) As Byte
memStream.Read(result, 0, CType(result.Length, System.Int32))
memStream.Close()
cryptStream.Close()
Return result
End Function
End Class
The complete cTripleDES
class in C#:
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
namespace Utilities.Crypto
{
class cTripleDES
{
private TripleDESCryptoServiceProvider m_des =
new TripleDESCryptoServiceProvider();
private UTF8Encoding m_utf8 = new UTF8Encoding();
private byte[] m_key;
private byte[] m_iv;
public cTripleDES(byte[] key, byte[] iv)
{
this.m_key = key;
this.m_iv = iv;
}
public byte[] Encrypt(byte[] input)
{
return Transform(input,
m_des.CreateEncryptor(m_key, m_iv));
}
public byte[] Decrypt(byte[] input)
{
return Transform(input,
m_des.CreateDecryptor(m_key, m_iv));
}
public string Encrypt(string text)
{
byte[] input = m_utf8.GetBytes(text);
byte[] output = Transform(input,
m_des.CreateEncryptor(m_key, m_iv));
return Convert.ToBase64String(output);
}
public string Decrypt(string text)
{
byte[] input = Convert.FromBase64String(text);
byte[] output = Transform(input,
m_des.CreateDecryptor(m_key, m_iv));
return m_utf8.GetString(output);
}
private byte[] Transform(byte[] input,
ICryptoTransform CryptoTransform)
{
MemoryStream memStream = new MemoryStream();
CryptoStream cryptStream = new CryptoStream(memStream,
CryptoTransform, CryptoStreamMode.Write);
cryptStream.Write(input, 0, input.Length);
cryptStream.FlushFinalBlock();
memStream.Position = 0;
byte[] result = memStream.ToArray();
memStream.Close();
cryptStream.Close();
return result;
}
}
}
Using the cTripleDES
class in VB.NET:
Private ReadOnly key() As Byte = _
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, _
15, 16, 17, 18, 19, 20, 21, 22, 23, 24}
Private ReadOnly iv() As Byte = {8, 7, 6, 5, 4, 3, 2, 1}
Private des As New cTripleDES(key, iv)
Private ReadOnly encryptedData As String = "++XIiGymvbg="
Private decryptedData As String = des.Decrypt(encryptedData)
Private newEncryptedData As String = des.Encrypt(decryptedData)
Using the cTripleDES
class in C#:
byte[] key = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
byte[] iv = {8, 7, 6, 5, 4, 3, 2, 1};
cTripleDES des = new cTripleDES(key, iv);
string encryptedData = "++XIiGymvbg=";
string decryptedData = des.Decrypt(encryptedData);
string newEncryptedData = des.Encrypt(decryptedData);
Conclusion
Hopefully, this simple, straight-forward example shows how to effectively and efficiently wrap the TripleDES (or any other encryption) functionality in Visual Basic .NET syntax. Of course, the same principles can just as easily be applied to a C#, J#, or managed C++ implementation.
Update (March 17, 2005)
It's been nearly two years since I first published this article and it's gotten a fair number of views, votes, and thanks. I'd like to thank you all for your kindness and, in return, I have updated the article with the much asked-for C# version of the class. Happy coding!