An MSDN forum post shows what is probably someone trying to understand how the client of CRM webservices formulates a signed request. Their scenario seems to have been a local ADFS communicating with a local CRM. For us, our scenario is a little more complex: a web-site client of Exchange webservices (read CRM) must talk to a sequence of STS the last of which, MicrosoftOnline issues the equivalent of what we see here – an encryptedData wrapper around a SAML assertion, AND, evidently, the parameters for the client to compute its symmetric hashing-key. to be used in proof services for the eventual web service call.
In the marked-up example given above we see a soap message with header and body. The simple body is a web method request, and the headers support addressing, security and identity of that request.
We see 3 security headers: 1) a timestamp, and 2) an encryptedData (ciphertext of a SAML assertion in all likelihood), and 3) a signature block.
As the original poster commented, we can see that the signature is over the timestamp as indicated by the reference #_0. This practice is consistent with the desire to address MITM – or the substitution of the encrypted data token.
Thus, we see the signature is computed directly over the timestamp but also indirectly over the securitytokenreference field within it’s the detached signature’s own keyinfo content. We can guess that the assertion reference cites the token within the encrypted data – to be unsealed by the intended web service endpoint by normal processes: unwrapping DES key, obtaining the assertion content, obtaining thereby the rsa-wrapped symmetric proof key, which upon being reduced to clear text key provides the signature hashing parameter to be used in verifying the signature… over the timestamp.
Since the sender may not have access to the saml assertion (particularly in the case of microsoft online federated identity scenarios), it seems doubtful that the signature is computed over the assertion cleartext. Rather, the party that had the power to obtain the encryptedData token from an STS also had the unique power to obtain the client-side of the proof token. Since there is a double sealing of the recipient’s side this key, within the encrypted-Data of the assertion as a whole and then the RSA-wrapped confirmation field within said cleartext assertion, the requestor’s signature over the timestamp can only be verified by the authorized and intended recipient.
For future information seekers, here’s what worked for me.
1. Digest value – canonicalize the timestamp xml, do a simple SHA1 hash on it.
2. Place the digestvalue in the ‘signedInfo’ and canonicalize the SignedInfo XML.
3. Calculate a derived PSHA1 key based on the trust:BinarySecret of the original token request (‘main’ key) and the trust:BinarySecret (seed/nonce/secondary key) of the token response.
4. Hash the binary version of the base64 of your canonicalized signedxml as HMACSHA1, with the derived key as the secret, and turn the result hash back into Base64, that’s your SignatureValue
The non-specialists view of the process is given above (and its basically correct, if you squint a little on the language used). The same party may have not understood that the proof key process is standard…and didn’t need to be reverse engineered:
Now, we should be able to find sample source code that performs these core processes. Something more modern than, but along the lines of, http://msdn.microsoft.com/en-us/library/ms996952.aspx
After 5m work, we can at sign some blob of XML using dotnet and an ephemeral RSA key – this contrasting with the hmac code that follows:
Obviously, the next skill to figure is to create an XML digital signature with a symmetric key rather than an RSA key, instead. This turns out to be rather trivial (barring things like choose the right algorithm details for such as canonicalization):
to sort those things takes a little digging around for 15m, but is trivially easy (once you know how):
To now signal the source of the keying material, lets recall our model:
The note at http://stackoverflow.com/questions/12832213/how-to-make-wcf-client-conform-to-specific-ws-security-sign-usernametoken-and Seems to offer good starting info, giving us:
Knowing that our original is slightly screwy, we can look around at a few MSDN notes and get something that looks about right:
This gives us a symmetrically-signed, basically-canonicalized signature over some bit of XML, with a key of our choice. And, we can give a reference to the source of such a key, as a saml token reference.
So, now the question comes up that assuming we have an encryptedData, how do we know the assertionid of the token within? Presumably, this is the role of the non-attached references in the RSTR, or similar.
As the prover, we can use the internal assertion ref in formulating the signature, from the GenericXMLSecurityToken ( a semi secret). As the verifier, we would decrypt the token to cleartext and presumably add it to some kind of (token) resolver, to be used by the signature verifier as followed by using reference cues from the token block, as its elements are granted integrity status.
Yea! JUST HAPPENS to have assertion ID beginning with _fed!
Here we sign the assertion (rather than a SOAP timestamp field). we don’t reference the id of that timestamp header… and probably would need to properly construct documents before signing, so namespace declarations are properly placed.
Now, in the next memo, let’s try having the Microsoft client API for Exchange do all these processes. Then we can do the same.