I have been looking at a problem over the last week where we were not sure what certificate was being used in a particular case during a secure web service exchanges. It turns out that there are a number of ways a certificate could be referenced and it required a bit of maths to do the correlation. (Also in some cases the full certificate can be included but that is a rather easier correlation problem as you just need to un-base64 and diff) Both of these cases assume you have the ".der" file for the certificate to work with.
In the first example, thanks to Chris M, the SecurityTokenReference contains the serial number of the certificate:
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="str_1VQOGYy2CvP18oEC"> <X509Data xmlns="http://www.w3.org/2000/09/xmldsig#"> <X509IssuerSerial> <X509IssuerName>CN=CertGenCAB,OU=FOR TESTING ONLY,O=MyOrganization,L=MyTown,ST=MyState,C=US</X509IssuerName> <X509SerialNumber>9652974370220359889588047549019486289</X509SerialNumber> </X509IssuerSerial> </X509Data> </wsse:SecurityTokenReference>
Now I came up with the following which uses openssl to print out the serial number, in hex, and then convert it to decimal so you can compare it with the value in the soap message. If you know more unix voodoo than me feel free to comment with a more optimal version, thanks to Alan Davis for some help here.
[gdavison Certificates]$ ( echo ibase=16 ; openssl x509 -serial -inform der -noout -in ClientCert.der ; echo serial ) | bc -q 9652974370220359889588047549019486289
It is worth know you can convince openssl to dump your entire certificate in a pretty form using the -text option if you want to look at it a bit closer:
[gdavison@ukp79266 Certificates]$ openssl x509 -inform der -noout -text -in ServerCert.der Certificate: Data: Version: 1 (0x0) Serial Number: (Negative)79:76:ab:94:51:fe:b5:7c:a5:c8:15:88:1d:15:a6:31 Signature Algorithm: md5WithRSAEncryption Issuer: C=US, ST=MyState, L=MyTown, O=MyOrganization, OU=FOR TESTING ONLY, CN=CertGenCAB Validity Not Before: Jan 19 13:46:59 2009 GMT Not After : Jan 20 13:46:59 2024 GMT Subject: C=US, ST=MyState, L=MyTown, O=MyOrganization, OU=FOR TESTING ONLY, CN=XXXXXX Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) Modulus (1024 bit): 00:a4:9b:ae:fe:57:0f:5b:23:11:9c:60:f0:b0:29: 2a:6a:2d:d5:3e:44:a9:84:c4:a3:52:7a:d2:1c:1e: bf:ed:eb:5d:90:20:8f:05:da:a1:1c:7b:67:90:36: 2e:7d:f9:c5:6e:82:25:b8:72:9a:25:7f:20:d7:ec: 9b:dd:d5:a0:95:8a:a0:df:20:d7:f7:04:89:da:17: 9c:d7:ce:f8:7f:fa:59:03:dc:ad:3b:51:ba:ad:57: f4:5a:e6:29:85:8e:02:c9:a4:36:35:fb:a2:17:70: 74:ab:56:a3:ed:ed:c0:d8:26:f8:68:4f:ad:78:b5: 53:cd:f4:7b:93:e0:05:55:fd Exponent: 65537 (0x10001) Signature Algorithm: md5WithRSAEncryption 3f:d6:e7:0b:00:0c:14:13:90:9e:7d:de:cf:46:4d:9d:3e:f3: 57:fa:27:6c:0c:bf:b0:9e:d8:91:93:6b:47:e5:62:31:29:52: b2:b5:3e:b8:1b:ac:2d:c0:b3:38:ab:e5:f6:5c:30:5f:04:7b: 4f:90:90:75:25:81:59:33:24:e8
In the second example we have the following key info but this in case uses the sha1 of the key in base64 format:
<ns3:KeyInfo xmlns:ns3="http://www.w3.org/2000/09/xmldsig#"> <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsse11:TokenType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="str_fC2JkjjyT0mUbvXk"> <wsse:KeyIdentifier EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1" >eF68uMnGeydQmRc69mWanQzAek0=</wsse:KeyIdentifier> </wsse:SecurityTokenReference> </ns3:KeyInfo>
You can easily use the openssl command and base64 to convert you certificate into the required format for comparison. You can work out what processes you need to apply by looking at the ValueType, ThumbprintSHA1, and the EncodingType, Base64Binary, in this case. It would be relatively easy to generate the correct string should another hashing algorithm be specified.
[gdavison Certificates]$ openssl dgst -binary -sha1 ClientCert.der | base64 eF68uMnGeydQmRc69mWanQzAek0=
The upshot of this is whilst the structure and format of the certificate files can be intimidating at first the openssl tool can be used to make things more transparent.