CardSpace: a closer look to the CRD format
I’m receiving a lot of questions about the CRD file format, that is to say the format used by CardSpace for defining managed cards. I am rather sure that sooner or later we will publish an official reference for it, however I thought it could be interesting to take a closer look to it already today. Special thanks to Garrett that allowed me to use an early version of his tool for generating the samples! If you want to know more keep reading 🙂
First of all, here’s a managed card crash course. A managed card, or provider card, is an information card issued by an identity provider. It lists
a) details about the entity that issues the card: name, certificate, STS and MEX endpoints, etc
b) the list of claims about the user that the card issuer can corroborate
c) details about how the user will authenticate with the STS of the card issuer in order to have his information card populated with the needed claim values. This is the famous second authentication factor, that in v1 can be in form of a certificate, or a kerberos token, of a selfissued card or, in extreme cases, in an old fashion username/password pair.
The CRD format is, in extreme simplification, just an XML document that contains the above information: it is used by the card issuer to express all those in concise form, and it is used by the user for importing the card into his/her collection.
In our example we assume that an hairdresser is issuing me a card that certifies that I have long hair, so that I can access the long hair club or have discounts for prog metal concerts (ah, would not be marvelous if it would be true? :-)). Since I have a smartcard, that I got from the same hairdresser, I will be asked to use it as second authentication factor whenever I will use my managed card. Since I’m a very curious person, as soon as I receive the file I open it with an XML editor and I take a look. You can find it later in the post text.
First thing I notice: the root element is an enveloping signature, here marked in gray. That should not surprise anyone, once the card has been issued nobody should be able to tamper it: the signature prevents exactly that. There’s more: it gives me the cryptographic certainty that it’s really from my hairdresser, since it shows off usage of his private key. The two X509Certificate elements contain 1) the certificate of the hairdresser and 2) the certificate of the CA that issued the certificate to the hairdresser.
When I get past the signature, I finally get to the meat: there’s an element called InformationCard, which contains all the remainder of the file. Will the namespace change before RTM? I have no idea.
The content of InformationCard is not especially “hierarchical”, however it can be subdivided in categories that I color-coded: data about the card itself, list of supported claims and data about the issuer which contains details about the II authentication factor.
Let’s take a closer look at the elements in the various sections.
InformationCardReference contains the card ID and the version; useful in subsequent import operations, so that cards can be updated or overwritten.
CardName contains the mnemonic card name, the only thing that will be possible to modify after the import.
CardImage contains the base64 of the card background graphic, so that the issuer can push the appearance he prefers without depending on the capability of resolving links.
TimeIssued and TimeExpires contain the time of the issuing operation and the card expiration date, respectively.
SupportedClaimTypeList contains the list of claims that will be supported by the card. Single claims are described by the SupportedClaimType element, whose subelements are selfexplanatory. Notice that in this card we use both claims available in the selfissued set (such as http://schemas.microsoft.com/ws/2005/05/identity/claims/givenname) and completely custom claims (like the improbable http://schemas.maseghepensu.it/claims/HairLenght).
Finally we get to the “tough” part, the issuer.
Issuer represents the URI of the STS: this is the address to which we will send our Request Security Token (RST) messages every time we’ll use the managed card. IssuerName is simply the menmonic name associated to it.
TokenServiceList/TokenService contains the data for obtaining the STS metadata, for contacting it securely and for authenticating incoming requests.
EndpointReference is a ws-addressing endpointreference, which contains again the STS endpoint; the Metadata section contains the address of the ws-MetadataExchange endpoint. Note the use of HTTPS: I explained the rationale behind it here.
Identity contains the certificate associated to the STS, typically the same as the one used in the initial signature.
The UserCredential is especially interesting. The element X509V3Credential presence determines the fact that this managed card is backed by an X509 certificate; the KeyIdentifier element contains a sure mean to unambiguoausly identify what is the certificate I want to use (I think it should be the base64 of the hash of the certificate). The DisplayCredentialHint element actually influences the way in which the user is prompted by the Identity Selector when the managed card is used: in thi case the issuer knows that the certificate will live on a smartcard, so the prompt text is designed accordingly.
<Signature xmlns=“http://www.w3.org/2000/09/xmldsig#“>
<SignedInfo>
<CanonicalizationMethod Algorithm=“http://www.w3.org/2001/10/xml-exc-c14n#“ />
<SignatureMethod Algorithm=“http://www.w3.org/2000/09/xmldsig#rsa-sha1“ />
<Reference URI=“#_Object_InfoCard“>
<Transforms>
<Transform Algorithm=“http://www.w3.org/2001/10/xml-exc-c14n#“ />
</Transforms>
<DigestMethod Algorithm=“http://www.w3.org/2000/09/xmldsig#sha1“ />
<DigestValue>5TuCvlZNa6Jh2NGZZpxCDlGoS9c=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>MiWroZZJ…THE SIGNATURE VALUE…ASA==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIG…THE BASE64 OF THE CARD ISSUER CERTIFICATE…DIyPdflaPzuEd</X509Certificate>
<X509Certificate>MIIEdzCC…THE BASE64 OF THE ASSOCIATED CA CERTIFICATE ..+n+nuQ==</X509Certificate>
</X509Data>
</KeyInfo>
<Object Id=“_Object_InfoCard“>
<InformationCardReference>
<CardId>http://www.maseghepensu.it/certificate/101010</CardId>
<CardVersion>1</CardVersion>
</InformationCardReference>
<CardName>Vittorio Hair Card (Certificate)</CardName>
<CardImage MimeType=“image/png“>iVBORw0KGgoAA..THE BASE64 OF THE CARD GRAPHIC..GmB4wAAAABJRU5ErkJggg==</CardImage>
<Issuer>http://www.maseghepensu.it:6700/certificate/sts</Issuer>
<IssuerName>Maseghepensu hairdresser</IssuerName>
<TimeIssued>2006-08-02T17:20:22.548936Z</TimeIssued>
<TimeExpires>9999-12-31T23:59:59.9999999Z</TimeExpires>
<TokenServiceList>
<TokenService>
<EndpointReference xmlns=“http://www.w3.org/2005/08/addressing“>
<Address>http://www.maseghepensu.it:6700/certificate/sts</Address>
<Metadata>
<Metadata xmlns=“http://schemas.xmlsoap.org/ws/2004/09/mex“ xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance“ xmlns:xsd=“http://www.w3.org/2001/XMLSchema“ xmlns:wsx=“http://schemas.xmlsoap.org/ws/2004/09/mex“>
<wsx:MetadataSection xmlns=“”>
<wsx:MetadataReference>
<Address xmlns=“http://www.w3.org/2005/08/addressing“>https://www.maseghepensu.it:7700/certificate/sts</Address>
</wsx:MetadataReference>
</wsx:MetadataSection>
</Metadata>
</Metadata>
<Identity xmlns=“http://schemas.xmlsoap.org/ws/2006/02/addressingidentity“>
<KeyInfo xmlns=“http://www.w3.org/2000/09/xmldsig#“>
<X509Data>
<X509Certificate>MIIGRDCCBSyg..THE STS CERTIFICATE..PzuEd</X509Certificate>
</X509Data>
</KeyInfo>
</Identity>
</EndpointReference>
<UserCredential>
<DisplayCredentialHint>Insert your smartcard please.</DisplayCredentialHint>
<X509V3Credential>
<X509Data xmlns=“http://www.w3.org/2000/09/xmldsig#“>
<KeyIdentifier ValueType=“http://docs.oasis-open.org/wss/2004/xx/oasis-2004xx-wss-soap-message-security-1.1#ThumbprintSHA1“ xmlns=“http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd“>V43s…Q=</KeyIdentifier>
</X509Data>
</X509V3Credential>
</UserCredential>
</TokenService>
</TokenServiceList>
<SupportedTokenTypeList>
<TokenType xmlns=“http://schemas.xmlsoap.org/ws/2005/02/trust“>urn:oasis:names:tc:SAML:1.0:assertion</TokenType>
</SupportedTokenTypeList>
<SupportedClaimTypeList>
<SupportedClaimType Uri=“http://schemas.microsoft.com/ws/2005/05/identity/claims/givenname“>
<DisplayTag>Given Name</DisplayTag>
<Description>Given Name</Description>
</SupportedClaimType>
<SupportedClaimType Uri=“http://schemas.microsoft.com/ws/2005/05/identity/claims/surname“>
<DisplayTag>Last Name</DisplayTag>
<Description>Last Name</Description>
</SupportedClaimType>
<SupportedClaimType Uri=“http://schemas.microsoft.com/ws/2005/05/identity/claims/emailaddress“>
<DisplayTag>Email Address</DisplayTag>
<Description>Email Address</Description>
</SupportedClaimType>
<SupportedClaimType Uri=“http://schemas.microsoft.com/ws/2005/05/identity/claims/privatepersonalidentifier“>
<DisplayTag>Private Personal ID</DisplayTag>
<Description>Private Personal ID</Description>
</SupportedClaimType>
<SupportedClaimType Uri=“http://schemas.maseghepensu.it/claims/HairLenght“>
<DisplayTag>Hair Lenght</DisplayTag>
<Description>The hair lenght, from roots to ends (in cm)</Description>
</SupportedClaimType>
<SupportedClaimType Uri=“http://schemas.maseghepensu.it/claims/HairType“>
<DisplayTag>Hair Type</DisplayTag>
<Description>The hair type. Can be curly, wavy, etc…</Description>
</SupportedClaimType>
<SupportedClaimType Uri=“http://schemas.maseghepensu.it/claims/HairColor“>
<DisplayTag>Hair Color</DisplayTag>
<Description>The hair color. Can be black, red, blonde, etc…</Description>
</SupportedClaimType>
</SupportedClaimTypeList>
<PrivacyNoticeAt>http://www.maseghepensu.it/StsTest/PrivacyPolicy.xml</PrivacyNoticeAt>
</InformationCard>
</Signature>
Figure 1 An example of CRD FILE backed by a smartcard
Very well! Now we have a better idea of what a CRD looks like and what are the purposes of the various elements. What can I add? This example was build around a card supported by a smartcard (but it actually applies to any certificate, regardless of its placement); what about other cases? It’s actually pretty straightforward: the UserCredential section will change accordingly. For example: backing the managed card with a selfissued card would change the UserCredential section in something similar to the fragment below, where SelfIssuedCredential substitutes X509V3Credential and PrivatePersonalIdentifier represents the corresponding value of the selfissued card.
<UserCredential>
<DisplayCredentialHint>false</DisplayCredentialHint>
<SelfIssuedCredential>
<PrivatePersonalIdentifier>4un0VhxkiYIgkbBvwtd4mDFKvkttoqGmHRQiqpFRWdw=</PrivatePersonalIdentifier>
</SelfIssuedCredential>
</UserCredential>
OK, I hope you’ll find this post useful. In the moment in which we will publish official guidance/reference, I’ll promptly update the post with the relevant links. Let me know if you have questions! 🙂
2 Comments