Friday, October 24, 2008

X.509 interoperability & SubjectKeyIdentifier

@YaronNaveh

I've already highlighted some X.509 interoperability issues before. This time we will talk about correctly referencing certificates.

A client that uses a server certificate in order to encrypt a message needs to reference this certificate in code. Inside the message the reference would typically look like this:


  <o:SecurityTokenReference>
   <keyName>CN=someServer</keyName>
  </o:SecurityTokenReference>


Or this:

  <o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">sWTM4Q7da6N9q2kYYYhn+jnnsv4=</o:KeyIdentifier>


Or this:


  <wsse:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"<bBwPfItvKp3b6TNDq+14qs58VJQ=</wsse:KeyIdentifier>


Or in any of a few other formats.

The required format can be declared in WS-Policy. For example:


<wsp:Policy>
   <sp:RequireKeyIdentifierReference />
   <sp:WssX509V3Token10 />
</wsp:Policy>


However many services do not have WS-Policy so it's not a must.

There are various ways to get this SKI from a certificate. Some of them are:

  • The certificate might contain an out-of-band generated SKI inside it as an "extension".



  • An SHA1 thumbprint is calculated out of the certificate raw data.

  • The certificate serial number and issuer name are used

  • The certificate subject name is used

  • The SKI needs to be calculated from the certificate using some algorithm

    Guess which option causes us most trouble? Right, the last one. The problem is that it is not concrete enough. There were a few ways to generate this SKI and so there were misunderstandings between Java and Microsoft applications and even between different versions of the same frameworks.

    Let's take a sample certificate as an example. First convince yourself that it does not contain SKI extension:



    Now look at the format WebSphere 6 server would expect:


    M9WWSXczVFt2otJ3adPjfmbUxU8=


    WSE2 would generate:


    bBwPfItvKp3b6TNDq+14qs58VJQ=


    And WSE 3 generates this one:


    SdPjfmbUxU8=


    With WCF you would get the following exception:


    System.NotSupportedException:

    "'X509SecurityToken' does not support 'X509SubjectKeyIdentifierClause' creation."


    As WCF does not work with certificates that do not have SKI when the latter is explicitly required - and that's what I did for this sample.

    So by all and all we've got 4 different SKI's out of one certificate!

    Out of these 4 frameworks there is a way to interoperate using SKI and X.509 that does not contain SKI extension between the following:



    Note: It is possible to interoperate between these platform in various other ways. If you now design your system you should use these ways. The information here is provided for those who are already working with a given systems.

    So how can we reach this interoperability?

    To interoperate with WebSphere all you need to do is to change WSE2 configuration to:


       <microsoft.web.services2>
         <security>
           <x509 ... useRFC3280="true" />
    ...
         </security>
       </microsoft.web.services2>


    And it will generate a WebSphere-like SKI (which is more standard all around).
    To interoperate between WSE2 and WSE3 you need to leave the default WSE2 configuration as is and change WSE3:


    <microsoft.web.services3>
       <security>
         <keyIdentifierMapping>
           <x509 ... skiMode="CAPI" />
    ...
         </security>
       </microsoft.web.services3>


    Note: even though WSE 3 allows skiMode="RFC3280" as WSE2 does the calculation is different and will not interoperate.

    As for the rest - you would have to use a certificate with an SKI extension or use another type of reference instead.

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!
  • 6 comments:

    Anonymous said...

    When you say "A client that uses a server certificate in order to encrypt a message needs to reference this certificate in code.", what do you mean? Do you have an example?

    I have a server certificate from a company that does not have a "Subject Key Identifier" in the certificate, and I'm getting the following error: "WSS1852: KeyIdentifier value cannot be empty. Possible cause, certificate version being used does not support SubjectKeyIdentifier."

    Is there a way to as the "Subject Key Identifier"? Or perhaps a workaround?

    Love your series of blogs, by the way! I've learned a lot... need to add a paypal tip jar.

    Yaron Naveh said...

    Hi Anonymous

    I actually meant that the client message needs to reference the certificate, not the code. The samples followed.

    As for your problem, you need to compare the soap message you send to the a valid soap message the vendor can provide or a valid message you can generate from a different framework (e.g. the same one the server uses).

    Chances are you will find a lot of differences in versions and formats and need to handle them. The exact instructions really depend in the protection requirements and the framework you use. Also if WS-Policy is used in the WSDL it is easier. If you're lucky the only difference will be in the SKI in which case the solution depends in the frameworks used in the client and the server.

    A paypal tip jar is a good idea, I've just added it...

    Hernan said...

    What does this error mean??

    "The key identifier iqOqsSjOoZyoO923bRNF8IeN/wU= retrieved from the message is different from the key identifier vmFljXX4Bpp4awaZeM3pL9nPf3s= acquired from the keystore Path: C:\Datos Hernan\ESB\Test\SG247758\Chapter6\ITSO7758\receiver.jks."

    I have already tested those keys with a java client and they are ok. What should i do?? pls help me!!!

    Yaron Naveh (MVP) said...

    Hernan

    Compare the WCF request to the working java client request.

    Most probably your WCF and java clients use different certificates.

    Hernan said...

    I have already done it, and they are different. But they are the same certificates they have the same information, how do you recommend create a certificate from a java keystore?

    Yaron Naveh (MVP) said...

    http://travisspencer.com/blog/2009/10/exporting-keys-from-a-jks-and.html