Page 1
Page 2
Page 3
Page 4
Cryptography
I started targeting the basic crypto services
first: Random #'s and working with Providers. Then I moved
on to Hashes and Keyed Hashes. Next, was working with Keys
and getting access to the raw key data. Finally, Encryption
and Signing. The SmartPhone WinForm project in the code
has all of these tests. These tests run local on the device
and might not be interoperable with the full .NET framework
(I will make it interoperable later). The actual Crypto
wrapper lives in the bNb.Sec project, which is a CE class
library and has no dependencies.
Random
This tested multiple ways of generating
random numbers, as well as multiple ways of generating GUIDs.
Providers
This lists the available provider types,
providers, and ciphers that are available on a device. On
a SmartPhone, the Provider Types are:
- PROV_RSA_FULL
- PROV_DSS_DH - not on PPC 2002
Each Provider Type above had 2
Providers:
- MS Base Crypto Provider [PROV_RSA_FULL]
- MS Enhanced Crypto Provider - not
on PPC 2002 emulator, but on my PPC 2002 device
- MS Base DSS Diff-Hell [PROV_DSS_DH]
- MS Enhanced DSS Diff-Hell
These are the Ciphers and (min, max)
key length available for the 2 Enhanced Providers above:
- RC2 (40 128), RC4 (40 128), RC5
(40 128), DES (56 56), 3DES TWO KEY (112 112), 3DES (168
168), SHA-1 (160 160), MD2 (128 128), MD4 (128 128), MD5
(128 128), SSL3 SHAMD5 (288 288), MAC (0 0), RSA_SIGN
(384 16384), RSA_KEYX (384 16384), HMAC (0 0) [MS
Enhanced Crypto Provider]
- RC4 (40 128), DES (56 56), 3DES
TWO KEY (112 112), 3DES (168 168), SHA-1 (160 160), MD5
(128 128), DSA_SIGN (512 1024), DH_KEYX (512 4096), DH_KEYX
(512 4096) [MS Enhanced DSS Diff-Hell]

Hash
The most popular are MD5 and SHA1,
and they both work on the SmartPhone. MD5 is 16 bytes, SHA1
is 20. MD5 is supposed to be faster, and SHA1 is supposed
to be stronger. SHA1 is what you will probably use most
of the time in your apps. SSL SHAMD5 is used for SSL (probably what
Pocket IE uses), it is a combination of MD5 and SHA1 (thus
36 bytes)
Keyed Hash
The keyed hashes most often used are
MacTripleDes and HmacSha1. MacTripleDes combines a TripleDES
symmetric key with a MAC hash. The MAC hash ends up being
8 bytes. I could not get it to work on the SmartPhone. It
would return a byte [] of 8 bytes, but all of the values
were zero. If I used DES instead of TripleDES, then it would
get a value. An MS employee was helping me in a newsgroup
and posted their working C++ code for doing MacTripleDes.
I ported that to eVC++, and still got all 0's, so I think
this is a bug in the CryptoApi for SmartPhones (maybe for
PocketPC too?). A couple of MS employees have recreated
this problem and are looking into it. HmacSha1 is a combination
of an HMAC and a SHA1 hash. This worked on the SmartPhone
with no problems. Originally coded this with using the
CALG_HMAC algId. From a newsgroup posting, I ended
up having to change this to doing multiple SHA1 hashes after
doing some key manipulation. With that change
it became more compatible with the full framework. I
also tested the CryptHashSessionKey here. I did by getting
access to the raw session key data (explained below), manually
hashing that key, and making sure those bytes matched the
hash obtained by calling CryptHashSessionKey.
Keys
I started out working with symmetric
keys (DES, TripleDES, and RC2). Made sure CryptGenKey created
random keys each time, and CryptDeriveKey would create the
same key each time. Also, attempted to import and export
raw session keys. Unluckily, the CryptoApi makes this tedious
to accomplish. The rule of thumb is that session keys should
never be transferred in the clear, so the CryptoApi forces
you to encrypt the session key with an asymmetric key to
get the random bytes. Of course, there is a convoluted workaround
that lets you get the raw session keys with what is called
an
exponent-of-one private key. The concept is x * 1 =
x, where 1 is the exponent-of-one key. So when you export
or import the session key, no bytes are actually changing.
When you finally extract a session key in the clear,
it will come out being something like 142 bytes. This is
odd because session keys are mostly in the range from
8 to 24 bytes. The 142 bytes are a SimpleBlob structure
that MS has defined. Its basically header info, the actual
key, and then random bytes. Asymmetric keys are easier to
import and export. You can just ask for the PublicKeyBlob
or PrivateKeyBlob and get access to their plaintext bytes,
also in MS defined wrappers.
For symmetric keys, DES is no longer
considered secure. RC4 is supposed to be faster than RC2,
and RC2 is supposed to be stronger. TripleDES replaces DES
and is supposed to be stronger than RC2 and RC4. For
asymmetric keys, the PROV_RSA_FULL provides us with RSA
which can be used for encrypting and signing. NOTE you should
not encrypt and sign with the same key pairs. The PROV_DSS_DH
provider types provide DSA. DSA can only be used for signing.
Encryption
The unportable way is to use CryptProtectData
with CryptUnprotectData. I'm not exactly sure how CryptProtectData
is encrypting the data, but I believe it is tied to a machine.
So that if you encrypt with ProtectData on deviceX, then
you cannot use CryptUnprotectData to decrypt on deviceY.
This seems useful as a means to store keys that need to
be reused.
The other methods are CryptEncrypt and
CryptDecrypt to be used with the standard symmetric and
asymmetric algorithms, which will be portable across devices.
Symmetric algorithms are much faster than asymmetric, so
the rule of thumb is to use symmetric algorithms to encrypt
data with a session key, and then encrypt session keys
with pub / priv keys to pass the session key over
the wire. For symmetric encryption, you encrypt and decrypt
with the same key. For asymmetric encryption you encrypt
with somebody else's public key, and they decrypt with their
private key.
Signing
This is possible with pub / priv keys.
To sign, you use your private key (typically on a hash value),
and then that signature can be verified with your public
key on another device. To sign with the CryptoApi you use
CryptSignHash, and verify with CryptVerifySignature. I made
sure that these calls worked and that a signature would
not verify if a byte was changed.
Certificates
Most of what we have looked at until
now is CryptoApi 1.0, which is basically complete on
a SmartPhone. CryptoApi 2.0 introduces more functionality,
mainly for dealing with Certificates, with about 1/2 of
it existing for SmartPhones. I did not wrap these interfaces
as well, and will use the managed System.Security.Cryptography.X509Certificates.X509Certificate
class, which does exist in the .NETcf.

Previous Page
Next Page