Symmetric Key Encryption using Rijndael and C#

October 19, 2007 § 1 Comment

Security remains the primary concern of on-line consumers and individuals who wish to keep their private documents private. Cryptography is the process associated with keeping messages secure. The process of converting plaintext to cipher text is called encryption and the process of reconverting the cipher text into plaintext is called decryption. Cryptography algorithms (ciphers) are mathematical functions used for encryption and decryptions.

There are two types of encryption, namely asymmetric encryption and symmetric encryption. Asymmetric encryption uses one key (the public key) to encrypt a message and a different key (the private key) to decrypt a message, or the other way around. Symmetric encryption uses the same key (the secret key) to encrypt and decrypt a message; messages encrypted with a secret key can be decrypted only with the same secret key.

The .Net framework is developed from the ground up with security in mind; the System.Security.Cryptography namespace provides classes for Symmetric Encryption, Asymmetric Encryption, Hashing, Digital Signatures, Digital Certificates and XML Signatures.

The rest of this article is going to concentrate on symmetric key encryption.

With the .Net framework, we have 4 choices of symmetric encryption algorithms:

DES
Triple DES
RC2
Rijndael
DES

The Data Encryption Standard (DES) was developed by an IBM team around 1974 and adopted as a national standard in 1977. DES encrypts and decrypts data in 64-bit blocks, using a 64-bit key. Although the input key for DES is 64 bits long, the actual key used by DES is only 56 bits in length. The least significant (right-most) bit in each byte is a parity bit, and should be set so that there are always an odd number of 1s in every byte. These parity bits are ignored, so only the seven most significant bits of each byte are used, resulting in a key length of 56 bits.

Triple DES

Triple DES is three times slower than regular DES but can be billions of times more secure if used properly. Triple DES is simply another mode of DES operation. It takes three 64-bit keys, for an overall key length of 192 bits. The procedure for encryption is exactly the same as regular DES, but it is repeated three times, hence the name Triple DES. The data is encrypted with the first key, encrypted with the second key, and finally encrypted again with the third key. Triple DES enjoys much wider use than DES because DES is so easy to break with today’s rapidly advancing technology.

RC2

RC2 (Rivest Cipher) was designed by Ron Rivest as a replacement for DES and boasts a 3 times speed increase over DES. The input and output block sizes are 64 bits each. The key size is variable, from one byte up to 128 bytes, although the current implementation uses eight bytes. The algorithm is designed to be easy to implement on 16-bit microprocessors.

Rijndael

The National Institute of Standards and Technology (NIST) officially announced that Rijndael, designed by Joan Daemen and Vincent Rijmen, would be the new Advanced Encryption Standard.

The Advanced Encryption Standard (AES) is the current encryption standard, intended to be used by the U.S. Government organisations to protect sensitive (and even secret and top secret) information. It is also becoming a global standard for commercial software and hardware that use encryption. It is a block cipher which uses 128-bit, 192-bit or 256-bit keys. Rijndael is very secure and has no known weaknesses.

Enter the Code:

Ok, now that we have got all of the background out of the way lets get started with the fun stuff. Lets take a look at the code, here is a simple implementation of the Rijndael algorithm. We will start with the encryption process first.

Encryption

private static string EncryptString(string InputText, string Password)

{

// We are now going to create an instance of the

// Rihndael class.

RijndaelManaged RijndaelCipher = new RijndaelManaged();

// First we need to turn the input strings into a byte array.

byte[] PlainText = System.Text.Encoding.Unicode.GetBytes(InputText);

// We are using salt to make it harder to guess our key

// using a dictionary attack.

byte[] Salt = Encoding.ASCII.GetBytes(Password.Length.ToString());

// The (Secret Key) will be generated from the specified

// password and salt.

PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(Password, Salt);

// Create a encryptor from the existing SecretKey bytes.

// We use 32 bytes for the secret key

// (the default Rijndael key length is 256 bit = 32 bytes) and

// then 16 bytes for the IV (initialization vector),

// (the default Rijndael IV length is 128 bit = 16 bytes)

ICryptoTransform Encryptor = RijndaelCipher.CreateEncryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16));

// Create a MemoryStream that is going to hold the encrypted bytes

MemoryStream memoryStream = new MemoryStream();

// Create a CryptoStream through which we are going to be processing our data.

// CryptoStreamMode.Write means that we are going to be writing data

// to the stream and the output will be written in the MemoryStream

// we have provided. (always use write mode for encryption)

CryptoStream cryptoStream = new CryptoStream(memoryStream, Encryptor, CryptoStreamMode.Write);

// Start the encryption process.

cryptoStream.Write(PlainText, 0, PlainText.Length);

// Finish encrypting.

cryptoStream.FlushFinalBlock();

// Convert our encrypted data from a memoryStream into a byte array.

byte[] CipherBytes = memoryStream.ToArray();

// Close both streams.

memoryStream.Close();

cryptoStream.Close();

// Convert encrypted data into a base64-encoded string.

// A common mistake would be to use an Encoding class for that.

// It does not work, because not all byte values can be

// represented by characters. We are going to be using Base64 encoding

// That is designed exactly for what we are trying to do.

string EncryptedData = Convert.ToBase64String(CipherBytes);

// Return encrypted string.

return EncryptedData;

}

Decryption

Most of the logic in decryption is similar to the encryption logic.

Let’s take a quick look at how the decryption works.

private static string DecryptString(string InputText, string Password)

{

RijndaelManaged RijndaelCipher = new RijndaelManaged();

byte[] EncryptedData = Convert.FromBase64String(InputText);

byte[] Salt = Encoding.ASCII.GetBytes(Password.Length.ToString());

PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(Password, Salt);

// Create a decryptor from the existing SecretKey bytes.

ICryptoTransform Decryptor = RijndaelCipher.CreateDecryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16));

MemoryStream memoryStream = new MemoryStream(EncryptedData);

// Create a CryptoStream. (always use Read mode for decryption).

CryptoStream cryptoStream = new CryptoStream(memoryStream, Decryptor, CryptoStreamMode.Read);

// Since at this point we don’t know what the size of decrypted data

// will be, allocate the buffer long enough to hold EncryptedData;

// DecryptedData is never longer than EncryptedData.

byte[] PlainText = new byte[EncryptedData.Length];

// Start decrypting.

int DecryptedCount = cryptoStream.Read(PlainText, 0, PlainText.Length);

memoryStream.Close();

cryptoStream.Close();

// Convert decrypted data into a string.

string DecryptedData = Encoding.Unicode.GetString(PlainText, 0, DecryptedCount);

// Return decrypted string.

return DecryptedData;

}

Encrypting a file

The only difference in, encrypting a file is that we use a file stream instead of a memory stream.

private static void EncryptFile(string FileLocation, string FileDestination, string Password)

{

RijndaelManaged RijndaelCipher = new RijndaelManaged();

// First we are going to open the file streams

FileStream fsIn = new FileStream(FileLocation, FileMode.Open, FileAccess.Read);

FileStream fsOut = new FileStream(FileDestination, FileMode.Create, FileAccess.Write);

byte[] Salt = Encoding.ASCII.GetBytes(Password.Length.ToString());

PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(Password, Salt);

ICryptoTransform Encryptor = RijndaelCipher.CreateEncryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16));

CryptoStream cryptoStream = new CryptoStream(fsOut, Encryptor, CryptoStreamMode.Write);

int ByteData;

while ((ByteData=fsIn.ReadByte()) != -1)

{

cryptoStream.WriteByte((byte)ByteData);

}

cryptoStream.Close();

fsIn.Close();

fsOut.Close();

}

The decrypting of a file is very similar to the encrypting of a file.

Conclusion:

The encryption/decryption sample above had a very defined purpose, being extremely easy to read and understand. While it explains how to use encryption and gives some ideas on how to start implementing encryption in your applications, you should add parameter checking and error handling. Wrap calls that can potentially fail into try/catch blocks, use finally blocks to release resources if something goes wrong.

§ One Response to Symmetric Key Encryption using Rijndael and C#

Leave a comment

What’s this?

You are currently reading Symmetric Key Encryption using Rijndael and C# at Naik Vinay.

meta