title: Signing SOAP messages using X.509 certificate from WCF service to Java webservice
body: <p>It's my first question over the web. Hope it will make sense.</p>
  
  <p>I have seen several blogs related to this issue over the Web, and I have tried few of the ideas presented in them with no success. Here's my situation:</p>
  
  <p>I have a web App calling a WCF web service which then call a Java web service. They are all on different servers. The call between the WCF web service to the java web service is not over https as the certificate will be enough to identify the caller (Message security therefore).</p>
  
  <ul>
  <li><strong>Java web service (black box)</strong></li>
  </ul>
  
  <p>The Java web service requires to received a signed message and works as per below:<br>
  Before each request is processed a handler intercepts all incoming messages and performs the following validation rules:<br>
  1. Does the message contain a security header<br>
  2. Does the message contain the correct security header ID<br>
  3. Is the message been signed correctly<br>
  4. Does the message contain a KeyInfo x.509 certificate<br>
  5. Is the certificate issued from a trusted CA – configuration based<br>
  6. Is the certificate valid (not expired, revoked)<br>
  7. Does the certificate contain the correct policy OID  </p>
  
  <p>Once all of these steps have been confirmed then the message can be processed, if any step fails then a soap message exception will be returned.</p>
  
  <p>The SOAP security header should validate against xxx...w3.org/TR/SOAP-dsig/ digital signature specification.</p>
  
  <p>The most complete description can be found here xxx...ibm.com/developerworks/webservices/library/ws-security.html this IBM article lists the details of each WS-Security header, additionally a sample signed SOAP message has been provided.</p>
  
  <p>When signing the SOAP message you must also add they x.509 certificate into the message KeyInfo this is required for the certificate validation.</p>
  
  <p>SOAP Request should like this:  </p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"&gt;
  &lt;S:Header&gt;
  &lt;ds:Signature xmlns:ds="xxx...w3.org/2000/09/xmldsig#" Id="Signature001"&gt;
  &lt;ds:SignedInfo&gt;
  &lt;ds:CanonicalizationMethod Algorithm="xxx...w3.org/TR/2001/REC-xml-c14n-20010315"/&gt;
  &lt;ds:SignatureMethod Algorithm="xxx...w3.org/2000/09/xmldsig#rsa-sha1"/&gt;
  &lt;ds:Reference URI=""&gt;
  &lt;ds:Transforms&gt;
  &lt;ds:Transform Algorithm="xxx...w3.org/2000/09/xmldsig#enveloped-signature"/&gt;
  &lt;/ds:Transforms&gt;
  &lt;ds:DigestMethod Algorithm="xxx...w3.org/2000/09/xmldsig#sha1"/&gt;
  &lt;ds:DigestValue&gt;soe1PnaGXVGrsauC61JSHD+uqGw=&lt;/ds:DigestValue&gt;
  &lt;/ds:Reference&gt;
  &lt;ds:Reference URI="#KeyInfo001"&gt;
  &lt;ds:DigestMethod Algorithm="xxx...w3.org/2000/09/xmldsig#sha1"/&gt;
  &lt;ds:DigestValue&gt;Y9SRPQ9TcDu+GazO3LFwodEdhaA=&lt;/ds:DigestValue&gt;
  &lt;/ds:Reference&gt;
  &lt;/ds:SignedInfo&gt;
  &lt;ds:SignatureValue&gt;jBX/8XkY2aCte7qgXEp1sbNWmQcK/90iVL58sAvwYAEcBABGzOk2agxR0HvWrNa6ixkocAQ205lggwOxnxZJvoVozVYAAjcLtayPBOUYrnSEBFrwKWP/vxgvUDRIdXeIuw5GLY87NrTQMm1Ehf/HvMX9hTBJn4Nm8RdDiUmPcIo=&lt;/ds:SignatureValue&gt;
  &lt;ds:KeyInfo Id="KeyInfo001"&gt;
  &lt;ds:X509Data&gt;
  &lt;ds:X509Certificate&gt;MIIEbZCCA1WgAwIBAgIES1XpMjANBgkqhkiG9w0BAQUFADBYMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFzAVBgoJkiaJk/IsZAEZFgdlbnRydXN0MRIwEAYDVQQDEwllbnRydXN0U00xEjAQBgNVBAMTCWVudHJ1c3RDQTAeFw0xMDA0MjIxMDQ4MDBaFw0xMzA0MjIxMTE4MDBaMGoxFTATBgoJkiaJk/IsZAEZFgVsb2NhbDEXMBUGCgmSJomT8ixkARkWB2VudHJ1c3QxEjAQBgNVBAMTCWVudHJ1c3RTTTESMBAGA1UEAxMJZW50cnVzdENBMRAwDgYDVQQDEwdSYnMgUmJzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMf88L2JjLPG1hNmTA/KBiC53WVwS2WU9Jh3lC1Rob6RMzOojomZ/dNrvSRB6nzWeXJpZXwik4XFrsAq24By2SZpLTO4p8Vcq71mTAfDu33cnO49Au2pwNvcMn5qIKBk1Xx+oVb4fzK9ncTRu7bW46HsIYth+qkGhbI2JEHwr/zwIDAQABo4IBrzCCAaswCwYDVR0PBAQDAgeAMCsGA1UdEAQkMCKADzIwMTAwNDIyMTA0ODAwWoEPMjAxMjA1MjgxNTE4MDBaMCMGA1UdIAQcMBowCwYJYIZIAYb6awoEMAsGCSqGSIb2fQdLAzAbBgNVHQkEFDASMBAGCSqGSIb2fQdEHTEDAgEBMIHGBgNVHR8Egb4wgbswb6BtoGukaTBnMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFzAVBgoJkiaJk/IsZAEZFgdlbnRydXN0MRIwEAYDVQQDEwllbnRydXN0U00xEjAQBgNVBAMTCWVudHJ1c3RDQTENMAsGA1UEAxMEQ1JMMTBIoEagRIZCZmlsZTovLy8vTVNJREhVLTQ0NUE0RkVFL0NSTC9lbnRydXN0Y2FfZW50cnVzdHNtX2xvY2FsX2NybGZpbGUuY3JsMB8GA1UdIwQYMBaAFBvSL6cPz8L5shubV58yf0pczKzuMB0GA1UdDgQWBBT1/j6OSS8FTjwqluvew16sv7h+VzAJBgNVHRMEAjAAMBkGCSqGSIb2fQdBAAQMMAobBFY4LjADAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQBXxRIA4HUvGSw4L+4uaR51pY4ISjUQWo2Fh7FYBMt29NsKCTdur1OWVVdndt1yjXP4yWXxoAhHtvZL+XNALUFlR2HAWiXuL1nRcxHkB98N5gPqQzW/lJk9cLtL4hVp28EiEpgmKT3I3NP2Pdb2G5MMOdvQ/GFb2y6OwblR8ViPQ8B2aHWzXMrH+0qadPAuBhXyAohwb+mMuYT/ms6xpGi1NMYuYMf6XONz9GkZgnGnMwa+9CCQws1HNz8WYHtmFIxLsVuEWc/0a1vg4IYX1Ds/ttyhJGTVXOSJSkBz8kRyj1pNBDdc1KeG8M++O8m8VgRTJvYaPc7NMiclISukGpea&lt;/ds:X509Certificate&gt; &lt;/ds:X509Data&gt;
  &lt;/ds:KeyInfo&gt;
  &lt;/ds:Signature&gt;
  &lt;/S:Header&gt;
  &lt;S:Body Id="ABC"&gt;
  &lt;ns2:createUser xmlns:ns2="http://webservice.rbs.emea.ps.entrust.com/" xmlns:ns3="http://webservice.rbs.emea.ps.entrust.com/types/CertificateException" xmlns:ns4="http://webservice.rbs.emea.ps.entrust.com/types/UserException"&gt;
  &lt;userID&gt;0061020051&lt;/userID&gt;
  &lt;/ns2:createUser&gt;
  &lt;/S:Body&gt;
  &lt;/S:Envelope&gt;
  </code></pre>
  
  <ul>
  <li><strong>WCF web service</strong></li>
  </ul>
  
  <p>I have one server certificate (p7b format from a trusted CA) that I installed where my WCF web service workstation (dev) is by using the mmc Certificate Snap-in (at the moment cert is in the Trusted Publishers). I don't think I need another cert on the Java server as the response should be in clear (neither signed or encrypted). I am still a bit confused on this certificate -and certificates in general- as it seems to hold only a public key.</p>
  
  <p>Here is the app.config of my test project:<br>
    </p>
  
  <pre><code>&lt;client&gt;
    &lt;endpoint address="http://entrust-user-certification-uat.fm.rbsgrp.net/rbs/WebAS"
      behaviorConfiguration="endpointCredentialsBehavior" binding="wsHttpBinding"
      bindingConfiguration="WebAsServicePortTypeBinding" contract="IWebAsServicePortType"
      name="WebAsServicePortType"&gt;
      &lt;!--&lt;identity&gt;
        &lt;dns value="entrust-user-certification-uat.fm.rbsgrp.net" /&gt;
      &lt;/identity&gt;--&gt;
    &lt;/endpoint&gt;
  &lt;/client&gt;
  &lt;bindings&gt;
    &lt;wsHttpBinding&gt;
      &lt;binding name="WebAsServicePortTypeBinding" closeTimeout="00:01:00"
        openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
        bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
        maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text"
        textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false"&gt;
        &lt;readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
          maxBytesPerRead="4096" maxNameTableCharCount="16384" /&gt;
        &lt;security mode="Message"&gt;
          &lt;message clientCredentialType="Certificate" negotiateServiceCredential="false"
            establishSecurityContext="false" /&gt;
        &lt;/security&gt;
      &lt;/binding&gt;
    &lt;/wsHttpBinding&gt;
  &lt;/bindings&gt;
  
  &lt;behaviors&gt;
    &lt;endpointBehaviors&gt;
      &lt;behavior name="endpointCredentialsBehavior"&gt;
        &lt;clientCredentials&gt;
          &lt;clientCertificate findValue="entrust-user-certification-uat.fm.rbsgrp.net"
             storeLocation="LocalMachine" storeName="TrustedPublisher"
            x509FindType="FindBySubjectName"&gt;&lt;/clientCertificate&gt;
          &lt;serviceCertificate&gt;
            &lt;!--   
            Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate 
            is in the user's Trusted People store, then it will be trusted without performing a
            validation of the certificate's issuer chain. This setting is used here for convenience so that the 
            sample can be run without having to have certificates issued by a certificate authority (CA).
            This setting is less secure than the default, ChainTrust. The security implications of this 
            setting should be carefully considered before using PeerOrChainTrust in production code. 
            --&gt;
            &lt;authentication certificateValidationMode="None" revocationMode="NoCheck" trustedStoreLocation="LocalMachine"/&gt;
          &lt;/serviceCertificate&gt;
        &lt;/clientCredentials&gt;
      &lt;/behavior&gt;
    &lt;/endpointBehaviors&gt;
  &lt;/behaviors&gt;
  </code></pre>
  
  <p></p>
  
  <p>When I ran a simple test:<BR>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WebAS entrustService = new WebAS();<BR>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ActivationCodes certCodes = entrustService.createUser("testNomad");<BR>
  I've got the error:<BR>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;failed: System.Web.Services.Protocols.SoapException:
  javax.xml.soap.SOAPException: No Signature element found in soap message</p>
  
  <p>How could I force the signing process for each message? I was thinking I could do it through WCF configuration quite easily. Any help would be greatly appreciated !</p>