Skip to main content

Articles

Featured Products

Windows Mobile Developer Controls
Windows Mobile Developer Controls
Stay in touch using the DEVBUSS RSS feeds.
 

News

Windows Mobile Developer Controls
Windows Mobile Developer Controls

SmartPhone (SP) and CryptoApi with CompactFramework (.NETcf)

Written by casey chesnut  [author's bio]  [read 36135 times]
Edited by Derek

Download the code

Page 1  Page 2  Page 3  Page 4 

.NET Interoperability

Now that I knew the basic crypto services worked, I wanted to start testing interoperability with the full framework. To do this I wrapped my code loosely following the System.Security.Cryptography namespaces. All I did was create interfaces, classes, and methods as needed; so it is not as complete. These classes handle the byte reversing and key blob parsing that need to happen between Win32 CryptoApi calls and the real Managed .NET implementation. This same processing would have to happen for the CryptoApi on the desktop, as well as on devices. The code for this wrapper lives in the System.Security.Cryptography namespace (CE class library), and has a dependency on the bNb.Sec project above.

Most of the classes in System.Security.Cryptography ultimately call the CryptoApi for performance in the 1st place (e.g. SHA1CryptoServiceProvider). As opposed to SHA1Managed, which is an entirely managed implementation of the SHA1 hash. Even with the pInvokes, it should be faster to call the CryptoApi then it is to call the pure managed classes. Probably not a big deal for hashes, but definitely for Asymmetric encryption and signing. Also, some of the ciphers just do not exist in the CryptoApi for SmartPhones at all: Rijndael, SHA256, SHA384, SHA512

My method for testing involved the same .NETcf WinForm client running on the SmartPhone emulator (used above), along with a WebService running on a desktop using the full .NET Framework. Then the client would do its version of the crypto call and pass its results to the WebService. The WebService would verify those results on its end, and then perform the same operation, passing back the results to the CE client, which would then verify those results. (e.g. encrypt on device and send to WS, WS decrypts and checks that bytes, WS then encrypts and responds, device decrypts and checks that bytes match). The SmartPhone unit test project is called spCrypt, and the ASP.NET WebService interop test harness is wsCyrpto.

RNGCryptoServiceProvider

This one is simple. All it does is wrap CryptGenRandom. It looks random enough, so I didnt make a WS call to make sure the bytes didn't match :)

ToBase64Transform and FromBase64Transform

Just use Convert.ToBase64String and Convert.FromBase64String instead

MD5CryptoServiceProvider and SHA1CryptoServiceProvider

These are just simple hashes. The hash obtained on CE ended up being the same on the WS, so they match with no changes needed. NOTE that SHA256, SHA384, SHA512 dont exist in the CE CryptoApi

MACTripleDES

This is the Keyed Hash that I could not get to work above on CE at all, so I could not test it. MS is looking into it as a bug.

HMACSHA1

This keyed hash worked on the desktop, and the WS got the same hash value byte for byte.

PasswordDeriveBytes

This is used to derive session keys. You provide it a password and the name of a key cipher and hash, and it should derive the same session key time every time. In this manner you only have to remember your password, and dont have to store the session key. When I did an RC2 key and a SHA1 hash, the keys matched on the device and the desktop. When I did a DES key with a MD5 hash, some of the bytes were off by 1. I think this is due to 'salting'. I tried turning off the salt but could not get the derived keys to match exactly. In general, PasswordDeriveBytes is probably not compatible outside of the CryptoApi (regardless of desktop or device).

DES / TripleDESCryptoServiceProvider and RC2CryptoServiceProvider

I dont like the frameworks object model for ciphering with session keys, so I did not reproduce it. Instead I created the classes but made EncryptValue() and DecryptValue() methods like on the RSA class (as opposed to CryptoStreams). I tested DES, RC2, and TripleDES and was able to encrypt and decrypt to and from both the desktop and device. The only trick was the keys were stored in reverse by the CryptoApi. So keys I sent to the desktop had to be flipped, as well as keys being returned from the desktop before importing on the device. NOTE that Rijndael does not exist on the CE Crypto API, nor does RC4 or RC5 exist on the desktop.

RSAParameters and DSAParameters

The RSA and DSA classes will export and import using these classes, as well as to and from Xml. This implementation will handle both, so you can export and import both RSA and DSA keys between the desktop and the device. There is a bunch of bit flipping involved to do this.

RSACryptoServiceProvider

This class does a lot. 1st I made sure that it could encrypt and decrypt data between the WS. Along with the key flippings, the resulting ciphered data also had to be reversed. After that, I could encrypt on the device and decrypt on the WS, and vice versa.

DSACryptoServiceProvider

Similar to RSA above, except DSA can only be used for signing. This one had a different blob format then RSA which required me to export the key twice to get all info for private keys. Also, the full framework exports a derived parameter 'J' which I recreated by pilfering a Mono BigInteger class. Also the resulting signature had to be byte flipped twice (in sections) to get it to work with the full framework.

RSAPKCS1KeyExchangeFormatter and RSAPKCS1KeyExchangeDeformatter

These are just thin wrappers over RSA, that do encryption and decryption of session keys. I tested by creating a session key on the device, using my RSAPKCS1KeyExchangeFormatter , and sending the result to the WS to use its RSAPKCS1KeyExchangeDeformatter and create a session key from it; and vice versa. The keys exchanged matched byte for byte. NOTE the full framework has OAEP (instead of PKCS1) versions of these as well. I do not know if the CE CryptoApi can do OAEP?

RSAPKCS1SignatureFormatter and RSAPKCS1SignatureDeformatter

Same as the above, but instead of encryption and decryption, it calls SignHash and VerifyHash on the RSACryptoServiceProvider. This checked out on both the desktop and device as well.

DSASignatureFormatter and DSASignatureDeformatter

Same as the above SignatureFormatter, but for DSA instead of RSA.

Diffie-Hellman

The full framework does not have Diffie-Hellman, but the PROV_DSS_DH provider type on CE seems to. This is used for key agreement, as opposed to key exchange with RSA above. In RSAPKCS1KeyExchange, the session key was encrypted and sent over the wire. In key agreement, the session key is derived by both parties and never transferred over the wire. So that if I have my private key and your public key, and you have your private key and my public key, then we can both derive the same session key to exchange info, without actually having to exchange the session key so that somebody could compromise it. Pretty cool! NOTE DH is compromised, if either of the private keys is acquired.

Previous Page  Next Page