none
WCF The EncryptedKey clause was not wrapped with the required encryption token 'System.IdentityModel.Tokens.X509SecurityToken' RRS feed

  • Question

  • I need help with establishing a connection with a web service on which I don't have control. I'm using VS2012, C# and .NET framework 4.0.

    This is the communication setup:

    I have 2 certificates, buyed from local CA. One is server (let's call it certA) and another is client(application, certB). The same setup is on server(service) side. They have also one server certificate (certC) and one client certificate (certD).

    The communication should go like this: 1. I sign SOAP request with my CLIENT cert (private key, certB),

    1. I encyrpt SOAP with SERVICE (server) public key cert (certC),
    2. They process the message and send me a response,
    3. Response is digitaly signed with their client private key cert (certD),
    4. Response is encrypted with my server public key cert (certA),
    5. I have to decrypt the message (I guess WCF takes care of that) and here the exception rises.

    Since WCF does not have default definition for more than 2 certs, I googled and found this:

    http://blogesh.wordpress.com/2009/10/08/separate-certificates-for-transport-and-message-security-in-wcf/

    This tutorial is great, I did everything what is said there (except their cert D, I was instructed that I don't need to verify the signature, just decrypt the response with my certA private key.

    But, as I stated in the title, I get this exception: The EncryptedKey clause was not wrapped with the required encryption token 'System.IdentityModel.Tokens.X509SecurityToken'.

    I enabled tracing and message logging. I can see the response from the service, then I created another program in which I decrypted manualy the response and the response is as expected. But I can't (don't know how) to get the response before exception rises. Also, I extended class SimpleEndpointBehavior : IEndpointBehavior in which I can intercept the request but not the response, it breaks before.

    My code:

    CustomBinding cust = new CustomBinding();
            EndpointAddress ea = new EndpointAddress(someUri);
            ServiceClient client = new ServiceClient(cust, ea);

            var securityBindingElement = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);


            securityBindingElement.RequireSignatureConfirmation = false;
            securityBindingElement.EnableUnsecuredResponse = true;

            securityBindingElement.InitiatorTokenParameters = new X509SecurityTokenParameters(X509KeyIdentifierClauseType.SubjectKeyIdentifier, SecurityTokenInclusionMode.AlwaysToRecipient);
            securityBindingElement.RecipientTokenParameters = new X509SecurityTokenParameters(X509KeyIdentifierClauseType.SubjectKeyIdentifier, SecurityTokenInclusionMode.AlwaysToInitiator);

            securityBindingElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
            securityBindingElement.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
            securityBindingElement.IncludeTimestamp = false;
            securityBindingElement.DefaultAlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic128Rsa15;
            securityBindingElement.SetKeyDerivation(true);
            securityBindingElement.AllowSerializedSigningTokenOnReply = true;

            var textMessageEncoding = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);


            cust.Elements.Clear();


            cust.Elements.Add(securityBindingElement);

            cust.Elements.Add(textMessageEncoding);


            client.Endpoint.Behaviors.Add(new SimpleEndpointBehavior());

            var httpsTransport = new HttpsTransportBindingElement();
            httpsTransport.RequireClientCertificate = true;
            httpsTransport.AuthenticationScheme = AuthenticationSchemes.Negotiate;
            httpsTransport.ManualAddressing = false;
            cust.Elements.Add(httpsTransport);


            MyCredentials clCr = new MyCredentials(client.ClientCredentials);


            X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

            store.Open(OpenFlags.ReadWrite);
            X509Certificate2 transportCertificate = store.Certificates.Find(X509FindType.FindBySubjectKeyIdentifier, "someKey", true)[0];
            X509Certificate2 serviceCertificate = store.Certificates.Find(X509FindType.FindBySubjectKeyIdentifier, "someKey", true)[0];
            X509Certificate2 clientCertificate = store.Certificates.Find(X509FindType.FindBySubjectKeyIdentifier, "someKey", true)[0];


            store.Close();

            clCr.TransportCertificate = transportCertificate;
            clCr.ServiceCertificate.DefaultCertificate = serviceCertificate;
            clCr.ClientCertificate.Certificate = clientCertificate;

            client.ChannelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
            client.ChannelFactory.Endpoint.Behaviors.Add(clCr);

    //then service method call...

    I set protectionlevel on service reference.cs on EncryptAndSign. I check base64 key reference in response, it is the same as it is for my cert subjectkeyidentifier.

    I realy don't know what else to try. The error is probably certificate related as is mentioned in couple question on web but I don't know how to solve it.

    Thanks and cheers!






    • Edited by harsinjo Thursday, June 26, 2014 12:43 PM
    Thursday, June 26, 2014 12:39 PM

All replies

  • I suggest you set up a WCF service with the same setting and verify it is working with the client, and then compare the structure of its response to the failing response.

    Assuming they are the same structure (otherwise need to change binding) one option is that the response uses an encryption certificate which is different than the one you used to sign with in the request.  Verify that the value inside the response  keyInfo is indeed the subjectKeyIdentifier of the certificate you used to sign with.

    <wsse: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">y1cWMPtJ5ta+ZXxOOHKhkAwG5zM=</wsse:KeyIdentifier>
    
     
    
     
    


    • Edited by dns jinung Friday, June 27, 2014 11:07 AM
    Friday, June 27, 2014 11:07 AM
  • Thnx for the advice.

    SKI is OK, I checked it. In the mean time I managed to overcome this problem with manually decryprting the response using message encoder. I intercepted the returning message and there I modified it. Will reply if I ever find the solution to my exception with my configuration.

    Cheers

    Monday, June 30, 2014 6:38 AM
  • In my case there were two issues:

    1. Missing SKI in the self-signed certificates 

    2. Web service not replying with Timestamp

    More info:

    https://stackoverflow.com/questions/46686785/wcf-the-encryptedkey-clause-was-not-wrapped-with-the-required-encryption-token

    Thursday, December 21, 2017 3:10 PM