### Secret Key (Symmetric) Encryption

Secret key encryption, also called symmetric encryption because of its two-way nature, relies on something called a shared secret or secret key. Before discussing code, consider a hypothetical scenario:

Bob wants to send information to John, but Bob doesn't want anyone to be able to intercept the communication and be able to read the information being sent. To accomplish this, Bob comes up with a secret code that he uses to encrypt his message. Bob makes sure that John has this secret code through some means. When John receives the encrypted message, John can use that same secret key to decrypt the message that Bob sent.

There are two important aspects of this type of encryption:

• There is a secret shared between parties that allows for the secure transmission of data.

• The same key that is used to encrypt the data is used to decrypt the data (hence the term symmetric to describe this encryption type).

Secret key encryption works on single blocks of data at a time. Blocks are then chained together and operated on sequentially. If the secret key was used to encrypt each block without any modification, the same encrypted results would appear for the same block all the time. All someone would have to do is search for patterns in your blocks of encrypted data to get a head start on deciphering your key. To deal with this, an initialization vector (IV) is used. This is essentially a starter key that is used to encrypt the first block of data. Then data from each block is mixed with the data from the block, preventing duplicate blocks from producing the same encrypted output.

Thus, a common characteristic of all secret key encryption is the use of a secret key and an initialization vector key. The combination of these two keys is used to encrypt and decrypt information in a symmetric fashion. The next few sections will show you samples of some of the .NET cryptographic service providers that implement secret key encryption: DESCryptoServiceProvider, RC2CryptoServiceProvider, RijndaelManaged, and TRipleDESCryptoServiceProvider.

#### DESCryptoServiceProvider

The DESCryptoServiceProvider is a managed class that inherits from System.Security.SymmetricAlgorithm. It provides an implementation of the DES (Data Encryption Standard) algorithm.

As with all symmetric algorithms, it requires a key and an IV to operate properly. These values are stored as byte arrays in the .NET Framework. For the examples in this chapter, some random keys have been generated on the fly to make them easier to read. For real-world scenarios, these keys would be kept secret somewhere inaccessible to most users.

The best way to encrypt data with a symmetric algorithm is to create a CryptoStream. A CryptoStream functions just like any other stream, but with one major difference: When nonencrypted data is written to the stream, it is encrypted by the stream itself. The following code creates an instance of the DESCryptoServiceProvider and sets up a CryptoStream:

```// DES
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.GenerateKey();
des.GenerateIV();
FileStream fsOut_DES = new FileStream("outputDES.txt", FileMode.Create, FileAccess.Write);
CryptoStream desStream = new CryptoStream( fsOut_DES,
des.CreateEncryptor( des.Key, des.IV ), CryptoStreamMode.Write);
```

In a real-world scenario, instead of calling GenerateKey and GenerateIV, you would assign the Key and IV properties to byte arrays that you created with your own keys.

Keep in mind that each of the algorithms has its own requirements for key size, so you will need to consult the documentation on each algorithm before creating your key and IV.

#### RC2CryptoServiceProvider

RC2CryptoServiceProvider is an implementation of the SymmetricAlgorithm abstract base class that provides access to the RC2 encryption algorithm. The following code shows how to set up a CryptoStream to an output file where the contents of the file will be RC2-encrypted:

```// RC2
RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
rc2.GenerateIV();
rc2.GenerateKey();
FileStream fsOut_RC2 = new FileStream("outputRC2.txt", FileMode.Create, FileAccess.Write);
CryptoStream rc2Stream = new CryptoStream( fsOut_RC2,
rc2.CreateEncryptor(), CryptoStreamMode.Write);
```

#### RijndaelManaged

The RijndaelManaged class is an implementation of the managed version of the Rijndael symmetric encryption algorithm. The following code illustrates creating a CryptoStream to an output file that will create a Rijndael-encrypted output:

```// RijndaelManaged
RijndaelManaged rm = new RijndaelManaged();
rm.GenerateIV();
rm.GenerateKey();
FileStream fsOut_RM = new FileStream("outputRM.txt", FileMode.Create, FileAccess.Write);
CryptoStream rmStream = new CryptoStream( fsOut_RM,
rm.CreateEncryptor(), CryptoStreamMode.Write);
```

#### tripleDESCryptoServiceProvider

The TripleDES encryption algorithm is a symmetric encryption algorithm based on the data encryption standard. The following code illustrates how to set up an output CryptoStream that will create an encrypted text file based on TripleDES:

```// TripleDES
TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider();
tripleDes.GenerateIV();
tripleDes.GenerateKey();
FileStream fsOut_3Des =
new FileStream("output3DES.txt", FileMode.Create, FileAccess.Write);
CryptoStream tripleStream = new CryptoStream( fsOut_3Des,
tripleDes.CreateEncryptor(), CryptoStreamMode.Write);
```

To put all of these encryption algorithms together into a simple program that will take an unencrypted text file and produce an encrypted version for each one of the symmetric algorithms, you can use the code shown in Listing 35.1.

##### Listing 35.1. A Symmetric Encryption Demonstration
```using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

namespace SecretKeyCrypto
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{

byte[] bin = new byte[100]; // 100 byte buffer

FileStream fsIn = new FileStream("input.txt", FileMode.Open, FileAccess.Read);

// buffer data
long rdLen = 0;
long totLen = fsIn.Length;
int len;

// DES
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.GenerateKey();
des.GenerateIV();
FileStream fsOut_DES =
new FileStream("outputDES.txt", FileMode.Create, FileAccess.Write);
CryptoStream desStream = new CryptoStream( fsOut_DES,
des.CreateEncryptor( des.Key, des.IV ), CryptoStreamMode.Write);

// RC2
RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
rc2.GenerateIV();
rc2.GenerateKey();
FileStream fsOut_RC2 =
new FileStream("outputRC2.txt", FileMode.Create, FileAccess.Write);
CryptoStream rc2Stream = new CryptoStream( fsOut_RC2,
rc2.CreateEncryptor(), CryptoStreamMode.Write);

// RijndaelManaged
RijndaelManaged rm = new RijndaelManaged();
rm.GenerateIV();
rm.GenerateKey();
FileStream fsOut_RM =
new FileStream("outputRM.txt", FileMode.Create, FileAccess.Write);
CryptoStream rmStream = new CryptoStream( fsOut_RM,
rm.CreateEncryptor(), CryptoStreamMode.Write);

// TripleDES
TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider();
tripleDes.GenerateIV();
tripleDes.GenerateKey();
FileStream fsOut_3Des =
new FileStream("output3DES.txt", FileMode.Create, FileAccess.Write);
CryptoStream tripleStream = new CryptoStream( fsOut_3Des,
tripleDes.CreateEncryptor(), CryptoStreamMode.Write);

while ( rdLen < totLen )
{
System.Diagnostics.Debug.WriteLine("Read " + len.ToString() + " bytes.");
desStream.Write(bin, 0, len );
rc2Stream.Write(bin, 0, len );
rmStream.Write(bin, 0, len );
tripleStream.Write(bin, 0, len );
rdLen += len;