Don’t forget to Encrypt your Windows Phone 7 Data

| July 2, 2010 | 27 Comments

Encryption

Whether you’re targeting Mobile Line of Business apps for the Enterprise or B2C apps for consumers, ensuring that sensitive data is encrypted is a must.  These days, I can’t have a serious discussion with a CIO unless I can assure her that my mobile device can protect data-in-transit and data-at-rest.  You already know that Windows Phone 7 secures data-in-transit via SSL whether you’re using Internet Explorer or calling a Web Service from a Silverlight app.  What you may not know is how it covers the other bases.  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

I thought I’d take some of these algorithms for a spin by building a sample app using Microsoft Visual Studio 2010 Express for Windows Phone.  All I really wanted to do is use the Advanced Encryption Standard (AES) for symmetric key encryption to encrypt and decrypt some data so I could save it to Isolated Storage.  Doing this would definitely check the security checkboxes of Microsoft’s customers and ISVs.

Above are screenshots of the simple app I created.  A TextBox is used to enter the data to be encrypted by AES.  Below that, a PasswordBox control is used to enter a password that works in conjunction with Rfc2898DeriveBytes and HMACSHA1 + a Salt value to create a key.  Keep in mind that you must enter more than 8 characters to create a valid Salt value.  I don’t necessarily expect you to understand PBKDF2 Password-Based Cryptography.  Tapping the Encrypt button calls the Encrypt() method which uses Silverlight’s AesManaged class to create a Key and an Initialization Vector (IV) to perform the crypto magic and display the resulting Base64 encrypted data in the Encrypted data TextBox.  Tapping the Decrypt button does the reverse by calling the Decrypt() method to unscramble the data and display the resulting data in the Decrypted data TextBox.

I also threw some buttons on there to save the newly encrypted data to Isolated Storage as an ApplicationSetting.  As shown in the screenshot above, tapping the Save to Isolated Storage button will save the encrypted data locally.  The best way to test the Retreive from Isolated Storage button is to first close the app, then restart it, and then tap the button.  It will place the saved information in the Encrypted data TextBox.  From there, just enter the password and salt you used before and the text you’re looking for will appear in the Decrypted data TextBox. 

Let’s take a look at some code. 

You’ll need to include the following using statements to get started:

using System.IO;
using System.IO.IsolatedStorage;
using System.Security.Cryptography;
using System.Text;

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 size 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.  When creating the pseudo-random number needed to derive a key, the default number of iterations specified by the Password-Based Cryptography Specification (RFC 2898) is 1,000.  On the advice of some of our top security experts, I bumped that value up to 10,000 to make this harder to crack.  The next thing to note is both the AES key and IV have their values assigned from the Rfc289DeriveBytes object containing the base key.  Keep in mind that you don’t want to use a static IV and that’s why it’s good to have it derived from your unique password, salt, plus 10,000 iterations to create pseudo-randomness.  One other thing to note is that the biggest performance hit you’ll experience in running this code  comes from when you call the GetBytes(int) method of the Rfc2898DeriveBytes object which initializes a new instance of HMAC each time.  If you need to encrypt multiple strings or other types of data, you should pull the Rfc2898DeriveBytes objects out of the Encrypt method and just pass in a pre-created Key and IV so that each call doesn’t have to perform this expensive initialization over and over again.  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, or save to Isolated Storage.

private void btnEncrypt_Click(object sender, RoutedEventArgs e)
{
    try
    {
        txtEncryptedData.Text = Encrypt(txtDataToEncrypt.Text, txtPassword.Password, txtSalt.Password);
    }
    catch (CryptographicException cryptEx)
    {
        MessageBox.Show(cryptEx.Message, "Encryption Error", MessageBoxButton.OK);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "General Error", MessageBoxButton.OK);
    }
}
 
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 and HMACSHA1 pseudo-random number generator
        //Salt must be at least 8 bytes long
        //Use an iteration count of at least 1000
        Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt), 10000);

        //Create AES algorithm
        aes = new AesManaged();
        //Key derived from byte array with 32 pseudo-random key bytes
        aes.Key = rfc2898.GetBytes(32);
        //IV derived from byte array with 16 pseudo-random key bytes
        aes.IV = rfc2898.GetBytes(16);

        //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.

private void btnDecrypt_Click(object sender, RoutedEventArgs e)
{
    try
    {
        txtDecryptedData.Text = "";
        txtDecryptedData.Text = Decrypt(txtEncryptedData.Text, txtPassword.Password, txtSalt.Password);
    }
    catch (CryptographicException cryptEx)
    {
        MessageBox.Show(cryptEx.Message, "Decryption Error", MessageBoxButton.OK);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "General Error", MessageBoxButton.OK);
    }
}
 
public string Decrypt(string dataToDecrypt, string password, string salt)
{
    AesManaged aes = null;
    MemoryStream memoryStream = null;

    try
    {
        //Generate a Key based on a Password and HMACSHA1 pseudo-random number generator
        //Salt must be at least 8 bytes long
        //Use an iteration count of at least 1000
        Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt), 10000);

        //Create AES algorithm
        aes = new AesManaged();
        //Key derived from byte array with 32 pseudo-random key bytes
        aes.Key = rfc2898.GetBytes(32);
        //IV derived from byte array with 16 pseudo-random key bytes
        aes.IV = rfc2898.GetBytes(16);

        //Create Memory and Crypto Streams
        memoryStream = new MemoryStream();
        CryptoStream 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();

        //Dispose
        if (cryptoStream != null)
            cryptoStream.Dispose();

        //Retval
        return Encoding.UTF8.GetString(decryptBytes, 0, decryptBytes.Length);
    }
    finally
    {
        if (memoryStream != null)
            memoryStream.Dispose();

        if (aes != null)
            aes.Clear();
    }
}
 

Please keep a few things in mind when encrypting data on the Windows Phone 7 platform.  The OS Does Not 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  never store your password, salt value or keys 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.  If you see an app in the Windows Phone Marketplace that allows you to cache your credentials or keys locally for convenience, be aware that these are Not Secure solutions because everything a hacker needs to get at your data is right there in the code or in Isolated Storage.  The only place to store your password and salt is in your head.  It’s not that big a deal.  Your bank’s website makes you enter your credentials each time to ensure the security of your financial data, so this is something you’re already accustomed to. 

Beyond the two Crypto methods above, I created a pair of methods to save and load your encrypted ApplicationSettings to Isolated Storage as shown below:

private void btnSave_Click(object sender, RoutedEventArgs e)
{
    try
    {
        SaveState("EncryptedValue", txtEncryptedData.Text);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Save Error", MessageBoxButton.OK);
    }
} 
 
public void SaveState(string Name, string Value)
{
    if (Value != "")
    {
        if (IsolatedStorageSettings.ApplicationSettings.Contains(Name))
        {
            IsolatedStorageSettings.ApplicationSettings[Name] = Value;
        }
        else
        {
            IsolatedStorageSettings.ApplicationSettings.Add(Name, Value);
        }
    }
} 
 
private void btnRetreive_Click(object sender, RoutedEventArgs e)
{
    try
    {
        txtEncryptedData.Text = LoadState("EncryptedValue");
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Load Error", MessageBoxButton.OK);
    }
}
 
public string LoadState(string Name)
{
    if (IsolatedStorageSettings.ApplicationSettings.Contains(Name))
    {
        return IsolatedStorageSettings.ApplicationSettings[Name].ToString();
    }
    else
    {
        return "";
    }
} 

As you can see from the code samples above, encrypting the sensitive data you use in your Windows Phone 7 apps is completely within your reach.  This is just one of many managed crypto examples to give you an idea on how to get started.  Many more are waiting for you on MSDN.  When you combine this with the following security elements:

  • Apps are tested, digitally signed and securely delivered via the Windows Phone Marketplace
  • No side-loading of potentially insecure apps
  • SSL for data in transit
  • Managed apps run inside secure sandbox
  • Apps have private, inaccessible Isolated Storage
  • Exchange Policies including PIN lock enforcement + Remote wipe  

It’s clear that Windows Phone 7 has an excellent app security story that’s not only good for consumers, but also means that this mobile app platform is prime-time ready for the Secure Enterprise.

Keep coding,

Rob

Tags: , , , , , , , , , , , , , , , , , , ,

Category: Windows Phone 7

About the Author ()

A mobile strategist and cloud architect at Microsoft, Rob has spent his career as an entrepreneur, advisor, teacher, developer, speaker, and author of bestselling books on mobile and wireless technologies. A pioneer of the smartphone revolution, he drove the development of the mobile app ecosystem from its earliest days and co-founded the world’s first cloud-based mobile device management company.

Comments (27)

Trackback URL | Comments RSS Feed

Sites That Link to this Post

  1. Windows Phone 7 Data Encryption | MobileTechWorld | July 3, 2010
  2. Windows Phone 7 Also Comes With Encryption Methods; Good News for Business Users | GSM Dome - Mobile Phone News | July 4, 2010
  3. Windows Phone 7 Also Comes With Encryption Methods; Good News for Business Users - A Collection of Latest Happening in Technology Field | July 5, 2010
  4. Dew Drop – July 7, 2010 | Alvin Ashcraft's Morning Dew | July 7, 2010
  5. Dizem Blog » Blog Archive » Windows Phone 7 Resources and Links [WP7开发资源] | February 16, 2011
  6. 超快递 beta版 » Windows Phone 7 资源汇总(超全) | June 21, 2011
  7. Шифрование в Windows Phone 7 | Программизм | September 28, 2011
  8. Encrypting your Credentials on Windows Phone 7.5 | Rob Tiffany | December 12, 2011
  9. WINDOWS 7 SECURITY IMPLICATIONS | Hack Archives | January 7, 2012
  10. Windows Phone Sicherheit - Windows Phone 7 Allgemein - Windows Phone Forum | March 10, 2012
  11. windows phone 7 | Pearltrees | March 18, 2012
  12. Securing Windows Phone Apps–Tips to make your app lock-solid | MSDN Blogs | March 19, 2012
  13. Daily Deeds: Windows Phone Data Encryption | ব্লগবাকুম! | December 12, 2012
  14. AES encryption Java to c#QueryBy | QueryBy, ejjuit, query, query by, queryby.com, android doubt, ios question, sql query, sqlite query, nodejsquery, dns query, update query, insert query, kony, mobilesecurity, postquery, queryposts.com, sapquery, jquery, | October 30, 2013
  15. AES encryption Java to c#CopyQuery CopyQuery | Question & Answer Tool for your Technical Queries,CopyQuery, ejjuit, query, copyquery, copyquery.com, android doubt, ios question, sql query, sqlite query, nodejsquery, dns query, update query, insert que | October 30, 2013
  1. Tarun Pahuja says:

    Hi,

    Thanks for this useful blog. But, I have a problem. My earlier application was made in C,C++ for I-phone and the similar application i am importing in WP7 :) But the problem is, in C,C++., i have used RSA cryptography terms and here in WP7, these are not supported. I only want to use the same algorithms as used in C,C++.

    I am stuck in between the project. Kindly help me out of this providing me a solution. I will be really thankful to you.

    B/R,
    Tarun

  2. DaveShaw says:

    Are there plans to let the OS manage Encryption Keys like in Windows?

  3. Thank you ever so for you blog post.Really thank you! Awesome.

  4. DustinHorne says:

    Last November I set out to work on an RSA implementation in C# for Silverlight in the browser. I’ve been actively updating it as an open source project on Codeplex. As it turns out, it also works perfectly on WP7. :)

    http://scrypt.codeplex.com

    As of today thanks to community contribution it also supports Blob based key storage and retrieval in addition to parameters and xml variations. The complete source is there and it’s completely open and free both personal and commercial so you’re welcome to use it in your corporate apps.

    Thanks,

    Dustin

  5. piter says:

     Thanks for your bog post. I have trouble with image steganography in windows phone 7, can you guide, please ?

  6. Mike says:

    First off great post, helped me greatly. You said if you have to encrypt multiple strings use pre created keys. What exactly does that mean? Basically what I’m trying to do is send a high score to a server but I want it encrypted. I’m sending 3 strings to the server so the server and the app need to have synced keys right? How do I create a pre created key with it being secure that I can use both in my app and server?

    • Rob Tiffany says:

      Hi Mike,
      In my article, I talk about and show the code needed to create a key based on a password and salt value. Once that key is created, you could reuse it to encrypt multiple strings to be stored in Isolated Storage on Windows Phone. Dealing with servers get tricky since the server would need the same key you created on the device in order to decrypt. Unfortunately, Windows Phone 7 doesn’t include the capabilities needed to maintain secure key storage. This is why the user is required to enter their credential each time in order to encrypt/decrypt the local data. The lack of no automated key management makes what you’re asking for very difficult.

      -Rob

  7. Asian says:

    Hi Rob!

    Thanks for the nice article. I have a question regarding about encryption. In WP7.5, socket is supported. So I am using socket to communicate an window phone application (app) with the server. I want to know if I have to encrypt the data or not….Oh.. I feel stupid about asking this… There will be 2-way communications (app to server, server to app) using socket and some data can be sensitive. There will be a decent amount of communication between the app and the server.

    Is using your encryption technique a good idea for this case?

    And also, to enable 2-way encrypted communication, the server and the app both will have to have password&salt generated. right? I am sorry for my bad english.

  8. Dan Chimento says:

    Thanks for the post!! This really helped me avoid long hours of research and reading. Works perfectly from the beginning!

  9. francisco says:

    Thanks for the code Rob

Leave a Reply