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