SignedXml.CheckSignature() can’t find the certificate for verification
The System.Security.Cryptography.Xml namespace has been there since the dawn of time, and the look and feel of the API is rough at best. To top that, the MSDN documentation isn’t really something to lean on either, and it’s been a long, long time since I last tried to get acquainted with it.
I’ve done some work to integrate Windows Identity Foundation (WIF) with the ESB we’re using at work, and I wanted to implement message security (encryption and signing). Since the messages are XML-based, and that I really didn’t want any homegrown security solutions, I found it natural to use EncryptedXml and SignedXml from the aforementioned namespace to do the job. My weapon of choice was x509 certificates and the proof-of-possession key (AES-256-CBC) from the SAML 1.1 token issued by the STS, and by tweaking the EncryptedXml configuration, I managed to massage the information about the x509 key down to a bare minimum (to keep the message size down).
Now, creating the detached signature on the publisher side was a no-brainer as well, but on the other end of the “cable” I wasn’t able to verify the signature. I tried “everything”, but to no avail. I bugged Barry Dorrans (@blowdart) on Twitter, since he’s as a guy that knows “a thing or two” about .NET Security. Barry had a couple of pointers, but none that resolved my issue.
So, weaponed with the .NET Reflector and some moral support from Barry via email, I started to dig into the System.Security assembly. It reeks of all sorts of code smells, and it took a while before I found the piece of information I was looking for:
Using SignedXml.CheckSignature() w/o sending in an X509Certificate2 instance explicitly, will only look in Current User\Other People or Local Machine\Other People. Be aware that Other People is an alias for AddressBook too.