August 10, 2008

Symmetric Encryption in C#

The following code is based on that found in this article: Cryptography Simplified in Microsoft .NET The Key and the IV are needed to decrypt the encrypted text
using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Diagnostics;

...

// Simple Symmetric Encryption helper class
// Encrypts/Decrypts strings
public class SymmetricEncryptor
{
    // Private Variables for this Form
    private SymmetricAlgorithm m_EncryptionAlgorithmn;

    //Default constructor. Default Encryption algorithmn 
    // to TripleDESCryptoServiceProvider
    public SymmetricEncryptor()
    {
        m_EncryptionAlgorithmn = Rijndael.Create();
    }

    public SymmetricEncryptor(SymmetricAlgorithm symmetricAlgorithm)
    {
        m_EncryptionAlgorithmn = symmetricAlgorithm;
    }

    // Generate a Key for use with the Encryptor
    public string GenerateKeyString()
    {
        m_EncryptionAlgorithmn.GenerateKey();
        return Convert.ToBase64String(m_EncryptionAlgorithmn.Key);
    }

    // Generate an Initialisation Vector (as a string) for use with the Encryptor
    public string GenerateIVString()
    {
        m_EncryptionAlgorithmn.GenerateIV();
        return Convert.ToBase64String(m_EncryptionAlgorithmn.IV);
    }

    // Generate an Initialisation Vector for use with the Encryptor
    public byte[] GenerateIV()
    {
        m_EncryptionAlgorithmn.GenerateIV();
        return m_EncryptionAlgorithmn.IV;
    }


    // Get/Set the a Key for use with the Encryptor. 
    // Note the Key is provided as a Base 64 encoded string
    public string KeyString
    {
        get
        { return Convert.ToBase64String(m_EncryptionAlgorithmn.Key); }
        set
        { m_EncryptionAlgorithmn.Key = Convert.FromBase64String(value); }
    }

    // Get/Set the a Initialisation Vector for use
    // with the Encryptor. Note the Initialisation 
    // Vector is provided as a Base 64 encoded string
    public string IVString
    {
        get
        {
            return Convert.ToBase64String(m_EncryptionAlgorithmn.IV);
        }
        set
        { m_EncryptionAlgorithmn.IV = Convert.FromBase64String(value); }
    }


    // Get/Set the a Key for use with the Encryptor. 
    // Note the Key is provided as a Base 64 encoded string
    public byte[] Key
    {
        get
        { return m_EncryptionAlgorithmn.Key; }
        set
        { m_EncryptionAlgorithmn.Key = value; }
    }

    // Get/Set the a Initialisation Vector for use with the Encryptor.
    public byte[] IV
    {
        get
        { return m_EncryptionAlgorithmn.IV; }
        set
        { m_EncryptionAlgorithmn.IV = value; }
    }

    // Encrypt a string
    public string EncryptToString(string Value)
    {
        ICryptoTransform ct = m_EncryptionAlgorithmn.CreateEncryptor(
            m_EncryptionAlgorithmn.Key,
            m_EncryptionAlgorithmn.IV);
        byte[] bytes = Encoding.UTF8.GetBytes(Value);
        bytes = ApplyCryptoTransform(bytes, ct);
        return Convert.ToBase64String(bytes);
    }

    // Decrypt a string
    public string DecryptFromString(string Value)
    {
        ICryptoTransform ct = m_EncryptionAlgorithmn.CreateDecryptor(
            m_EncryptionAlgorithmn.Key,
            m_EncryptionAlgorithmn.IV);
        byte[] bytes = Convert.FromBase64String(Value);
        bytes = ApplyCryptoTransform(bytes, ct);
        return Encoding.UTF8.GetString(bytes);
    }

    // Encrypt a string
    public byte[] EncryptToBytes(string Value)
    {
        ICryptoTransform ct = m_EncryptionAlgorithmn.CreateEncryptor(
            m_EncryptionAlgorithmn.Key,
            m_EncryptionAlgorithmn.IV);
        byte[] bytes = Encoding.UTF8.GetBytes(Value);
        bytes = ApplyCryptoTransform(bytes, ct);
        return bytes;
    }

    // Decrypt a string
    public string DecryptFromBytes(byte[] encrBytes)
    {
        ICryptoTransform ct = m_EncryptionAlgorithmn.CreateDecryptor(
            m_EncryptionAlgorithmn.Key,
            m_EncryptionAlgorithmn.IV);
        byte[] bytes = ApplyCryptoTransform(encrBytes, ct);
        return Encoding.UTF8.GetString(bytes);
    }


    private static byte[] ApplyCryptoTransform(byte[] bytes,
        ICryptoTransform ct)
    {
        MemoryStream ms = new MemoryStream();
        CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
        cs.Write(bytes, 0, bytes.Length);
        cs.FlushFinalBlock();
        cs.Close();

        return ms.ToArray();
    }

    public byte[] GenerateKey()
    {
        m_EncryptionAlgorithmn.GenerateKey();
        return m_EncryptionAlgorithmn.Key;
    }
}
Here is a tester that demonstrates usage of the class.
public class SymmetricEncryptorTester
{
    public void Test()
    {
        string test = "98The0quick1brown2fox3jumps4over5the6lazy7cow";
        byte[] key;
        byte[] iv;
        string encrypted;
        string res;
        {
            SymmetricEncryptor se = new SymmetricEncryptor();
            key = se.GenerateKey();
            iv = se.GenerateIV();
            Debug.WriteLine(ByteToArray("key", key));
            Debug.WriteLine(ByteToArray("iv", iv));
            encrypted = se.EncryptToString(test);
            Debug.WriteLine("encrypted=" + encrypted);
        }
        {
            SymmetricEncryptor se = new SymmetricEncryptor();
            se.IV = iv;
            se.Key = key;
            res = se.DecryptFromString(encrypted);
            Debug.Assert(res.Equals(test, StringComparison.InvariantCulture));
            Debug.WriteLine("res=" + res);
        }
    }

    public void Test2()
    {
        string test = "98The0quick1brown2fox3jumps4over5the6lazy7cow";
        byte[] key;
        byte[] iv;
        byte[] encrypted;
        string res = "";
        {
            SymmetricEncryptor se = new SymmetricEncryptor();
            key = se.GenerateKey();
            iv = se.GenerateIV();
            Debug.WriteLine(ByteToArray("key", key));
            Debug.WriteLine(ByteToArray("iv", iv));
            encrypted = se.EncryptToBytes(test);
            Debug.WriteLine(ByteToArray("encrypted", encrypted));
        }
        {
            SymmetricEncryptor se = new SymmetricEncryptor();
            se.IV = iv;
            se.Key = key;
            res = se.DecryptFromBytes(encrypted);
            Debug.Assert(res.Equals(test, StringComparison.InvariantCulture));
            Debug.WriteLine("res=" + res);
        }

    }


    private string ByteToArray(string name, byte[] bytes)
    {
        string res = "byte[] " + name + " = new byte[" 
            + bytes.Length.ToString() + "] { ";
        for (int ix = 0; ix < bytes.Length; ix++)
        {
            res += "0x" + bytes[ix].ToString("X");
            if (ix < (bytes.Length - 1))
                res += ", ";
        }
        res += " }";
        return res;
    }
}

No comments: