Well, i didn't get nearly as far in my book as I wanted... I did go see a good show last night at the Grand Emporium with a good friends' bands: www.fivedefy.com and http://myspace.com/thewaitinglist
When i got home, i figured a late night of programming would be fun. Don't laugh. Using Graham Wihlidals Encryption helper class and my own additional methods for Asymmetric encryption (ganked from the public samples on MSDN) i came up with the following helper class:
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
namespace JPeckham.Samples.Encryption
{
public class EncryptionHelper
{
#region Asymmetric Methods
public byte[] RSAEncrypt(byte[] DataToEncrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
{
//Create a new instance of RSACryptoServiceProvider.
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
//Import the RSA Key information. This only needs
//toinclude the public key information.
RSA.ImportParameters(RSAKeyInfo);
//Encrypt the passed byte array and specify OAEP padding.
//OAEP padding is only available on Microsoft Windows XP or
//later.
return RSA.Encrypt(DataToEncrypt, DoOAEPPadding);
}
public byte[] RSADecrypt(byte[] DataToDecrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
{
//Create a new instance of RSACryptoServiceProvider.
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
//Import the RSA Key information. This needs
//to include the private key information.
RSA.ImportParameters(RSAKeyInfo);
//Decrypt the passed byte array and specify OAEP padding.
//OAEP padding is only available on Microsoft Windows XP or
//later.
return RSA.Decrypt(DataToDecrypt, DoOAEPPadding);
}
#endregion
#region Symmetric
/// <summary>
/// Generates the initialization vector
/// </summary>
/// <param name="key">Your key</param>
/// <param name="size">the size of the vector you want</param>
/// <returns>The initialization vector as a byte array</returns>
internal byte[] GenerateIV(byte[] key, int size)
{
byte[] result = new byte[size];
SHA384Managed sha384 = new SHA384Managed();
sha384.ComputeHash(key);
for (int byteIndex = 0; byteIndex < result.Length; byteIndex++)
{
result[byteIndex] = sha384.Hash[byteIndex];
}
return result;
}//end GenerateIV
/// <summary>
/// Creates a key. Info withheld for security.
/// </summary>
/// <param name="key">your key</param>
/// <param name="size">the size of result key desired</param>
/// <returns>The generated key as a byte array.</returns>
internal byte[] GenerateKey(byte[] key, int size)
{
byte[] result = new byte[size];
SHA384Managed sha384 = new SHA384Managed();
sha384.ComputeHash(key);
int counter = 0;
for (int byteIndex = sha384.Hash.Length - 1;
byteIndex >= (sha384.Hash.Length - size);
byteIndex--)
{
result[counter++] = sha384.Hash[byteIndex];
}
return result;
}//end generate key
/// <summary>
/// Encrypts your data and returns a byte array of the encrypted version.
/// </summary>
/// <param name="cipher">Send a cipher (ie Rijndael/RC2)</param>
/// <param name="key">Your key</param>
/// <param name="plainText">Your data</param>
/// <returns>Your encrypted data</returns>
public byte[] EncryptMessage(SymmetricAlgorithm cipher, byte[] key, byte[] plainText)
{
ICryptoTransform transform = cipher.CreateEncryptor(GenerateKey(key, cipher.KeySize / 8), GenerateIV(key, cipher.BlockSize / 8));
byte[] result = transform.TransformFinalBlock(plainText, 0, plainText.Length);
return result;
}
/// <summary>
/// Decrypts your encrypted data and returns a byte array of the decrypted version.
/// </summary>
/// <param name="cipher">Send the same cipher used to encrypt (ie Rijndael/RC2)</param>
/// <param name="key">Send the same key you used to encrypt.</param>
/// <param name="cipherText">Your Encrytpted data</param>
/// <returns>Your decrypted data</returns>
public byte[] DecryptMessage(SymmetricAlgorithm cipher, byte[] key, byte[] cipherText)
{
ICryptoTransform transform = cipher.CreateDecryptor(GenerateKey(key, cipher.KeySize / 8), GenerateIV(key, cipher.BlockSize / 8));
byte[] result = transform.TransformFinalBlock(cipherText, 0, cipherText.Length);
return result;
}
#endregion
}
}
I then used the helper class to create a 'simulation' of sending an asymmetric public key across the wire to the server then the server sending back the symmetric key to the client. This allows two way communication using the much more efficient symmetric key.
Here's a shot of it in action:

and the source code if you want to play around with it:
Source Code