Click here to Skip to main content
15,884,836 members
Articles / Programming Languages / Visual Basic
Article

Making TripleDES Simple in Visual Basic .NET

Rate me:
Please Sign up or sign in to vote.
4.60/5 (56 votes)
17 Mar 20062 min read 459.5K   98   111
This is a simple wrapper class that provides an easy interface for encrypting and decrypting byte arrays and strings.

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:

VB
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography

Friend Class cTripleDES

    ' define the triple des provider
    Private m_des As New TripleDESCryptoServiceProvider

    ' define the string handler
    Private m_utf8 As New UTF8Encoding

    ' define the local property arrays
    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()
        ' create the necessary streams
        Dim memStream As MemoryStream = New MemoryStream
        Dim cryptStream As CryptoStream = New _
            CryptoStream(memStream, CryptoTransform, _
            CryptoStreamMode.Write)
        ' transform the bytes as requested
        cryptStream.Write(input, 0, input.Length)
        cryptStream.FlushFinalBlock()
        ' Read the memory stream and convert it back into byte array
        memStream.Position = 0
        Dim result(CType(memStream.Length - 1, System.Int32)) As Byte
        memStream.Read(result, 0, CType(result.Length, System.Int32))
        ' close and release the streams
        memStream.Close()
        cryptStream.Close()
        ' hand back the encrypted buffer
        Return result
    End Function

End Class

The complete cTripleDES class in C#:

C#
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

namespace Utilities.Crypto
{
    class cTripleDES
    {
        // define the triple des provider
        private TripleDESCryptoServiceProvider m_des = 
                 new TripleDESCryptoServiceProvider();

        // define the string handler
        private UTF8Encoding m_utf8 = new UTF8Encoding();

        // define the local property arrays
        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)
        {
            // create the necessary streams
            MemoryStream memStream = new MemoryStream();
            CryptoStream cryptStream = new CryptoStream(memStream, 
                         CryptoTransform, CryptoStreamMode.Write);
            // transform the bytes as requested
            cryptStream.Write(input, 0, input.Length);
            cryptStream.FlushFinalBlock();
            // Read the memory stream and
            // convert it back into byte array
            memStream.Position = 0;
            byte[] result = memStream.ToArray();
            // close and release the streams
            memStream.Close();
            cryptStream.Close();
            // hand back the encrypted buffer
            return result;
        }
    }
} 

Using the cTripleDES class in VB.NET:

VB
' define the local key and vector byte arrays
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}

' instantiate the class with the arrays
Private des As New cTripleDES(key, iv)

' for the example, define a variable with the encrypted value
Private ReadOnly encryptedData As String = "++XIiGymvbg="

' now, decrypt the data
Private decryptedData As String = des.Decrypt(encryptedData)

' the value of decryptedData should be "test",
' but for our example purposes, let's re-encrypt it
Private newEncryptedData As String = des.Encrypt(decryptedData)

Using the cTripleDES class in C#:

C#
// define the local key and vector byte arrays
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};

// instantiate the class with the arrays
cTripleDES des = new cTripleDES(key, iv);

// for the example, define a variable with the encrypted value
string encryptedData = "++XIiGymvbg=";

// now, decrypt the data
string decryptedData = des.Decrypt(encryptedData);

// the value of decryptedData should be "test",
// but for our example purposes, let's re-encrypt it
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!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect Wyvern Software
United States United States
Tony Selke is an independant consultant who has spent the last 20 years working with Microsoft technologies (VB, VC++, ASP, J++, C#, VB.NET, SQL Server, etc.) to develop solutions used in all kinds of market verticals (industrial, pharmaceutical, financial, marketing, multimedia, educational, telecommunications, etc.). He obtained his first MCSD certification in 1998 and his second in 2004, with an MCDBA in 2005. In addition, he has taught courses for MCSD certification students as well as programming classes at Penn State University.

Comments and Discussions

 
GeneralMy vote of 5 Pin
AdminDatabase Iknow8-Mar-23 22:14
AdminDatabase Iknow8-Mar-23 22:14 
Question2 different key can decrypt data Pin
Türker TUNALI24-Jan-13 21:41
Türker TUNALI24-Jan-13 21:41 
GeneralMy vote of 5 Pin
Richard Osafo2-Jun-12 8:07
Richard Osafo2-Jun-12 8:07 
QuestionNo good dead goes unpunished??? Pin
Tom Hawkins20-Sep-11 9:55
Tom Hawkins20-Sep-11 9:55 
AnswerRe: No good dead goes unpunished??? Pin
Tony Selke21-Sep-11 1:41
Tony Selke21-Sep-11 1:41 
GeneralRe: No good dead goes unpunished??? Pin
Tom Hawkins22-Sep-11 8:34
Tom Hawkins22-Sep-11 8:34 
GeneralSimplified Transform() Function Pin
peterhar122-May-11 4:57
peterhar122-May-11 4:57 
AnswerRe: Simplified Transform() Function Pin
Tony Selke22-May-11 5:49
Tony Selke22-May-11 5:49 
GeneralMy vote of 5 Pin
Michael Rawi30-Mar-11 18:03
Michael Rawi30-Mar-11 18:03 
QuestionDo you need to setup IDisposable (Dispose Pattern) in your class? and how? Pin
danvmn4-Feb-11 6:35
danvmn4-Feb-11 6:35 
AnswerRe: Do you need to setup IDisposable (Dispose Pattern) in your class? and how? Pin
Tony Selke4-Feb-11 6:55
Tony Selke4-Feb-11 6:55 
GeneralRe: Do you need to setup IDisposable (Dispose Pattern) in your class? and how? Pin
danvmn4-Feb-11 7:27
danvmn4-Feb-11 7:27 
GeneralBad encrypt decrypt Pin
onkie breed25-Dec-10 12:15
onkie breed25-Dec-10 12:15 
AnswerRe: Bad encrypt decrypt [modified] Pin
Tony Selke4-Feb-11 7:13
Tony Selke4-Feb-11 7:13 
GeneralRe: Bad encrypt decrypt Pin
danvmn4-Feb-11 7:35
danvmn4-Feb-11 7:35 
I added a more secure class to the above for two options:

public class cRijndael
// Rijndael managed algorithm supports key lengths of 128, 192, or 256 bits.  Initial Vector must be 16 bytes.
// Rijndael encrypts data at 256 bit secuirty.
{
    // define the symetrical crypto provider
    private RijndaelManaged m_des = new RijndaelManaged();  // AES (Rijndael).  Pure .NET implementation.
    // default for RijndaelManaged: block size = 128, PaddingMode = PKCS7, CipherMode = CBC

    // define the string handler
    private UTF8Encoding m_utf8 = new UTF8Encoding();

    // define the local property arrays
    private byte[] m_key;  // Rijndael managed algorithm supports key lengths of 128, 192, or 256 bits.
    private byte[] m_iv;   // must be 16 bytes.

    public cRijndael(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 byte[] Decrypt(byte[] input, CipherMode cm, PaddingMode pm, int KeySize, int BlockSize)
    {
        m_des.Mode = cm;                // default = CBC
        m_des.Padding = pm;             // default = PKCS7.  PKCS7 DotNet = PKCS5 Java for blocksize < 256 I think.
        m_des.KeySize = KeySize;        // default = 256
        m_des.BlockSize = BlockSize;    // default = 128
        m_des.FeedbackSize = BlockSize; // default = 128.  feedback size cannot be greater than BlockSize.)

        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);
    }

    public string Decrypt(string text, CipherMode cm, PaddingMode pm, int KeySize, int BlockSize)
    {
        m_des.Mode = cm;                // default = CBC
        m_des.Padding = pm;             // default = PKCS7.  PKCS7 DotNet = PKCS5 Java for blocksize < 256 I think.
        m_des.KeySize = KeySize;        // default = 256
        m_des.BlockSize = BlockSize;    // default = 128
        m_des.FeedbackSize = BlockSize; // default = 128.  feedback size cannot be greater than BlockSize.

        byte[] input = Convert.FromBase64String(text);
        byte[] output = Transform(input, m_des.CreateDecryptor(m_key, m_iv));
        return m_utf8.GetString(output);
    }

    public bool Encrypt(string sourceFile, string destFile)
    {
        try
        {
            byte[] input = File.ReadAllBytes(sourceFile);
            byte[] output = Transform(input, m_des.CreateEncryptor(m_key, m_iv));
            File.WriteAllBytes(destFile, output);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }


    public bool Encrypt(string sourceFile, string destFile, CipherMode cm, PaddingMode pm, int KeySize, int BlockSize)
    {
        m_des.Mode = cm;                // default = CBC
        m_des.Padding = pm;             // default = PKCS7.  PKCS7 DotNet = PKCS5 Java for blocksize < 256 I think.
        m_des.KeySize = KeySize;        // default = 256
        m_des.BlockSize = BlockSize;    // default = 128
        m_des.FeedbackSize = BlockSize; // default = 128.  feedback size cannot be greater than BlockSize.

        try
        {
            byte[] input = File.ReadAllBytes(sourceFile);
            byte[] output = Transform(input, m_des.CreateEncryptor(m_key, m_iv));
            File.WriteAllBytes(destFile, output);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    public bool Decrypt(string sourceFile, string destFile)
    {
        try
        {
            byte[] input = File.ReadAllBytes(sourceFile);
            byte[] output = Transform(input, m_des.CreateDecryptor(m_key, m_iv));
            File.WriteAllBytes(destFile, output);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    public bool Decrypt(string sourceFile, string destFile, CipherMode cm, PaddingMode pm, int KeySize, int BlockSize)
    {
        m_des.Mode = cm;                // default = CBC
        m_des.Padding = pm;             // default = PKCS7.  PKCS7 DotNet = PKCS5 Java for blocksize < 256 I think.
        m_des.KeySize = KeySize;        // default = 256
        m_des.BlockSize = BlockSize;    // default = 128
        m_des.FeedbackSize = BlockSize; // default = 128.  feedback size cannot be greater than BlockSize.
        try
        {
            byte[] input = File.ReadAllBytes(sourceFile);
            byte[] output = Transform(input, m_des.CreateDecryptor(m_key, m_iv));

            File.WriteAllBytes(destFile, output);

            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }


    private byte[] Transform(byte[] input, ICryptoTransform CryptoTransform)
    {
        // create the necessary streams
      using (MemoryStream memStream = new MemoryStream())
      {
        using (CryptoStream cryptStream = new CryptoStream(memStream, CryptoTransform, CryptoStreamMode.Write))
        {
          // transform the bytes as requested
          cryptStream.Write(input, 0, input.Length);
          cryptStream.FlushFinalBlock();

          // Read the memory stream and convert it back into byte array
          memStream.Position = 0;
          byte[] result = memStream.ToArray();

          // memStream.Close();    // redundant now with using
          // cryptStream.Close();  // redundant now with using

          // hand back the encrypted buffer
          return result;
        } // using - release the stream
      } // using - release the stream
    } // private byte[] Transform(..)
} // class cRijndael

AnswerRe: Bad encrypt decrypt Pin
Tony Selke4-Feb-11 7:39
Tony Selke4-Feb-11 7:39 
GeneralRe: Bad encrypt decrypt Pin
danvmn7-Feb-11 7:29
danvmn7-Feb-11 7:29 
QuestionOne step more Pin
LadyReader1-Dec-10 5:11
LadyReader1-Dec-10 5:11 
AnswerRe: One step more Pin
Tony Selke1-Dec-10 5:30
Tony Selke1-Dec-10 5:30 
GeneralRe: One step more Pin
LadyReader1-Dec-10 7:31
LadyReader1-Dec-10 7:31 
GeneralTripleDESCryptoServiceProvider Pin
Jim317-Aug-10 7:41
Jim317-Aug-10 7:41 
GeneralRe: TripleDESCryptoServiceProvider Pin
Tony Selke7-Aug-10 7:44
Tony Selke7-Aug-10 7:44 
GeneralEncryption on windows mobile device using the compact framework.... [modified] Pin
dmetzgar19-Nov-09 6:26
dmetzgar19-Nov-09 6:26 
AnswerRe: Encryption on windows mobile device using the compact framework.... Pin
Tony Selke19-Nov-09 6:46
Tony Selke19-Nov-09 6:46 
GeneralRe: Encryption on windows mobile device using the compact framework.... Pin
dmetzgar19-Nov-09 6:48
dmetzgar19-Nov-09 6:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.