July 23rd, 2014

PSHA1 Algorithm for WS-Trust Server and Client Entropy Scenarios on Node.js

I’ve just published a new Node.js module that implements the P_SHA1 algorithm as specified in TLS spec, that is used on WS-Trust spec in scenarios where the service you want to call requires client and server entropy. It has been tested with Microsoft CRM Dynamics and ADFS.

You can find the library here https://github.com/leandrob/node-psha1

A little context

As a security feature WS-Trust supports Proof-of-Possession Tokens. A proof-of-possession (POP) token is a security token that contains secret data that can be used to demonstrate authorized use of an associated security token, thereby the final service (relying party) can validate that the caller is the “real” owner of the token that he is presenting. Typically, although not exclusively, the POP token consist of a key known by the relying party.

WS-Trust specifies two ways of use proof-of-possession token keys: specific and partial.

When you use specific keys, the requestor can specify the key when he requests the token or the security token service can retrieve the key in the request security token response inside of the <wst:RequestedProofToken>. In both cases you just need to use the specific key to sign the requests you perform to the relying party (final service)

When you use partial keys, the final key, the key with which you will sign the requests you perform to the relying party must be calculated combining two keys: client key and server key.

In this scenario, also known as client and server entropy, when requesting the security token the client must specify a random key using the <wst:Entropy> element inside of the <RequestSecurityToken> structure, and the security token service must respond with another key, using the same element (<wst:Entropy>) inside of the <RequestSecurityTokenResponse> message. At the same time, the server will return a <wst:ComputedKey> element to indicate how the final key is computed.

<t:RequestSecurityTokenResponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
   <t:Entropy>
      <t:BinarySecret>pSvudXqeURG8H0MrrKr2H+Q7nJ51WrcRJphoqcvGWu0=</t:BinarySecret>
   </t:Entropy>
   <t:RequestedProofToken>
     <t:ComputedKey>http://docs.oasis-open.org/ws-sx/ws-trust/200512/CK/PSHA1</t:ComputedKey>
   </t:RequestedProofToken>
</t:RequestSecurityTokenResponse>

While this can be extended, the default mechanism in WS-Trust 1.3 spec is the PSHA1 algorithm (defined in TLS spec, identified by this uri: http://docs.oasis-open.org/ws-sx/ws-trust/200512/CK/PSHA1 (also http://schemas.xmlsoap.org/ws/2005/02/trust/CK/PSHA1 is possible)

To resume, that means that both keys, client and server must be combined using the PSHA1 algoritm, and that is what this module implements.

How do I know if the service I want to consume requires client and server entropy?

That is easy, it is described in the WSDL of the service using WS-Policy, you will find something like this:

<sp:Trust13 xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
   <wsp:Policy>
     <sp:MustSupportIssuedTokens/>
     <sp:RequireClientEntropy/>
     <sp:RequireServerEntropy/>
   </wsp:Policy>
</sp:Trust13>

Usage

The usage is very simple, you just need to provide client key, server key, and key size.

var psha1 = require('psha1');

var key = psha1('GS5olVevYdlK4/rP8=', 'LmF9Mjf9lYMHDx376jA=', 256);

In the next post I will show how to sign a request using this key.

Hope be useful!

  • That is super helpful! But… since I got this part working… When will the next blog post be available? 😀

    • Thanks for your comment! I haven’t had enough time to write that post yet, but I think that maybe this weekend I’ll have that published!

      • That’d be awesome :o)
        I already know how to compute the DigestValue for xml-exc-c14n+sha1, but I’ve got problems to understand how the SignatureValue is computed… I also don’t know what the RequestedTokenProof has to do with all these things…

  • martijnburgers

    Thanks for your explanation en and the code!

    • You are welcome! It’s good to know that you found it useful!

  • aroth

    Is there an established convention for determining in which order the client key and server key are passed to the psha1 function? Is it standard that the client key is always the first parameter, or may different implementations expect a different order?

    And also, do you have a link to the post demonstrating how to actually use the shared key once you have it?