none
Change canonicalization algorithm with WCF RRS feed

  • Question

  • I am trying to call a webservice using WCF with a certificate to sign the message.

    The server only supports the following canonicalization algorithm : 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments'

    By default, WCF uses 'http://www.w3.org/2001/10/xml-exc-c14n#'

    Since I couldn't configure it with the config file, I created a custom binding in which I set a custom SecurityAlgorithmSuite to force WCF to use the canonicalization algorithm expected by the service. Here is my custom binding :

    public class TestBinding : Binding
    {
        public override BindingElementCollection CreateBindingElements()
        {
            var sec = TransportSecurityBindingElement.CreateCertificateOverTransportBindingElement();
            sec.MessageSecurityVersion = MessageSecurityVersion
                .WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
            sec.EnableUnsecuredResponse = true;
            sec.DefaultAlgorithmSuite = new TestSecurityAlgorithmSuite();
    
            return new BindingElementCollection(new BindingElement[] {
                new TextMessageEncodingBindingElement() { MessageVersion = MessageVersion.Soap11WSAddressing10 },
                sec,
                new HttpsTransportBindingElement() { RequireClientCertificate = true }
            });
        }
    
        public override string Scheme
        {
            get { return new HttpsTransportBindingElement().Scheme; }
        }
    }

    And the algorithm suite :

    public class TestSecurityAlgorithmSuite : Basic256SecurityAlgorithmSuite
    {
        public override string DefaultCanonicalizationAlgorithm
        {
            get { return "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"; }
        }
    
        public override string ToString()
        {
            return "TestSecurityAlgorithmSuite";
        }
    }

    Unfortunately, I get the error :

    Canonicalization algorithm 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments' is not supported.
    
    Server stack trace: 
    à System.ServiceModel.Security.WSSecurityOneDotZeroSendSecurityHeader.StartPrimarySignatureCore(SecurityToken token, SecurityKeyIdentifier keyIdentifier, MessagePartSpecification signatureParts, Boolean generateTargettableSignature)
    à System.ServiceModel.Security.WSSecurityOneDotZeroSendSecurityHeader.CreateSupportingSignature(SecurityToken token, SecurityKeyIdentifier identifier)
    à System.ServiceModel.Security.SendSecurityHeader.SignWithSupportingToken(SecurityToken token, SecurityKeyIdentifierClause identifierClause)
    à System.ServiceModel.Security.SendSecurityHeader.SignWithSupportingTokens()
    à System.ServiceModel.Security.SendSecurityHeader.CompleteSecurityApplication()
    à System.ServiceModel.Security.SecurityAppliedMessage.OnWriteMessage(XmlDictionaryWriter writer)
    à System.ServiceModel.Channels.Message.WriteMessage(XmlDictionaryWriter writer)
    à System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(Message message, BufferManager bufferManager, Int32 initialOffset, Int32 maxSizeQuota)
    à System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
    à System.ServiceModel.Channels.MessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager)
    à System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message, Boolean shouldRecycleBuffer)
    à System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message)
    à System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout)
    à System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.SendRequest(Message message, TimeSpan timeout)
    à System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
    à System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
    à System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
    à System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
    à System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
    à System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)'

    Is there any way to make WCF work with the desired algorithm?

    Thursday, June 11, 2015 2:02 PM

Answers

All replies

  • Hi Arcodeon ,
       According to this case , your modified canonicalization algorithm string is fine. but  You need to get into the low level APIs such as MessageSignature.  Once you can get hold of a MessageSignature object, you can access the messageSignature.SignedInfo.CanonicalizationMethod property, and set it to what you desired.

    To get to the MessageSignature object,you can write your own policy class and security assertion,  before adding the message signature object to the security, change the url there.  The other way is to use the old WSE programming model, where you retrieve the SoapContext.Security object, and construct MessageSignature object, and modify the corresponding URL respectively.

    for more information, Click here to refer about Digitally Signing an XML Document and Verifying the Signature.
    Friday, June 12, 2015 9:40 AM
  • Hi,

    Thank you for your answer, but I don't get how a custom policy would help me in this case. After some researches on the web, I have no idea how I can get the MessageSignature object with WCF. If you have some sample available to put me in the right direction, I would gladly appreciate the help.

    I'll be taking a look at WSE though, and see what I can do.

    Thanks.

    Friday, June 12, 2015 5:01 PM
  • I have no idea how I can get the MessageSignature object with WCF. If you have some sample available to put me in the right direction,

           As per this case, I suggest you to refer the following similar thread which may guide you to resolve this case :

    http://stackoverflow.com/questions/13453921/how-to-make-wcf-client-sign-securitytokenreferencereference

    Monday, June 29, 2015 9:43 AM