title: WCF - How to debug "The signature verification failed" messages
body: <p>I've created a WCF client that is calling a Spring Web Services 2.1.0 + Apache WSS4J 1.6.7 (WS-Sec 1.1) server and returning a response.</p>
  
  <p>WCF is complaining that the <strong>"Message security verification failed"</strong> with an <code>InnerException</code> of <strong>"The signature verification failed"</strong></p>
  
  <p>Problem is, I've no other way of debugging this as it's on a production server. I've got WCF logging the SOAP going to and from and the exceptions being thrown, and the guys who run the server say they can process responses fine on their end (i.e. they dont get a problem verifying the signature )</p>
  
  <p>Any idea's on how to debug this further? Would I be able to create a console app to validate the SOAP?</p>
  
  <p>I've been able to send requests through to their server OK and am getting responses so I've been trying to validate this via a console app so that I can see where the response is going wrong, but cant get the Console app to verify the XML either - CheckSignature is always returning false when I run the request and response through.</p>
  
  <p>Note: I've tried setting <code>xmlDoc.PreserveWhitespace</code> as <code>true</code> and <code>false</code></p>
  
  <p>Any help at all is appreciated</p>
  
  <p>Just to note also - the code below is just something I put together to test the signature. The actual service binding / service client is a seperate app. The binding for this is below:</p>
  
  <pre><code>&lt;customBinding&gt;
          &lt;binding name="MY_BINDING"&gt;
            &lt;transactionFlow/&gt;
            &lt;security defaultAlgorithmSuite="Basic256Rsa15" authenticationMode="MutualCertificate"
                      messageSecurityVersion="WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10"
                      requireDerivedKeys="false" messageProtectionOrder="SignBeforeEncrypt" 
                      allowSerializedSigningTokenOnReply="true" securityHeaderLayout="Lax" &gt;
              &lt;secureConversationBootstrap authenticationMode="CertificateOverTransport"
                                           messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
                                           requireDerivedKeys="false" /&gt;
            &lt;/security&gt;
            &lt;textMessageEncoding messageVersion="Soap11WSAddressing10"/&gt;
            &lt;httpsTransport requireClientCertificate="true"/&gt;
          &lt;/binding&gt;
        &lt;/customBinding&gt;
  </code></pre>
  
  <p>Binding from code - Config XML binding is retrieved and modified</p>
  
  <pre><code>public static CustomBinding GetServiceBinding()
          {            
              //Get custom binding reference from app.config
              CustomBinding binding = new CustomBinding(SettingsLookup.WcfCustomBindingName);
              binding.ReceiveTimeout = new TimeSpan(0, 0, 15, 0);
              binding.SendTimeout = new TimeSpan(0, 0, 15, 0);
  
              // Get the x509ProtectionParams from the security element
              X509SecurityTokenParameters tokenParameters = new X509SecurityTokenParameters();
              tokenParameters.X509ReferenceStyle = X509KeyIdentifierClauseType.IssuerSerial;
              tokenParameters.RequireDerivedKeys = false;
              tokenParameters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
  
              // Reference the asymettric security element            
              AsymmetricSecurityBindingElement securityBindingElement = binding.Elements.Find&lt;AsymmetricSecurityBindingElement&gt;();
              // Set the X509SecurityTokenParameters to point to the one's just configured. This is for symetric encryption, for asymetric this line needs to change
              //securityBindingElement.ProtectionTokenParameters = tokenParameters;
              securityBindingElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
              securityBindingElement.InitiatorTokenParameters = tokenParameters;
              securityBindingElement.LocalClientSettings.DetectReplays = false;
              securityBindingElement.RequireSignatureConfirmation = true;
              //Set timestamp to false as it's not in the VHI request
              securityBindingElement.IncludeTimestamp = true;
              securityBindingElement.LocalClientSettings.TimestampValidityDuration = new TimeSpan(12,0,0);
  
  
  
  
              return binding;
          }
  </code></pre>
  
  <p>This app is just for checking the signature i was feeding in the SOAP envelope directly in a hope to debug the signature and see what was failing</p>
  
  <pre><code>// TEST PROGRAM JUST FOR CHECKING SIGNATURE, CONSOLE APP SEPERATE FROM MAIN APP
  class Program
          {
              static void Main(string[] args)
              {
                  XmlDocument xmlDoc = new XmlDocument();
                  xmlDoc.PreserveWhitespace = true;
                  xmlDoc.LoadXml(Resource1.request);
  
                  X509Certificate2 cert = new X509Certificate2(@"D:\TEMP\certs\pub_and_private_key.pfx", "password");
  
                  bool result = ValidateSoapBodySignature(xmlDoc, cert);
  
              }
  
          public static bool ValidateSoapBodySignature(XmlDocument doc, X509Certificate2 cert)
          {
              // *** Load the doc this time
              SignedXmlWithId sdoc = new SignedXmlWithId(doc);
  
              // *** Find the signature and load it into SignedXml
              XmlNodeList nodeList = doc.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#");
              sdoc.LoadXml((XmlElement)nodeList[0]);
  
              // *** Now read the actual signature and validate
              bool result = sdoc.CheckSignature(cert, true);
  
              return result;
          }
  
  
      }
  
      public class SignedXmlWithId : SignedXml
      {
          public SignedXmlWithId(XmlDocument xml)
              : base(xml)
          {
          }
  
          public SignedXmlWithId(XmlElement xmlElement)
              : base(xmlElement)
          {
          }
  
          public override XmlElement GetIdElement(XmlDocument doc, string id)
          {
              // check to see if it's a standard ID reference
              XmlElement idElem = base.GetIdElement(doc, id);
  
              if (idElem == null)
              {
                  XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
                  nsManager.AddNamespace("u", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
  
                  idElem = doc.SelectSingleNode("//*[@u:Id=\"" + id + "\"]", nsManager) as XmlElement;
              }
  
              return idElem;
          }
      }
  </code></pre>
  
  <p>Exceptions</p>
  
  <pre><code>System.ServiceModel.Security.MessageSecurityException: Message security verification failed. 
  
  ---&amp;amp;gt; System.Security.Cryptography.CryptographicException: The signature verification failed.
     at System.IdentityModel.SignedXml.VerifySignature(HashAlgorithm hash, AsymmetricSignatureDeformatter deformatter, String signatureMethod)
     at System.IdentityModel.SignedXml.StartSignatureVerification(SecurityKey verificationKey)
     at System.ServiceModel.Security.WSSecurityOneDotZeroReceiveSecurityHeader.VerifySignature(SignedXml signedXml, Boolean isPrimarySignature, SecurityHeaderTokenResolver resolver, Object signatureTarget, String id)
     at System.ServiceModel.Security.ReceiveSecurityHeader.ProcessPrimarySignature(SignedXml signedXml, Boolean isFromDecryptedSource)
     at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteSignatureEncryptionProcessingPass()
     at System.ServiceModel.Security.LaxModeSecurityHeaderElementInferenceEngine.ExecuteProcessingPasses(ReceiveSecurityHeader securityHeader, XmlDictionaryReader reader)
     at System.ServiceModel.Security.ReceiveSecurityHeader.Process(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy)
     at System.ServiceModel.Security.MessageSecurityProtocol.ProcessSecurityHeader(ReceiveSecurityHeader securityHeader, Message&amp;amp;amp; message, SecurityToken requiredSigningToken, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
     at System.ServiceModel.Security.AsymmetricSecurityProtocol.VerifyIncomingMessageCore(Message&amp;amp;amp; message, String actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
     at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message&amp;amp;amp; message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
     --- End of inner exception stack trace ---&lt;/ExceptionString&gt;&lt;InnerException&gt;&lt;ExceptionType&gt;System.Security.Cryptography.CryptographicException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&lt;/ExceptionType&gt;&lt;Message&gt;The signature verification failed.&lt;/Message&gt;&lt;StackTrace&gt;   at System.IdentityModel.SignedXml.VerifySignature(HashAlgorithm hash, AsymmetricSignatureDeformatter deformatter, String signatureMethod)
     at System.IdentityModel.SignedXml.StartSignatureVerification(SecurityKey verificationKey)
     at System.ServiceModel.Security.WSSecurityOneDotZeroReceiveSecurityHeader.VerifySignature(SignedXml signedXml, Boolean isPrimarySignature, SecurityHeaderTokenResolver resolver, Object signatureTarget, String id)
     at System.ServiceModel.Security.ReceiveSecurityHeader.ProcessPrimarySignature(SignedXml signedXml, Boolean isFromDecryptedSource)
     at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteSignatureEncryptionProcessingPass()
     at System.ServiceModel.Security.LaxModeSecurityHeaderElementInferenceEngine.ExecuteProcessingPasses(ReceiveSecurityHeader securityHeader, XmlDictionaryReader reader)
     at System.ServiceModel.Security.ReceiveSecurityHeader.Process(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy)
     at System.ServiceModel.Security.MessageSecurityProtocol.ProcessSecurityHeader(ReceiveSecurityHeader securityHeader, Message&amp;amp;amp; message, SecurityToken requiredSigningToken, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
     at System.ServiceModel.Security.AsymmetricSecurityProtocol.VerifyIncomingMessageCore(Message&amp;amp;amp; message, String actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
     at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message&amp;amp;amp; message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)&lt;/StackTrace&gt;&lt;ExceptionString&gt;System.Security.Cryptography.CryptographicException: The signature verification failed.
     at System.IdentityModel.SignedXml.VerifySignature(HashAlgorithm hash, AsymmetricSignatureDeformatter deformatter, String signatureMethod)
     at System.IdentityModel.SignedXml.StartSignatureVerification(SecurityKey verificationKey)
     at System.ServiceModel.Security.WSSecurityOneDotZeroReceiveSecurityHeader.VerifySignature(SignedXml signedXml, Boolean isPrimarySignature, SecurityHeaderTokenResolver resolver, Object signatureTarget, String id)
     at System.ServiceModel.Security.ReceiveSecurityHeader.ProcessPrimarySignature(SignedXml signedXml, Boolean isFromDecryptedSource)
     at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteSignatureEncryptionProcessingPass()
     at System.ServiceModel.Security.LaxModeSecurityHeaderElementInferenceEngine.ExecuteProcessingPasses(ReceiveSecurityHeader securityHeader, XmlDictionaryReader reader)
     at System.ServiceModel.Security.ReceiveSecurityHeader.Process(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy)
     at System.ServiceModel.Security.MessageSecurityProtocol.ProcessSecurityHeader(ReceiveSecurityHeader securityHeader, Message&amp;amp;amp; message, SecurityToken requiredSigningToken, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
     at System.ServiceModel.Security.AsymmetricSecurityProtocol.VerifyIncomingMessageCore(Message&amp;amp;amp; message, String actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
     at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message&amp;amp;amp; message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
  </code></pre>
  
  <p><strong>SOAP</strong></p>
  
  <pre><code>&lt;s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"&gt;
    &lt;s:Header&gt;
      &lt;a:Action s:mustUnderstand="1" u:Id="_3"&gt;http://www.xxx.com/xxx/v1/submitRequest&lt;/a:Action&gt;
      &lt;a:MessageID u:Id="_4"&gt;urn:uuid:d9d6ae53-4e63-4e2d-86bf-954684d26fd8&lt;/a:MessageID&gt;
      &lt;a:To s:mustUnderstand="1" u:Id="_5"&gt;https://urigoeshere.com/&lt;/a:To&gt;
      &lt;a:From u:Id="_6"&gt;
        &lt;a:Address&gt;http://ourcompany.com/&lt;/a:Address&gt;
      &lt;/a:From&gt;
      &lt;o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"&gt;
        &lt;u:Timestamp u:Id="uuid-01f867d2-f5c2-4587-a83d-0878a2342bd9-1"&gt;
          &lt;u:Created&gt;2013-01-21T17:12:31.213Z&lt;/u:Created&gt;
          &lt;u:Expires&gt;2013-01-22T05:12:31.213Z&lt;/u:Expires&gt;
        &lt;/u:Timestamp&gt;
        &lt;o:BinarySecurityToken u:Id="uuid-81deba4d-1a68-4f53-bb59-3c618914d683-2" 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"&gt;OMITTED&lt;/o:BinarySecurityToken&gt;
        &lt;e:EncryptedKey Id="_0" xmlns:e="http://www.w3.org/2001/04/xmlenc#"&gt;
          &lt;e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/&gt;
          &lt;KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"&gt;
            &lt;o:SecurityTokenReference&gt;
              &lt;o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"&gt;oNEIRj8uPIkIP4+BfAo/CmYDwzk=&lt;/o:KeyIdentifier&gt;
            &lt;/o:SecurityTokenReference&gt;
          &lt;/KeyInfo&gt;
          &lt;e:CipherData&gt;
            &lt;e:CipherValue&gt;OMITTED&lt;/e:CipherValue&gt;
          &lt;/e:CipherData&gt;
          &lt;e:ReferenceList&gt;
            &lt;e:DataReference URI="#_2"/&gt;
          &lt;/e:ReferenceList&gt;
        &lt;/e:EncryptedKey&gt;
        &lt;Signature xmlns="http://www.w3.org/2000/09/xmldsig#"&gt;
          &lt;SignedInfo&gt;
            &lt;CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/&gt;
            &lt;SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/&gt;
            &lt;Reference URI="#_1"&gt;
              &lt;Transforms&gt;
                &lt;Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/&gt;
              &lt;/Transforms&gt;
              &lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/&gt;
              &lt;DigestValue&gt;17c5Wuh9MNl4i/ytgwm9flLkAnY=&lt;/DigestValue&gt;
            &lt;/Reference&gt;
            &lt;Reference URI="#_3"&gt;
              &lt;Transforms&gt;
                &lt;Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/&gt;
              &lt;/Transforms&gt;
              &lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/&gt;
              &lt;DigestValue&gt;2YgeR5vFw0ICk8r+wiaVYknO4E8=&lt;/DigestValue&gt;
            &lt;/Reference&gt;
            &lt;Reference URI="#_4"&gt;
              &lt;Transforms&gt;
                &lt;Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/&gt;
              &lt;/Transforms&gt;
              &lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/&gt;
              &lt;DigestValue&gt;NepAQ8htbWWBy0ghljlVfMw5lr0=&lt;/DigestValue&gt;
            &lt;/Reference&gt;
            &lt;Reference URI="#_5"&gt;
              &lt;Transforms&gt;
                &lt;Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/&gt;
              &lt;/Transforms&gt;
              &lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/&gt;
              &lt;DigestValue&gt;ynr1icJszUi4OG5vt0usO0419As=&lt;/DigestValue&gt;
            &lt;/Reference&gt;
            &lt;Reference URI="#_6"&gt;
              &lt;Transforms&gt;
                &lt;Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/&gt;
              &lt;/Transforms&gt;
              &lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/&gt;
              &lt;DigestValue&gt;y8jXxE1bLmeg6vJi9iqKczNvEDo=&lt;/DigestValue&gt;
            &lt;/Reference&gt;
            &lt;Reference URI="#uuid-01f867d2-f5c2-4587-a83d-0878a2342bd9-1"&gt;
              &lt;Transforms&gt;
                &lt;Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/&gt;
              &lt;/Transforms&gt;
              &lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/&gt;
              &lt;DigestValue&gt;qlv+YHU/bxsWvEo/HYVZY9RfqQY=&lt;/DigestValue&gt;
            &lt;/Reference&gt;
          &lt;/SignedInfo&gt;
          &lt;SignatureValue&gt;O6MK3Etk/OIXkSTngGaN+W1JPTrbV2/K0ulnTS69o1/NvmDfpdlkb67TR+UNnCBwVEiV0ILZfQkl9zVhMMpB0lOeM3zzJ5f97dh1WLkGeQm7U2G+ZTN0QFA/O4HZ2yADhzRlPLp29hNdjGBdky99b0oeFyU2hq8qdpIWwKMCDkHlGyftKb4t51yZSc+6uJKYhv3uXSmFMJAYZ6tlTfYa5Cc0jLileNx6I9+tyg73oJZsTEyc+cDZZqdxEmXLrAyt0kz0fcpGWrNKCrKuQlaMsV/KkJYVHSohPpJYWUrrtGmOfiWWhQuwlCIUIxCwR8HBpspFOK8IHEuu+kBQgKrx3g==&lt;/SignatureValue&gt;
          &lt;KeyInfo&gt;
            &lt;o:SecurityTokenReference&gt;
              &lt;o:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" URI="#uuid-81deba4d-1a68-4f53-bb59-3c618914d683-2"/&gt;
            &lt;/o:SecurityTokenReference&gt;
          &lt;/KeyInfo&gt;
        &lt;/Signature&gt;
      &lt;/o:Security&gt;
    &lt;/s:Header&gt;
    &lt;s:Body u:Id="_1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
      &lt;e:EncryptedData Id="_2" Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:e="http://www.w3.org/2001/04/xmlenc#"&gt;
        &lt;e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/&gt;
        &lt;e:CipherData&gt;
          &lt;e:CipherValue&gt;OMITTED&lt;/e:CipherValue&gt;
        &lt;/e:CipherData&gt;
      &lt;/e:EncryptedData&gt;
    &lt;/s:Body&gt;
  &lt;/s:Envelope&gt;
  </code></pre>