Sunday, December 17, 2006

xmldap as a plugin to perpetual motion

Kevin Miller's new Firefox plugin wraps the native Windows CardSpace identity selector, and in the process provides a great card parsing implementation. Since Kevin was kind enough to implement a plugin framework, I figured I'd take advantage and added plugin support to the xmldap selector.

If you pick up the latest version of the plugin (requires Java 1.5 on your system) you will now find a new Identity Selector option in your preferences. If you have both Kevin and my extension installed, and you're on Windows, you can now flip back and forth between the CardSpace selector, and the xmldap selector at will.




The great news is that people implementing selectors will no longer need to worry about augmenting the browser. Now hopefully we can all quickly agree on a preferences structure to allow any implementation to easily add itself to the list.

If you're interested in writing you're own plugin, it's pretty simple...here's the basics of an XPCOM component that implements the plugin interface:

http://openinfocard.googlecode.com/svn/trunk/firefox/components/Identityselector.js

have fun!

Tuesday, December 12, 2006

Another Firefox Cardspace Extension

Check out this cool extension for Firefox by Kevin Miller

http://www.perpetual-motion.com/

It basically wraps the native CardSpace implementation on Windows so you can use it from Firefox. Very robust looking parsing card detection, and the ability to implement an XPCOM interface to plugin other selectors:

IIdentitySelector..GetBrowserToken(issuer , recipientURL, requiredClaims ,data.optionalClaims , tokenType, privacyPolicy, privacyPolicyVersion , serverCert );

The selector implementation can be determined by the user's preferences, so it should be very simple to adapt the xmldap selector or other cross platform implementations to this model and let user's choose their selector.

Nice work Kevin!

Wednesday, December 06, 2006

Combining CardSpace and OpenID

At IIW I demo'd a little proof-of-concept showing the ability to login to a CardSpace relying-party, using an OpenID based identity. For those who didn't get a chance to see it, I provided a little screen cast here:

How-To Decrypt a CardSpace backup file

Having posted a utility that decrypts CardSpace backup files, I thought I'd take a moment to explain how it works. The backup file format is rather obscure, so hopefully this should help serve as a guide to people looking to import and export cards with non-Windows selectors.

The first thing to do is take a look at the CardSpace backup file format (edited for brevity):

<?xml version="1.0" encoding="utf-8"?>
<EncryptedStore xmlns="http://schemas.xmlsoap.org/ws/2005/05/identity">
<StoreSalt>3BprRlJ6LpWvvLvuGS6hXQ==</StoreSalt>
<EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#">
<CipherData>
<CipherValue>...Base64 Encoded Ciphertext...</CipherValue>
</CipherData>
</EncryptedData>
</EncryptedStore>


Here we have the file format. There are really just two things we care about...the Salt, and the CipherValue. The first thing to do is extract these 2 values.

At this point, it's probably good to get an overview of what you'll be doing. The ciphertext is actually a 16 byte Initialization Vector, 32 bytes of signature data for validating integrity, and then a CardSpace RoamingStore xml document encrypted using a PBE. Specifically, it's a PKCS5v1 derived key and AES with CBC.

As you get started, one thing to be aware of is the byte order mark. Regardless of what it claims, this xml in this file is actually encoded using UTF-16LE. So...it's prefixed with 3 bytes of data. Here's what you should expect for the byte order mark:

byte[] bom = {(byte)0xEF, (byte)0xBB, (byte)0xBF};

You'll also want to know about a couple pieces of static entropy used in the algorithm:

byte[] encKeyEntropy = { (byte)0xd9, (byte)0x59, (byte)0x7b, (byte)0x26, (byte)0x1e, (byte)0xd8, (byte)0xb3, (byte)0x44, (byte)0x93, (byte)0x23, (byte)0xb3, (byte)0x96, (byte)0x85, (byte)0xde, (byte)0x95, (byte)0xfc };

byte[] integrityKeyEntropy = {(byte)0xc4, (byte)0x01, (byte)0x7b, (byte)0xf1, (byte)0x6b, (byte)0xad, (byte)0x2f, (byte)0x42, (byte)0xaf, (byte)0xf4, (byte)0x97, (byte)0x7d, (byte)0x4, (byte)0x68, (byte)0x3, (byte)0xdb};


So - back to business. Once you've extracted the salt and the ciphertext, you can begin to decrypt the backup file. Here are the steps you'll want to take:

  1. Remove the Byte Order Mark, and parse the XML file, extracting the Salt, and the CipherText
  2. Base64 decode the salt, and set it aside
  3. Base64 decode the ciphertext
  4. Copy the first 16 bytes of the ciphertext, and set it aside as your IV
  5. Copy the next 32 bytes of the ciphertext, and set it aside as your integrity check
  6. Concatenate the remaining bytes together with the IV. ( IV + remaining bytes ) Set this aside as your data
  7. Derive your keys using PKCS5v1. Take the bytes of the user's password used to encrypt the data, and concatenate it with the salt bytes. Take a SHA256 hash of those bytes, and then SHA256 hash the output another 999 times.
  8. Generate the encryption key by concatenating the static encryption entropy together with the derived key. Generate a SHA256 byte hash of these bytes, and that is your encryption key
  9. Generate the integrity key by concatenating the static entrgrity entropy together with the derived key. Generate a SHA256 byte hash of these bytes, and that is your integrity key
  10. Decrypt the data using AES/CBC/OAEP with the encryption key you generated
  11. Remove the byte order mark, and you have the decrypted RoamingStore.

So - that's the basics of decryption. If you'd like to encrypt a store, you simply perform that process in reverse.

Next, you'll want to validate the integrity of the data. Here's how:
  1. Concatenate the IV, the integrity check data ( bytes 12-48 that you set aside earlier), and the last block of data (the last 16 bytes)
  2. Sha 256 hash this, and you have the computed integrity check. Compare your computed value to the integrity check...if they match byte for byte, you're in luck.
That's it. Be wary of character encoding, but if you follow these steps, you should be able to encrypt/decrypt backup files