I recently worked on a secure device application which requires a PIN code to be entered as startup.The application database also needs to be encrypted. My first approach was to use a DESCryptoServiceProvider, which is among the few supported encryption methods in the .NET Compact Framework, to encrypt the database using the PIN code itself as the secret key.
My full code can be found here.
Soon after, I discovered the problem. The encrypted database can be decrypted if the secret key provided is slightly wrong. For example, if the secret key I used when encrypting is 12345678, the decryption will work with both 12345678 and 12345778 (wrong value). Thinking that this was almost certainly a bug, I went ahead to file a report at Microsoft Connect.
I did not have to wait until Microsoft responsed me (which was 3 days later) for an answer. Soon after I read the Wikipedia article on DES, I immediate realized my mistake. The key ostensibly consists of 64 bits; however, only 56 of these are actually used by the algorithm. Eight bits are used solely for checking parity, and are thereafter discarded. This explains why the wrong secret key can be used to decrypt the data as described above.
I changed to TripleDES only to observe the same behaviour. As AES is not supported on the compact framework, I end up encrypting the database using an MD5 hash of the PIN code. Although you may argue that MD5 has some chance of collision, the above hash + encryption combination will ensure, at least with ultimate possibility, that there is no way for the database to be decrypted without the correct password.
Actually, AES is supported on .NET Compact Framework (since 2.0), but it's called Rijndael. This is the original name of the algorithm that whas later adopted by the US government as AES.
ReplyDeleteThe only difference between AES and Rijndale is that AES has a fixed block size of 128 bits and a key size of 128, 192, or 256 bits, whereas Rijndael can be specified with block and key sizes in any multiple of 32 bits, with a minimum of 128 bits.
So as long as you stick to block size of 128 bits, Rijndael and AES are compatible.
For more information, check out http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
And using a MD5 hash as encryption key without any key derivation algorithm and salt value makes dictionary attacks a piece of cake.
Thanks for the useful information. I overlooked Rijndale when I was trying AES encryption in .NET CF, and could not find any hints online. Thanks again, I have learned something new :)
ReplyDelete