Cryptography with C# in Windows Mobile

I wrote last week about an evening I spent throwing together a password manager for Windows and Windows Mobile. As I wrote at the time, one of the motivations was to try writing some encryption code.

I’ve finally got around to writing it, and wanted to post it here with a few comments.

This is what I needed code to be able to do:

  • Encrypt and decrypt data based on a user-provided password
  • Encrypt/decrypt consistently on both Windows desktops and Windows Mobile devices – a file encrypted on a Windows Mobile PDA should be able to be decrypted on a Windows desktop, and vice versa

The System.Security.Cryptography library in .NET makes this fairly straightforward – the class I have written to add crypto support to the password manager app needed only a few hundred lines of code in total.

I’ve shared a simplified version of the source at the end of this post.

First, a quick walkthrough:

PasswordDeriveBytes keyGenerator = new PasswordDeriveBytes(password, null);

We want to be able to generate a unique key from the password that the user enters. We can do this by using PasswordDeriveBytes as a key generator.

This can be used as follows:

byte[] cryptoKey = keyGenerator.CryptDeriveKey("RC2", "SHA1", 128, 
                                               new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });

Now we have a key, we can use it to initialise a crypto provider:

RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
rc2.Key = cryptoKey;

We also need an IV (initialization vector) to initialise the crypto provider. This needs to be consistent random number. That sounds wrong, doesn’t it? I just mean that it should be a constant, selected randomly, and ideally kept secret. For this example, I’m using:

rc2.IV = new byte[] { 23, 1, 99, 73, 44, 69, 35, 80 };

To make this library re-usable, I could use something like the application name to generate this value in some way? In this way, different applications that use my crypto DLL will have different IVs.

We can now create the encryptor and decryptors we need to encrypt and decrypt data:

ICryptoTransform internalEncryptor = rc2.CreateEncryptor();
ICryptoTransform internalDecryptor = rc2.CreateDecryptor();

This can be used to create a CryptoStream. We can string together a CryptoStream with a StreamReader or StreamWriter to read or write to files.

For example, to create a StreamReader that will read the decrypted contents of a file at the path ‘encryptedSourceFilePath‘:

FileStream sourceFileStream = new FileStream(encryptedSourceFilePath, FileMode.Open);
CryptoStream cryptoReader = new CryptoStream(sourceFileStream, internalDecryptor, CryptoStreamMode.Read);
StreamReader encryptedReader = new StreamReader(cryptoReader);

That now gives you a StreamReader object.

encryptedReader.ReadLine()

will read a line from the encrypted file, decrypt it, and return the decrypted string.

We can otherwise use this StreamReader as we would a StreamReader that directly opens a file.

Similarly, we can create a StreamWriter that will encrypt the text given to it and write it to a file at the path ‘encryptedDestinationFilePath‘:

FileStream destinationFileStream = new FileStream(encryptedDestinationFilePath, FileMode.Create);
CryptoStream cryptoWriter = new CryptoStream(destinationFileStream, internalEncryptor, CryptoStreamMode.Write);
StreamWriter encryptedWriter = new StreamWriter(cryptoWriter);

This gives us a StreamWriter object that we can pass strings to.

encryptedWriter.WriteLine("Hello.");

will encrypt the “Hello.” string and write the encrypted string to the file at the path ‘encryptedDestinationFilePath‘.

And that’s it… it needs some error-handling, and you need to close up streams when you’ve finished with them, but this is a pretty good start.

Except… that isn’t quite it. 🙁

The slightly tricky thing is that I’ve used PasswordDeriveBytes to generate my key. And there isn’t a PasswordDeriveBytes in the .NET Compact Framework that you get on Windows Mobile.

To get around this, I’ve used the implementation of PasswordDeriveBytes in the OpenNETCF Smart Device Framework.

The Community Edition of the Smart Device Framework contains a DLL with PasswordDerviceBytes that can be used free-of-charge, and integrates seamlessly with the .NET Compact Framework.

The interface is identical – the only difference needed in my code is that I use:
OpenNETCF.Security.Cryptography.PasswordDeriveBytes instead of
System.Security.Cryptography.PasswordDeriveBytes.

More importantly, the behaviour is consistent – allowing me to use the OpenNETCF SDF implementation on the mobile, and the Microsoft .NET implementation on the desktop.

I’ve compiled my crypto stream factory class into a DLL, which I can now use in other .NET projects. The first has been my password manager, which is now password-protected and uses encrypted data files.

Download the source from this post here

As noted above, it is incomplete. Most obviously, it needs error-handling. An approach to determining if you are given the right password more sophisticated than “go-until-you-throw a Crypto-Exception” would be good, too. 🙂

But this is hopefully enough of a start to be helpful!

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

3 Responses to “Cryptography with C# in Windows Mobile”

  1. Thanks for that, i was wondering how i was going to get the code from “http://www.codeproject.com/KB/security/DotNetCrypto.aspx” to run on my device and the passwordDerivesBytes was the problem.

    Anthony

  2. Rafat says:

    Thanks, this was helpful.

  3. Jared says:

    Thanks for the note on the opennetcf smart device framework, I just ran into this issue while writing a similar program for the same purpose. This was very very helpful.