'.net server cannot verify CXF client signature with MTOM enabled

I have to write a SOAP client in Java to connect to a .net server with MTOM enabled and secured using TransportWithMessageCredential + Certificate.

The WSDL policies are:

<wsp:Policy wsu:Id="BasicHttpBinding_ITheirService_policy">
  <wsp:ExactlyOne>
    <wsp:All>
      <wsoma:OptimizedMimeSerialization xmlns:wsoma="http://schemas.xmlsoap.org/ws/2004/09/policy/optimizedmimeserialization"/>
      <sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
        <wsp:Policy>
          <sp:TransportToken>
            <wsp:Policy>
              <sp:HttpsToken RequireClientCertificate="false"/>
            </wsp:Policy>
          </sp:TransportToken>
          <sp:AlgorithmSuite>
            <wsp:Policy>
              <sp:Basic256/>
            </wsp:Policy>
          </sp:AlgorithmSuite>
          <sp:Layout>
            <wsp:Policy>
              <sp:Lax/>
            </wsp:Policy>
          </sp:Layout>
          <sp:IncludeTimestamp/>
        </wsp:Policy>
      </sp:TransportBinding>
      <sp:EndorsingSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
        <wsp:Policy>
          <sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
            <wsp:Policy>
              <sp:WssX509V3Token10/>
            </wsp:Policy>
          </sp:X509Token>
        </wsp:Policy>
      </sp:EndorsingSupportingTokens>
      <sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
        <wsp:Policy>
          <sp:MustSupportRefKeyIdentifier/>
          <sp:MustSupportRefIssuerSerial/>
        </wsp:Policy>
      </sp:Wss10>
    </wsp:All>
  </wsp:ExactlyOne>
</wsp:Policy>

I've tested it with a .net client first and everything works fine, it has the following config:

<binding name="BasicHttpBinding_ITheirService"
  closeTimeout="00:10:00" openTimeout="00:10:00" 
  receiveTimeout="00:10:00" sendTimeout="00:10:00" 
  maxReceivedMessageSize="10485760" messageEncoding="Mtom">
  <security mode="TransportWithMessageCredential">
  <message clientCredentialType="Certificate"/>
  </security>
</binding>

BUT! I can't make it work in Java and CXF. So far I have the following:

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(ITheirService.class);
factory.setAddress("https://blah.gov/ETheirService.svc");

LoggingFeature lf = new LoggingFeature();
lf.setPrettyLogging(true);
factory.getFeatures().add(lf);

ITheirService port = (ITheirService) factory.create();
BindingProvider bp = (BindingProvider) port;
SOAPBinding binding = (SOAPBinding) bp.getBinding();
binding.setMTOMEnabled(true);

Map<String, Object> outProps = new HashMap<>();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE);
outProps.put(WSHandlerConstants.SIG_PROP_FILE, "foo-security.properties");
outProps.put(WSHandlerConstants.USE_SINGLE_CERTIFICATE, Boolean.TRUE.toString());
outProps.put(WSHandlerConstants.USER, "1"); // Alias
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, FoobarPasswordCallback.class.getName());
outProps.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
outProps.put(WSHandlerConstants.MUST_UNDERSTAND, "1");
outProps.put(WSHandlerConstants.SIGNATURE_PARTS, "{}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp}");
outProps.put(WSHandlerConstants.ADD_INCLUSIVE_PREFIXES, Boolean.FALSE.toString());

WSS4JOutInterceptor outInterceptor = new WSS4JOutInterceptor(outProps);
client.getOutInterceptors().add(outInterceptor);

port.bar();

And here is my foobar-security.properties:

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.file = foobar.pfx
org.apache.ws.security.crypto.merlin.keystore.type = PKCS12
org.apache.ws.security.crypto.merlin.keystore.password = blahblah

The request from the .net looks like this:

--uuid:27598dec-dab6-462f-b058-66bc0991c155+id=1
Content-ID: <http://tempuri.org/0>
Content-Transfer-Encoding: 8bit
Content-Type: application/xop+xml;charset=utf-8;type="text/xml"

<s:Envelope
  xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <s:Header>
    <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <u:Timestamp u:Id="_0">
        <u:Created>2022-05-03T18:29:43.225Z</u:Created>
        <u:Expires>2022-05-03T18:34:43.225Z</u:Expires>
      </u:Timestamp>
      
      <o:BinarySecurityToken u:Id="uuid-fbd05bc1-03a0-4346-bcca-43b8ea47c793-1" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
        <xop:Include href="cid:http://tempuri.org/1/637872101832539604" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
      </o:BinarySecurityToken>
      
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
          <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
          
          <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          
          <Reference URI="#_0">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <DigestValue>QYKqdh3C61s43xmQgT3ZQeOckpc=</DigestValue>
          </Reference>
        </SignedInfo>
        <SignatureValue>Iz06InedLGt87Fd2LE...</SignatureValue>
        
        <KeyInfo>
          <o:SecurityTokenReference>
            <o:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" URI="#uuid-fbd05bc1-03a0-4346-bcca-43b8ea47c793-1"/>
          </o:SecurityTokenReference>
        </KeyInfo>
      </Signature>
    </o:Security>
  </s:Header>
  <s:Body>
    <Bar xmlns="https://blah.gov/theirservice"/>
  </s:Body>
</s:Envelope>

--uuid:1cdee7e9-0d60-4816-8f2b-65d4008226e1+id=1
Content-ID: <http://tempuri.org/1/637872101832539604>
Content-Transfer-Encoding: binary
Content-Type: application/octet-stream
BYTES HERE

And the one from my Java + CXF app is:

--uuid:16e4cb9f-572a-49d7-ad17-4236bdec84b4
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <[email protected]>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <wsse:Security 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" soap:mustUnderstand="1">
      <wsse:BinarySecurityToken xmlns:xop="http://www.w3.org/2004/08/xop/include" 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/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="X509-b6789cd3-9c2a-4238-b14c-16bd5d8474d6">
        <xop:Include href="cid:227ea9d7-abf6-4f8e-a969-97fc06da6b97"/>
      </wsse:BinarySecurityToken>
      
      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-fa41f70a-b3ca-49d2-866e-2e7376aa2758">
        <ds:SignedInfo>
          <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
          <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          
          <ds:Reference URI="#TS-e248320c-b7da-49d1-bb04-f8379ef65219">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>fHaFLZuu93imU3bSrBUlBseOmF4=</ds:DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        
        <ds:SignatureValue>UMNSiPpIfkreoJ8lNfiUd2U8Y...</ds:SignatureValue>
        <ds:KeyInfo Id="KI-d99eb5ab-a694-4385-a4dd-6a9a108e2550">
          <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-eb21be32-56d8-4c30-9f85-611d37494d32">
            <wsse:Reference URI="#X509-b6789cd3-9c2a-4238-b14c-16bd5d8474d6" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
          </wsse:SecurityTokenReference>
        </ds:KeyInfo>
      </ds:Signature>
      
      <wsu:Timestamp wsu:Id="TS-e248320c-b7da-49d1-bb04-f8379ef65219">
        <wsu:Created>2022-05-08T12:03:20.549Z</wsu:Created>
        <wsu:Expires>2022-05-08T12:08:20.549Z</wsu:Expires>
      </wsu:Timestamp>
    </wsse:Security>
  </soap:Header>
  <soap:Body>
    <Bar xmlns="https://blah.gov/theirservice" xmlns:ns2="http://schemas.datacontract.org/2004/07/TheirService.Common.DataContracts" xmlns:ns3="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:ns4="http://schemas.datacontract.org/2004/07/TheirService.Common.DataContracts.ESubject" xmlns:ns5="http://schemas.microsoft.com/2003/10/Serialization/" xmlns:ns6="http://schemas.datacontract.org/2004/07/TheirService.Common.Enums"/>
  </soap:Body>
</soap:Envelope>


--uuid:16e4cb9f-572a-49d7-ad17-4236bdec84b4
Content-Type: application/ciphervalue
Content-Transfer-Encoding: binary
Content-ID: <227ea9d7-abf6-4f8e-a969-97fc06da6b97>
BYTES HERE

To me the requests look the same, the only difference is the "Content-Transfer-Encoding" for the envelope and the "Content-Type" for the cipher. From what I've seen from the .net request, I have to sign only the timestamp and the request is not encrypted.

Unfortunately, I don't have access to the server logs to see what I'm doing wrong and the only error I'm getting from it is "An error occurred when verifying security for the message."

The Java version is 1.8 The CXF is 3.5.2

I'm sorry for the long post!



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source