Data encryption in WP7 by Anton


Windows Phone 7 developers trying to protect the customer’s data for every transition. In mobile phone it’s a question of life.

A quick look over at http://msdn.microsoft.com/en-us/library/ff402533(v=VS.92).aspx – lists the following cryptographic algorithms supported by Windows Phone OS 7.0:

  • AES
  • HMACSHA1
  • HMACSHA256
  • Rfc2898DeriveBytes
  • SHA1
  • SHA256

It would be great if we can simply use all of them. It’s our goal to combine some of them in one. So let’s take a look at some code.

The Encrypt() method below takes the data you want to encrypt as well as a password and salt value as arguments. It uses the AesManaged object with the default values of a 256-bit key and 128-bit block size. With the help of your supplied password, the encryption key is created using the Rfc2898DeriveBytes object with a dash of salt. Finally, the MemoryStream and CryptoStream objects work with the AesManaged object to convert your supplied data into an encrypted array of Bytes. I convert that array into a Base64 string that you can display on the screen, cache in memory, send to a WCF service or save to Isolated Storage.

public string Encrypt(string dataToEncrypt, string password, string salt)
{
AesManaged aes = null;
MemoryStream memoryStream = null;
CryptoStream cryptoStream = null;
try
{
//Generate a Key based on a Password, Salt and HMACSHA1 pseudo-random number generator
Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt));
//Create AES algorithm with 256 bit key and 128-bit block size
aes = new AesManaged();
aes.Key = rfc2898.GetBytes(aes.KeySize / 8);
aes.IV = rfc2898.GetBytes(aes.BlockSize / 8);
//Create Memory and Crypto Streams
memoryStream = new MemoryStream();
cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
//Encrypt Data
byte[] data = Encoding.UTF8.GetBytes(dataToEncrypt);
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
//Return Base 64 String
return Convert.ToBase64String(memoryStream.ToArray());
}
finally
{
if (cryptoStream != null)
cryptoStream.Close();
if (memoryStream != null)
memoryStream.Close();
if (aes != null)
aes.Clear();
}
}

As you can see below, the Decrypt() method looks remarkably similar to the Encrypt() method except that it does just the opposite. It accepts your AES-encrypted Base64 data plus a password and salt value as parameters to the method. The big difference is in the CryptoStream where you have the AesManaged object call CreateDecryptor() instead of CreateEncryptor(). This does the trick and then I convert the unencrypted Byte array into a string.

public string Decrypt(string dataToDecrypt, string password, string salt)
{
AesManaged aes = null;
MemoryStream memoryStream = null;
CryptoStream cryptoStream = null;
try
{
//Generate a Key based on a Password, Salt and HMACSHA1 pseudo-random number generator
Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt));
//Create AES algorithm with 256 bit key and 128-bit block size
aes = new AesManaged();
aes.Key = rfc2898.GetBytes(aes.KeySize / 8);
aes.IV = rfc2898.GetBytes(aes.BlockSize / 8);
//Create Memory and Crypto Streams
memoryStream = new MemoryStream();
cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(), CryptoStreamMode.Write);
//Decrypt Data
byte[] data = Convert.FromBase64String(dataToDecrypt);
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
//Return Decrypted String
byte[] decryptBytes = memoryStream.ToArray();
return Encoding.UTF8.GetString(decryptBytes, 0, decryptBytes.Length);
}
finally
{
if (cryptoStream != null)
cryptoStream.Close();
if (memoryStream != null)
memoryStream.Close();
if (aes != null)
aes.Clear();
}
}

Please keep a few things in mind when encrypting data on the Windows Phone 7 platform. The OS doesn’t include framework support for storing your passwords and salt values securely nor does it come with any kind of built-in key management. This means the only way to ensure your encrypted data is actually secure is to make sure your password, salt values and keys are not stored on the phone. As shown in my example, I require you to enter a password and a salt value each time you want to encrypt or decrypt data. I do not attempt to save those cleartext values anywhere in the system because there is no secure way to store them. One other thing to think about is that the cleartext password and salt value you entered on the screen can remain in memory at least until the next garbage collection.

You have to predict different ways of data transitions to be sure that non of them will be unsafe.