Cryptography in C#: Symmetric encoding

The .NET Framework offers a lot of easy to use cryptography classes. Within this article I want to give you the basic knowledge to use the symmetric encoding features of the namespace System.Security.Cryptography.

 
Symmetric encoding

Symmetric algorithms are using the same key for encryption and decryption of the data. Nearly all modern algorithms will encrypt the source data block wise. The most common block sizes are 8, 16, 24 and 32 bytes. Depending of the length of the source data the last block will be filled with a pre-defined data, the so called padding.

Simple encoding algorithms will encrypt each block separated. This encoding type is called Electronic Codebook (ECB). The same block data will result in the same encrypted data. But such patterns will make the encoding more unsafe. Therefore another technique exists: Cypher Block Chaining (CBC). If CBC is used, information of the previous block will be used to encrypt the actual block. The first block does not have a predecessor, therefore an Initial Vector (IV) may be defined.

 
AES, Rijndael

The AES algorithm is one of the standard symmetric encryption techniques. It is also called Rijndael algorithm according to his inventors: Vincent Rijmen and Joan Daemen. Within the .NET Framework you will find the two classes AesManaged and RijndaelManaged. AesManaged is only a variation of RijndaelManaged with some pre-defined configuration values.

 
Example: Encrypt and decrypt a string

The following example shows a console application which encrypts and decrypts data from and to a string.

Console Application:

static void Main(string[] args)
{
    byte i;
    string originData;
    string encryptedData;
    string decryptedData;

    //create key and initial vector
    byte[] key = new byte[24];
    byte[] vector = new byte[16];

    for (i = 0; i < 24; i++) key[i] = i;
    for (i = 0; i < 16; i++) vector[i] = i;

    //create data
    originData = "test data for Rijndael encryption and decryption";

    //execute
    encryptedData = Encrypt(originData, key, vector);
    decryptedData = Decrypt(encryptedData, key, vector);

    Console.WriteLine("origin: " + originData);
    Console.WriteLine("encrypted: " + encryptedData);
    Console.WriteLine("decrypted: " + decryptedData);
    Console.ReadKey();
}

 

Encryption

public static string Encrypt(string plainText, byte[] rgbKey, byte[] rgbIV)
{
    RijndaelManaged rijndaelManaged = new RijndaelManaged();
    ICryptoTransform encryptor = null;

    byte[] encryptedBytes = null;
    byte[] textBytes = null;

    MemoryStream msEncrypt = null;
    CryptoStream csEncrypt = null;
    StringBuilder encryptedString = null;

    int i;

    //create byte array
    textBytes = new byte[plainText.Length];
    for (i = 0; i < plainText.Length; i++)
    {
        textBytes[i] = (byte)plainText[i];
    }

    //create encryptor
    encryptor = rijndaelManaged.CreateEncryptor(rgbKey, rgbIV);

    //encrypt
    msEncrypt = new MemoryStream();
    csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);

    //write
    csEncrypt.Write(textBytes, 0, plainText.Length);
    csEncrypt.FlushFinalBlock();

    //get encrypted array of bytes.
    encryptedBytes = msEncrypt.ToArray();

    //create string
    encryptedString = new StringBuilder(encryptedBytes.Length);
    for (i = 0; i < encryptedBytes.Length; i++)
    {
        encryptedString.Append((char)(encryptedBytes[i]));
    }

    return encryptedString.ToString();
}

 

Decryption

public static string Decrypt(string encryptedText, byte[] rgbKey, byte[] rgbIV)
{
    byte[] encryptedBytes = new byte[encryptedText.Length];
    byte[] decryptedBytes = null;

    RijndaelManaged rijndaelManaged = new RijndaelManaged();
    ICryptoTransform decryptor = null;

    MemoryStream msDecrypt = null;
    CryptoStream csDecrypt = null;

    int i;

    StringBuilder builderDecryptedText;

    //create byte array
    for (i = 0; i < encryptedText.Length; i++)
    {
        encryptedBytes[i] = (byte)encryptedText[i];
    }

    //create decryptor
    decryptor = rijndaelManaged.CreateDecryptor(rgbKey, rgbIV);

    //decrypt
    msDecrypt = new MemoryStream(encryptedBytes);
    csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);

    //read
    decryptedBytes = new byte[encryptedText.Length];
    csDecrypt.Read(decryptedBytes, 0, decryptedBytes.Length);

    //create string
    builderDecryptedText = new StringBuilder();
    for (i = 0; i < decryptedBytes.Length; i++)
    {
        if (0 != decryptedBytes[i]) //truncate '0' because array has always a size of x*16
        {
            builderDecryptedText.Append((char)(decryptedBytes[i]));
        }
    }

    return builderDecryptedText.ToString();
}

 
Example: Encrypt and decrypt a secure string

Instead of a normal string it is also possible to use a SecureString. The following source code shows the modified functions.

Encryption

public static string SecureEncrypt(System.Security.SecureString plainText, byte[] rgbKey, byte[] rgbIV)
{
    RijndaelManaged rijndaelManaged = new RijndaelManaged();
    ICryptoTransform encryptor = null;

    string textToEncrypt = "";

    byte[] encryptedBytes = null;
    byte[] textBytes = null;

    MemoryStream msEncrypt = null;
    CryptoStream csEncrypt = null;
    StringBuilder encryptedString = null;

    int i;

    //get plain text            
    IntPtr ptrPlainText = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(plainText);
    try
    {
        textToEncrypt = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptrPlainText);
    }
    finally
    {
        System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptrPlainText);
    }

    //create byte array
    textBytes = new byte[textToEncrypt.Length];
    for (i = 0; i < textToEncrypt.Length; i++)
    {
        textBytes[i] = (byte)textToEncrypt[i];
    }


    //create encryptor
    encryptor = rijndaelManaged.CreateEncryptor(rgbKey, rgbIV);

    //encrypt
    msEncrypt = new MemoryStream();
    csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);

    //write
    csEncrypt.Write(textBytes, 0, textToEncrypt.Length);
    csEncrypt.FlushFinalBlock();

    //get encrypted array of bytes.
    encryptedBytes = msEncrypt.ToArray();

    //create string
    encryptedString = new StringBuilder(encryptedBytes.Length);
    for (i = 0; i < encryptedBytes.Length; i++)
    {
        encryptedString.Append((char)(encryptedBytes[i]));
    }

    return encryptedString.ToString();
}

 

Decryption

public static System.Security.SecureString SecureDecrypt(string encryptedText, byte[] rgbKey, byte[] rgbIV)
{
    byte[] encryptedBytes = new byte[encryptedText.Length];
    byte[] decryptedBytes = null;

    RijndaelManaged rijndaelManaged = new RijndaelManaged();
    ICryptoTransform decryptor = null;

    MemoryStream msDecrypt = null;
    CryptoStream csDecrypt = null;

    System.Security.SecureString decryptedString = null;

    int i;

    //create byte array
    for (i = 0; i < encryptedText.Length; i++)
    {
        encryptedBytes[i] = (byte)encryptedText[i];
    }

    //create decryptor
    decryptor = rijndaelManaged.CreateDecryptor(rgbKey, rgbIV);

    //decrypt
    msDecrypt = new MemoryStream(encryptedBytes);
    csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);

    //read
    decryptedBytes = new byte[encryptedText.Length];
    csDecrypt.Read(decryptedBytes, 0, decryptedBytes.Length);

    //create secure string
    decryptedString = new System.Security.SecureString();
    for (i = 0; i < decryptedBytes.Length; i++)
    {
        if (0 != decryptedBytes[i]) //truncate '0' because array has always a size of x*16
        {
            decryptedString.AppendChar((char)(decryptedBytes[i]));
        }
    }
    decryptedString.MakeReadOnly();

    return decryptedString;
}

 
Summary

By using the .NET Framework you can easily implement encryption functionalities. Within this article you have learned why properties like IV or Pattern exists in this framework classes and how you may use them.

Advertisements
Dieser Beitrag wurde unter .NET, C# abgelegt und mit , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s