/cfAES

comment(s) 

Compact Framework and Rijndael / AES

http://www.brains-N-brawn.com/cfAES 7/19/2004 casey chesnut

Introduction

the main limitation of my last article (/cfWSE2) was a lack of the AES symmetric encryption for the Compact Framework (CF). the problem was that WSE 2.0 uses AES encryption by default, which is not available through the CryptoAPI in Windows CE current. to make a WSE 2.0 web service callable by a device, it would have to be modified to use TripleDES instead ... which is not practical in real world scenarios (unless you own the web service too). as soon as i had finished that article, i found the following article on CodeProject.com: A CBC Stream Cipher in C#. the article provided a wrapper around some open source implementations of AES. ended up porting that code to CF as well as adding some more open source gems to further fill out the System.Security.Cryptography namespace for CF. finally, i've taken a look at what Whidbey Beta 1 adds , and have added a number of those algorithms as well. the algorithms with corresponding implementations on the full framework have been tested for interoperability. this is real short and will just give a brief overview of the new functionality. this is also an extension to the library originating from /spCrypt, which is a part of OpenNETCF.org

the table below shows the different crypto algorithms listed on the left, and where they live. X means that it is supported, 0 means partial support. you can see that System.Security.Cryptography for CFv2 is going to lack many algorithms compared to the desktop. OpenNETCF 1.2 and the /cfAes library are intended to be used together, to provide almost all of the crypto functionality of .NET 2005 (desktop)

Crytpo Algorithm .NET 2003 OpenNETCF 1.2 /cfAES WSE 2.0 CF 2.0 .NET 2005
MD5 X X X   X X
SHA1 X X X   X X
SHA256 X   X     X
SHA384 X   X     X
SHA512 X   X     X
MACTripleDES X 0 X     X
HMACSHA1 X X X X   X
PasswordDeriveBytes X 0 X     X
RC2 X X X   X X
DES X X X   X X
TripleDES X X X X X X
Rijndeal X   X   X X
RSA X X X X X X
DSA X X X   X X
RIPEMD160     X     X
HMACMD5     X     X
HMACSHA256     X     X
HMACSHA384     X     X
HMACSHA512     X     X
HMACRIPEMD160     X     X
Rfc2898DeriveBytes     X     X
ProtectedData     X     X
ProtectedMemory     X     X
PSHA1     X X    
AESKeyExchangeFormatter     X X    
TripleDesKeyExchangeFormatter     X X    
SecureString     X     X

RijndaelManaged, RijndaelCryptoServiceProvider

1st off, i think it is pronounced 'rain doll' :) i'm not certain of the history, but Rijndael and AES are related. something to the effect of Rijndael being the candidate for what is now known as AES. AES is the preferred standard for DOD symmetric encryption, replacing TripleDES. TripleDES superseded DES (by doing DES three times), because DES is no longer seen as secure. i even own a book that shows how to build hardware to crack DES in a short amount of time. this implementation is from the CodeProject article linked above, which wraps a C# AES implementation from an MSDN magazine article. it does CBC padding by default, but can be changed to do ECB as well

the full framework does provide a RijndaelManaged class, but not a native one. this native implementation is from the CodeProject article linked above, which wraps a C AES implementation from this article. all i did was build the C code using eVC to create a pInvoke-able DLL. that DLL has to be deployed to the device for the managed call to work, otherwise you will get a MissingMethodException. it is worth noting that the native implementation is about 4 to 5X faster than the managed

AES, EBC, NoPadding, KeyWrap

the Rijndeal implementations above were tested against WSE 2.0. WSE 2.0 was able to decrypt the messages from the device, as well as the device being able to decrypt messages from WSE 2.0. WSE 2.0 has a Microsoft.Web.Services2.Security.Cryptography namespace where it extends System.Security.Cryptography. the new additions i am most familiar with are the TripleDESKeyExchangeFormatter and the AESKeyExchangeFormatter. these algorithms are from the Xml-Encryption specification, and specify how symmetric keys should be encrypted before they are passed between endpoints. my version of AESKeyExchangeFormatter is called AesKeyWrap. it has also been tested against WSE 2.0. finally, the next version of CE is supposed to get an AES implementation in the CryptoApi

TripleDesEx, NoPadding, KeyWrap

the TripleDES KeyWrap implementation was brought over from the WSE bits (where it was tested). WSE 2.0 adds this algorithm through its own Cryptography namespace

SHA256Managed, SHA384Managed, SHA512Managed, SHA1Managed

these implementations were found from this article. SHA1Managed is included for completeness (use SHA1CryptoServiceProvider instead). SHA256/384/512 are missing from the CryptoApi as well. SHA256 is particularly important, because it is considered a RECOMMENDED Message Digest algorithm for Xml-Encryption

MD5Managed, MD2CryptoServiceProvider, MD4CryptoServiceProvider

MD5Managed is from an implementation found on the web. it is included for completeness (use MD5CryptoServiceProvider instead). MD2 and MD4 wrap the CryptoApi and are included for kicks. MD2 and MD4 have not been tested for interop since the full framework does not expose them

HMACMD5, HMACSHA256, HMACSHA384, HMACSHA512

these just do an HMAC with the corresponding HashAlgorithms. they have been tested for interop with Whidbey

RIPEMD160, HMACRIPEMD160

this was ported over from the Mentalis.org Security Library. it has been tested to work against Whidbey

Rfc2898DeriveBytes, PSHA1

Rfc2898DeriveBytes is added from VS 2005. it is used for key derivation. i wrote this one using the RSA spec and my HMACSHA1 wrapper. the RSA spec recommends using 1000 iterations, but this is really slow on a PocketPC, so try something like 100 instead. use this algorithm instead of PasswordDeriveBytes

PSHA1 is a key derivation that is used by the WS-* specs, and is implemented in WSE 2.0. i brought this code over from my WSE bits

ProtectedData, ProtectedMemory

ProtectedData just wraps the DPAPI. it provides 2 static methods to Protect() and Unprotect() the data. it accepts entropy, which i only have partially working right now

i'm not sure how ProtectedMemory works underneath the covers on the desktop. using Reflector i can see that it calls pInvokes SystemFunction040 and 041 of advapi32.dll ... whatever those methods are? regardless, i doubt those functions exist in CE. as a black box, all it does is somehow encrypt the memory you passed in. for CE, i have it use DES internally, and it manages the key using DPAPI. it does require the memory that is to be protected to be in 16 byte blocks, which does not seem that useful

SecureString

this is a port of Hernan de Lahitte's code for the Security.Cryptography namespace. its implementation relies on the ProtectedMemory code

NOTE that neither ProtectedData, ProtectedMemory, or SecureString should interop between the desktop and device. they are for use on the device only to store connection strings, keys, and such

PasswordDeriveBytes, MACTripleDES

these were not working great in the OpenNETCF implementation. PasswordDeriveBytes.CryptDeriveKey() just barely works. it calls into the CryptoApi, so i dont have much visibility as to what is going on. for .DeriveBytes() i used some code from Mono, which is working much better. the code is now in PasswordDeriveBytes2

MACTripleDES was originally calling into the CyrptoApi, which seems to have a bug in CE. MS was looking into it, but i never heard back. what i have done is created a MACTripleDES2 implementation, and just performed a MAC on top of TripleDESCryptoServiceProvider. this now works as expected.

Conclusion

these additions complete and extend the algorithms provided by the System.Security.Cryptography namespace (on the desktop) for the Compact Framework. Rijndeal / AES was critical for CF to call WSE 2.0, and that has already been integrated into the CF WSE codebase. this also gives CFv1 almost all of the same crypto algorithms that the desktop has for VS 2005.

Source

remember that a good portion of this code is not my own. it is code that others have graciously shared. all i did was port it to CF, give it the right name / interface, and make sure it was compatible with the full framework

/cfAES Source

Updates

the only planned updates would involve swapping out the Rijndael / AES implementation to use the CryptoApi implementation in the next version of CE. also, would make this build off of the CFv2 Crypto namespace, once that gets closer to release (and deprecate a chunk of my CryptoApi wrapper, in favor of MS supported code). finally, there might be license issues, but i'll try to get this code pushed into OpenNETCF

Future

i can tell you that i do NOT plan on writing the X509Certificate code for CF to use with WSE anytime soon. too painful. what i really need to do is break out of this Crypto / WSE rut