AES Encryption in VBScript

VB6/VBScript was one of the first languages I learned to use.  Today, VBScript is still my fall back language when I just need to 'Getter Done!'.  Coupled with Windows Script Host and the Scripting runtime I can use it to automate a large number of otherwise manual tasks.  We have some VBScripts laying around that export data from our datastore on scheduled intervals and make it available to our customers to download via FTP-SSL.  We are adding some new information to the export that is of the sensitive nature and so encryption came up.  Figured since 'Standard' is the S in AES, it made a good choice.  The problem was finding some code to do this in VBScript.  Some digging turned up an implementation in VB6/ASP but it was god awfully large and complicated.  Additionally it was difficult to verify that once encrypted on our side, our customer could easily decrypt it using a previously exchanged Key and Initialization Vector (also using a different programming language all together).  Since the .Net Framework makes encryption dirt simple and it was already on the server I whipped up a simple class that is exposed to COM and easily incorporated into our existing VBScript.

Without going too deep, AES requires a Key and an Initialization Vector (IV) to encrypt something.  You need the same Key and IV to decrypt the info at a later time.  Both of these are byte arrays (byte[]).  The resulting encrypted data is also a byte array.  Now sharing/hard coding a byte array in code is not all that easy.  Rather than share the raw byte array you can base64 encode the data and then you have something that is easily inserted into a text file or transferred via email.  The code below is written in a very targeted manner expecting/returning base64 data, hard coding the algorithm used, ascii encoding, etc.  Please feel free to tweak for your needs.  To expose this to COM, just run "regasm.exe My.Product.dll" and you can run the...cough...unit tests...cough at the end of the sample.  Program note: all of the methods here could be marked static, but COM doesn't like static methods.

namespace My.Product
{
  using System;
  using System.IO;
  using System.Runtime.InteropServices;
  using System.Security.Cryptography;
  using System.Text;

  [ProgId("My.Product.Crypto")]
  public class Crypto
  {
    public string Encrypt(string base64key, string base64iv, string clearText)
    {
      SymmetricAlgorithm algorithm = GetAlgorithm();
      algorithm.Key = Convert.FromBase64String(base64key);
      algorithm.IV = Convert.FromBase64String(base64iv);

      byte[] clearTextBytes = Encoding.ASCII.GetBytes(clearText);

      byte[] cipherTextBytes = Transform(algorithm, clearTextBytes, false);

      return Convert.ToBase64String(cipherTextBytes);
    }

    public string Decrypt(string base64key, string base64iv, string base64cipherText)
    {
      SymmetricAlgorithm algorithm = GetAlgorithm();
      algorithm.Key = Convert.FromBase64String(base64key);
      algorithm.IV = Convert.FromBase64String(base64iv);

      byte[] cipherTextBytes = Convert.FromBase64String(base64cipherText);

      byte[] clearTextBytes = Transform(algorithm, cipherTextBytes, true);

      return Encoding.ASCII.GetString(clearTextBytes, 0, clearTextBytes.Length);
    }

    public int DefaultKeySize
    {
      get
      {
        SymmetricAlgorithm algorithm = GetAlgorithm();
        return algorithm.KeySize;
      }
    }

    public int DefaultBlockSize
    {
      get
      {
        SymmetricAlgorithm algorithm = GetAlgorithm();
        return algorithm.BlockSize;
      }
    }

    public string GenerateBase64Key(int keySize)
    {
      SymmetricAlgorithm algorithm = GetAlgorithm();
      algorithm.KeySize = keySize;
      return Convert.ToBase64String(algorithm.Key);
    }

    public string GenerateBase64IV(int blockSize)
    {
      SymmetricAlgorithm algorithm = GetAlgorithm();
      algorithm.BlockSize = blockSize;
      return Convert.ToBase64String(algorithm.IV);
    }

    private static byte[] Transform(SymmetricAlgorithm algorithm, byte[] bytes, bool decrypt)
    {
      byte[] transformedBytes = null;
      using (ICryptoTransform transform = GetTransform(algorithm, decrypt))
      {
        using (MemoryStream memoryStream = new MemoryStream())
        {
          using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
          {
            cryptoStream.Write(bytes, 0, bytes.Length);
          }
          transformedBytes = memoryStream.ToArray();
        }
      }
      return transformedBytes;
    }

    private static ICryptoTransform GetTransform(SymmetricAlgorithm algorithim, bool decrypt)
    {
      if (decrypt)
      {
        return algorithim.CreateDecryptor();
      }

      return algorithim.CreateEncryptor();
    }

    private static SymmetricAlgorithm GetAlgorithm()
    {
      RijndaelManaged algorithm = new RijndaelManaged();
      algorithm.KeySize = 256;
      algorithm.BlockSize = 128;

      return algorithm;
    }
  }
}

 And it's usage in VBScript:

Option Explicit

Call Main()

Sub Main()
  Dim crypto
  Dim base64key, base64iv
  Dim clearText, cryptText, cryptText2, decryptText

  Set crypto = CreateObject("My.Product.Crypto")
  base64key = crypto.GenerateBase64Key(crypto.DefaultKeySize)
  base64iv = crypto.GenerateBase64IV(crypto.DefaultBlockSize)
  clearText = "EncryptThis"

  cryptText = crypto.Encrypt(base64key, base64iv, clearText)
  decryptText = crypto.Decrypt(base64key, base64iv, cryptText)
  If clearText <> decryptText Then
    MsgBox "Decrypting did not yield correct value"
    Exit Sub
  End If

  cryptText = crypto.Encrypt(base64key, base64iv, clearText)
  cryptText2 = crypto.Encrypt(base64key, base64iv, clearText)
  If cryptText <> cryptText2 Then
    MsgBox "Encrypting twice produces different results"
    Exit Sub
  End If

  MsgBox "All Tests Passed"    
End Sub

posted @ Friday, June 29, 2007 3:20 PM


Print

Comments on this entry:

No comments posted yet.

Your comment:



 (will not be displayed)


 
 
 
Please add 8 and 2 and type the answer here:
 

Live Comment Preview:

 
«August»
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456