Implementing password digest for ws-security UsernameToken in Java

17,245

I'll take a crack at it without SOAP-UI. The input to the hash function is supposed to be bytes, not a string. DigestUtils.sha() will allow you to use a string, but that string must be properly encoded. When you wrote the nonce, you were calling StringBuffer.append(Object) which ends up calling byte[].toString(). That gives you something like [B@3e25a5, definitely not what you want. By using bytes everywhere, you should avoid this problem. Note that the example below uses org.apache.commons.codec.binary.Base64, not the Base64 class you were using. It doesn't matter, that's just the one I had handy.

ByteBuffer buf = ByteBuffer.allocate(1000);
buf.put(Base64.decodeBase64("PzlbwtWRpmFWjG0JRIRn7A=="));
buf.put("2012-06-09T18:41:03.640Z".getBytes("UTF-8"));
buf.put("password".getBytes("UTF-8"));
byte[] toHash = new byte[buf.position()];
buf.rewind();
buf.get(toHash);
byte[] hash = DigestUtils.sha(toHash);
System.out.println("Generated password digest: " + Base64.encodeBase64String(hash));
Share:
17,245
Stian Sigvartsen
Author by

Stian Sigvartsen

Updated on November 22, 2022

Comments

  • Stian Sigvartsen
    Stian Sigvartsen over 1 year

    I am trying to make a call to a ws-security secured webservice from a server which unfortunately does not support this natively. The approach I have taken is to implement a .jsp which acts as reverse proxy to the actual end point URL, in the process adding the element with ws-security elements.

    This seems to be working quite well and I am confident I've constructed the XML correctly with the correct namespaces etc. I've verified this by comparing the XML with XML produced by SOAP-UI.

    The problem is in implementing the password digest generator. I don't get the same result as what SOAP-UI does using the same inputs for NOnce, xsd:dateTime and password, and the following code.

    StringBuffer passwordDigestStr_ = new StringBuffer();
    
    // First append the NOnce from the SOAP header
    passwordDigestStr_.append(Base64.decode("PzlbwtWRpmFWjG0JRIRn7A=="));
    
    // Then append the xsd:dateTime in UTC timezone
    passwordDigestStr_.append("2012-06-09T18:41:03.640Z");
    
    // Finally append the password/secret
    passwordDigestStr_.append("password");
    
    System.out.println("Generated password digest: " + new String(com.bea.xbean.util.Base64.encode(org.apache.commons.codec.digest.DigestUtils.sha(passwordDigestStr_.toString())), "UTF-8"));
    

    I think the problem is with implementing the hashing of the first two elements as explained by http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf

    Note that the nonce is hashed using the octet sequence of its decoded value while the timestamp is hashed using the octet sequence of its UTF8 encoding as specified in the contents of the element.

    If anyone could help me solve this problem that would be great because it's beginning to drive me crazy! It would be ideal if you could provide source code.

    • John Watts
      John Watts almost 12 years
      Can you please post sample input and output values from SOAP-UI? That way we can try to help with just Java and your code, not SOAP-UI.
  • Stian Sigvartsen
    Stian Sigvartsen almost 12 years
    Thanks for the quick reply. I've tried the snippet and it produces yet another password digest to my code and that of SOAP-UI. I did think the problem I am facing has something to do with character encoding. I can see that my approach with using StringBuffer is clearly flawed. Any chance you could setup a SOAP-UI and see if your algorithm produces equal results? Maybe I set up SOAP-UI wrong!
  • John Watts
    John Watts almost 12 years
    I tried downloading it but it didn't work right away and I don't want to spend a bunch of time messing with it. Can you just attach some sample values of input and output from your copy of SOAP UI?
  • Stian Sigvartsen
    Stian Sigvartsen almost 12 years
    I've posted an answer and awarded you points. I experienced a secondary issue whilst testing this in terms of data/time representation. This webservice client runs in the UK and we are currently UTC+1 = BST (British Summer Time). Howver, at present the webservice expects a dateTime values with a 'Z' suffix on the representation so I would have expected to need to send a date formatted as one hour in the past (UTC). However, it still wants the hour component to be the BST hour representation which I find odd. Do you agree this is not in accordance with XML Schema dateTime data type?
  • John Watts
    John Watts almost 12 years
    I would suggest posting this as a separate question, but yes it sounds incorrect.