Sensitive Data & the .NET Crypto API
by David B. Scofield and Eric Bergman-Terrell

Listing One

// Used to convert strings to byte arrays.
private Encoding encoding = new UnicodeEncoding();

// Used to hash passwords and user ids into encryption keys.
private HashAlgorithm hashAlgorithm = new MD5CryptoServiceProvider();

private byte[] HashPassword(String text)
{
  return hashAlgorithm.ComputeHash(encoding.GetBytes(text));
}


Listing Two

public byte[] EncryptByteArray(string userID, string password, 
                                                   byte[] plainTextBuffer)
{
 ...
  // Create key and initialization vector.
  key = HashPassword(password);
  iv  = HashPassword(userID);

  byte[] cipherTextBuffer = null;

  // Create Encryptor and encrypt the data.
  using (ICryptoTransform encryptor = algorithm.CreateEncryptor(key, iv))
  using (MemoryStream memoryStream = new MemoryStream())
  using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, 
                     CryptoStreamMode.Write))
  {
    //Write all data to the crypto stream and flush it.
    cryptoStream.Write(plainTextBuffer, 0, plainTextBuffer.Length);
    cryptoStream.FlushFinalBlock();

    //Get encrypted array of bytes.
    cipherTextBuffer = memoryStream.ToArray();
  }
  return cipherTextBuffer;
}
public byte[] EncryptObject(string userID, string password, object obj)
{
  // Convert the object to a byte array.
  byte[] plainTextBuffer =
    serializeDeserialize.SerializeObjectToByteArray(obj);
  // Encrypt it.
  return EncryptByteArray(userID, password, plainTextBuffer);
}


Listing Three

public byte[] DecryptByteArray(string userID, string password, 
                               byte[] cipherTextBuffer)
{
  // Create key and initialization vector.
  key = HashPassword(password);
  iv  = HashPassword(userID);

  ArrayList plainText = new ArrayList(cipherTextBuffer.Length);

  // Create Decryptor and decrypt the data.
  using (ICryptoTransform decryptor = algorithm.CreateDecryptor(key, iv))
  using (MemoryStream memoryStream = new MemoryStream(cipherTextBuffer))
  using (CryptoStream cryptoStream = 
          new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
  {
    byte[] buffer = new byte[cipherTextBuffer.Length];
    int bytesRead;
    // Read plaintext from cryptostream until all plaintext has been extracted.
    do
    {
      bytesRead = cryptoStream.Read(buffer, 0, buffer.Length);
      if (bytesRead > 0)
      {
        // Copy the bytes actually read into the plainText ArrayList.
        byte[] bufferRead = new byte[bytesRead];
        Array.Copy(buffer, 0, bufferRead, 0, bytesRead);
        plainText.AddRange(bufferRead);
      }

    } while (bytesRead > 0);
  }
  return (byte[]) plainText.ToArray(typeof(byte));
}
public object DecryptObject(string userID, string password, 
                            byte[] cipherTextBuffer)
{
  // Decrypt the byte array.
  byte[] plainTextBuffer = DecryptByteArray(userID,password,cipherTextBuffer);
  // Convert decrypted byte array to an object.
  return serializeDeserialize.SerializeByteArrayToObject(
            plainTextBuffer, plainTextBuffer.Length);
}


Listing Four

private string Serialize(object obj)
{
  string result = "";
  BinaryFormatter Formatter = new BinaryFormatter();
  using (MemoryStream memoryStream = new MemoryStream())
  {
    // Serialize the object to a byte array.
    Formatter.Serialize(memoryStream, obj);
    memoryStream.Flush();
    // Get ready to read the stream into a byte array.
    memoryStream.Seek(0, SeekOrigin.Begin);
    byte[] buffer = new byte[memoryStream.Length];
    // Read the stream into the byte array.
    int bytesRead = memoryStream.Read(buffer, 0, buffer.Length);
    // Encrypt the byte array
    buffer = EncryptByteArray(buffer);
    //Return the result as a Base64 string
    //  Base64 is only necessary if storing in XML
    //  or other text-based formats
    result = Convert.ToBase64String(buffer, 0, bytesRead);
  }
  return result;
}
private object Deserialize(string str)
{
  object obj = null;
  BinaryFormatter Formatter = new BinaryFormatter();
  // Convert from a Base64 string
  byte[] buffer = Convert.FromBase64String(str);
  // Decrypt the byte array
  buffer = DecryptByteArray(buffer);
  // Convert the byte array to a MemoryStream
  using (MemoryStream memoryStream = new MemoryStream(buffer,0,buffer.Length))
  {
    // Convert the MemoryStream to an object
    obj = Formatter.Deserialize(memoryStream);
  }
  return obj;
}






3


