Charlie Brown
Charlie Brown

Reputation: 2825

Soap Canonicalization Transform

I am trying to work with a soap service hosted on a Datapower appliance. So far, the sending soap service and the receiver calculate the digest differently for the following xml.

The transform that is applied to create the digest value

<ds:Reference URI="#TS-f3c103e9-1897-43d8-8cf6-274bdb647678">
    <ds:Transforms>
       <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
          <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="wsse soap"/>
       </ds:Transform>
   </ds:Transforms>
   <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
   <ds:DigestValue>1rjXQQWVMM5KBWY8uswUynk6PCk=</ds:DigestValue>
</ds:Reference>

The referenced element.

<wsu:Timestamp wsu:Id="TS-f3c103e9-1897-43d8-8cf6-274bdb647678">
  <wsu:Created>2016-02-24T15:32:12.693Z</wsu:Created>
  <wsu:Expires>2016-02-24T15:37:12.693Z</wsu:Expires>
</wsu:Timestamp>

Namespaces for above elements are applied on the root node

Sending the above XML works correctly (created from a Java soap client library). However, when I digest that same element with sha1 in node, I get a different digest value.

I am trying to discover what java does in the transform before calculating the digest value. If I can figure out what it actually sends to its sha1 method, I can correct the code in node to do the very same.

Given the above reference element, what is the output xml after the transform prior to hashing with sha1?

Upvotes: 4

Views: 1370

Answers (1)

rjp
rjp

Reputation: 151

You need to figure out how your java library or API creates the canonicalized XML that it sends to the SHA1 method.

Using Apache Commons Codec (https://commons.apache.org/proper/commons-codec/) and guessing the C14N'd XML from the Timestamp element and the included namespaces in the Transform element, I was able to get the same digest value: 1rjXQQWVMM5KBWY8uswUynk6PCk=

Here's the code that I used:

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;

public class Sha1Test {

    public static void main(String args[]) throws Exception {
        String data = "<wsu:Timestamp xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" 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=\"TS-f3c103e9-1897-43d8-8cf6-274bdb647678\"><wsu:Created>2016-02-24T15:32:12.693Z</wsu:Created><wsu:Expires>2016-02-24T15:37:12.693Z</wsu:Expires></wsu:Timestamp>";
        printShaDigest(data);
    }

    static void printShaDigest(String data) {
        System.out.println("data = " + data);
        System.out.println("sha1 = " + new String(Base64.encodeBase64(DigestUtils.sha1(data.getBytes()))));
    }

}

Upvotes: 2

Related Questions