2. Using Rfc2898DeriveBytes and AES to Encrypt Data
To encrypt data from prying
eyes on a Windows Phone 7 device, you need a strong encryption
mechanism that, in turn, relies on the strong key to make encryption
withstand all of the known attempts to break it. The Rfc2898DeriveBytes
algorithm, available on Windows Phone 7, creates a very strong key for
use in AES encryption from the password and salt values passed in. The
next walkthrough demonstrates how to use both of those algorithms on a
Windows Phone 7 device.
2.1. Creating a User Interface
The interface will prompt the
user for data to encrypt and for a password and salt to use for that
encryption. The interface will also have two buttons—one for encryption
and the other one for decryption of data.
Open Visual Studio Express for Windows Phone and create a new project called AESEncryption. Make the MainPage.xaml page look like the one shown in Figure 3. For convenience, the XAML of this page is pasted here: <!--LayoutRoot contains the root grid where all other page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12"> <TextBlock x:Name="ApplicationTitle" Text="CLASSIFIED" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="AES Encryption" Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel>
<!--ContentPanel - place additional content here--> <Grid x:Name="ContentGrid" Grid.Row="1"> <TextBox Height="65" HorizontalAlignment="Left" Margin="6,41,0,0" Name="txtDataToEncrypt" Text="" VerticalAlignment="Top" Width="462" /> <TextBlock Height="30" HorizontalAlignment="Left" Margin="20,21,0,0" Name="textBlock1" Text="Data to encrypt" VerticalAlignment="Top" Width="419" /> <TextBox Height="72" HorizontalAlignment="Left" Margin="6,334,0,0" Name="txtPassword" Text="" VerticalAlignment="Top" Width="462" /> <TextBlock Height="30" HorizontalAlignment="Left" Margin="20,310,0,0" Name="textBlock2" Text="Password" VerticalAlignment="Top" Width="346" /> <TextBox Height="72" HorizontalAlignment="Left" Margin="6,426,0,0" Name="txtSalt" Text="" VerticalAlignment="Top" Width="462" /> <TextBlock Height="36" HorizontalAlignment="Left" Margin="21,403,0,0" Name="textBlock3" Text="Salt" VerticalAlignment="Top" Width="304" /> <Button Content="Encrypt" Height="72" HorizontalAlignment="Left" Margin="20,504,0,0" Name="button1" VerticalAlignment="Top" Width="160" Click="button1_Click"/>
<Button Content="Decrypt" Height="72" HorizontalAlignment="Left" Margin="296,504,0,0" Name="button2" VerticalAlignment="Top" Width="160" Click="button2_Click"/>
<TextBlock Height="30" HorizontalAlignment="Left" Margin="24,101,0,0" Name="textBlock4" Text="Encrypted Data" VerticalAlignment="Top" Width="432" /> <TextBox Height="72" HorizontalAlignment="Left" Margin="8,123,0,0" Name="txtEncryptedData" Text="" VerticalAlignment="Top" Width="460" /> <TextBlock Height="27" HorizontalAlignment="Left" Margin="21,197,0,0" Name="textBlock5" Text="Decrypted Data" VerticalAlignment="Top" Width="435" /> <TextBox Height="72" HorizontalAlignment="Left" Margin="13,221,0,0" Name="txtDecryptedData" Text="" VerticalAlignment="Top" Width="460" /> </Grid> </Grid>
2.2. Coding the Application Logic
AES encryption in the .NET
Framework is implemented via a class called AesManaged. The following
code uses this class, together with the Rfc2898DeriveBytes class to
encrypt the data.
Add the following using directive to the top of the page:
using System.Security.Cryptography; using System.IO; using System.Text;
Code the Encrypt method. The Encrypt method takes data to encrypt, password and salt as parameters, and returns a string. Notice how the Encrypt
method creates the Rfc2898DerivedBytes class and uses that class to
generate a strong key from the password and salt combination; that key
is later used by the AesManaged class to encrypt data. public string Encrypt(string dataToEncrypt, string password, string salt) { AesManaged aes = null; MemoryStream memStream = null; CryptoStream crStream = null;
try { //Generate a Key based on a Password and Salt 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);
memStream = new MemoryStream(); crStream = new CryptoStream(memStream, aes.CreateEncryptor(),
CryptoStreamMode.Write);
byte[] data = Encoding.UTF8.GetBytes(dataToEncrypt); crStream.Write(data, 0, data.Length); crStream.FlushFinalBlock();
//Return Base 64 String return Convert.ToBase64String(memStream.ToArray()); } finally { //cleanup if (crStream != null) crStream.Close();
if (memStream != null) memStream.Close();
if (aes != null) aes.Clear(); } }
Code
the Decrypt method. The Decrypt method is the inverse of Encrypt: it
takes data to decrypt, password and salt as parameters, and returns an
input string. Since AES is a symmetric algorithm, the same password and
salt values must be used to decrypt data as were used to encrypt it. The
Decrypt method initializes the Rfc2898Bytes key and uses it to create
Decryptor for data. public string Decrypt(string dataToDecrypt, string password, string salt) { AesManaged aes = null; MemoryStream memStream = null; CryptoStream crStream = null;
try { Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt)); aes = new AesManaged(); aes.Key = rfc2898.GetBytes(aes.KeySize / 8); aes.IV = rfc2898.GetBytes(aes.BlockSize / 8);
memStream = new MemoryStream(); crStream = new CryptoStream(memStream, aes.CreateDecryptor(), CryptoStreamMode.Write); byte[] data = Convert.FromBase64String(dataToDecrypt); crStream.Write(data, 0, data.Length); crStream.FlushFinalBlock();
byte[] decryptBytes = memStream.ToArray(); return Encoding.UTF8.GetString(decryptBytes, 0, decryptBytes.Length); } finally
{ if (crStream != null) crStream.Close();
if (memStream != null) memStream.Close();
if (aes != null) aes.Clear(); } }
Add code to call the Encrypt method when the user clicks the Encrypt button. Double-click the Encrypt button in MainPage.xaml and add the following code to the click event handler: txtEncryptedData.Text = Encrypt(txtDataToEncrypt.Text, txtPassword.Text, txtSalt.Text);
Finally, add code to call the Decrypt method when the user clicks the Decrypt button. Double-click the Decrypt button in MainPage.xaml and add the following code to the Click event handler: txtDecryptedData.Text = Decrypt(txtEncryptedData.Text, txtPassword.Text, txtSalt.Text);
Press F5 to run the
application. Enter some data (for example, "Classified Information"), a
password (for example, "test"), and salt (note that it must be at least 8
characters long, otherwise AES classes will throw an exception), and
observe the values being encrypted in the Encrypted Data
textbox. Press Decrypt and you should see the original text in the
Decrypted Data field. Note that if you enter the password or salt values
that are different between encryption and decryption, the application
will raise an error.
Now that you understand
the cryptography framework on the Windows Phone 7, it's time to take a
look at the physical security of the device.
|