Home How do I configure a WCF .NET Client for a Response with Dual Encryption?
Reply: 1

How do I configure a WCF .NET Client for a Response with Dual Encryption?

Ivan
1#
Ivan Published in 2018-01-12 14:27:20Z

Using .NET, I need to call a third party API which uses mutual authentication and dual encryption using mode Transport bindings. They have successfully received and decrypted my Request, processed it and sent a Response.

In the Header of the SOAP Response is a Security element. This contains an EncryptedKey and Signature element. The Body is separately encrypted.

The key to decrypt the body is contained in the above EncryptedKey element but the actual key within is also encrypted. In the same element is a X509Data element providing certificate details (IssuerName and SerialNumber) to decrypt that key, which can be used to decrypt the Body.

Received Encrpted Response

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <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">
      <wsu:Timestamp wsu:Id="TS-ba9edb63-214d-4d6b-8040-ed715a1326c7"></wsu:Timestamp>
      <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="EK-fede8959-6d80-4166-9e79-4a4229efee4f">
        <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"></xenc:EncryptionMethod>
        <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
          <wsse:SecurityTokenReference>
            <ds:X509Data>
              <ds:X509IssuerSerial>
                <ds:X509IssuerName>CN=Their Name,O=Their Organisation</ds:X509IssuerName>
                <ds:X509SerialNumber>1234567*************************987654</ds:X509SerialNumber>
              </ds:X509IssuerSerial>
            </ds:X509Data>
          </wsse:SecurityTokenReference>
        </ds:KeyInfo>
        <xenc:CipherData>
          <xenc:CipherValue>K+l28afn3i8e..Encrypted...Key....4gnOHW0kxK7aL6l7Q==</xenc:CipherValue>
        </xenc:CipherData>
        <xenc:ReferenceList></xenc:ReferenceList>
      </xenc:EncryptedKey>
      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-77d3082f-2668-4347-9582-83d1ba9f0f8d">
        <ds:SignedInfo>
          <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> </ds:CanonicalizationMethod>
          <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>
          <ds:Reference URI="#TS-ba9edb63-214d-4d6b-8040-ed715a1326c7">
            <ds:Transforms> </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
            <ds:DigestValue>yKJziO....SrJPNE=</ds:DigestValue>
          </ds:Reference>
          <ds:Reference URI="#_2d4d85db-41d7-446b-87f1-0a839b9b3e7f">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
            <ds:DigestValue>9PNS98w.....KMWU0=</ds:DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>EaqS4/iiXybpMe6r........RFM2NM6D3X/zpQ==</ds:SignatureValue>
        <ds:KeyInfo Id="KI-a6793d90-a124-4960-ae17-f07c43248f53">
          <wsse:SecurityTokenReference wsu:Id="STR-1d682670-9dde-40e1-ad14-e29c9c62c474">
            <ds:X509Data>
              <ds:X509IssuerSerial>
                <ds:X509IssuerName>CN=Their Name,O=Their Organisatio</ds:X509IssuerName>
                <ds:X509SerialNumber>7654321*************************456789</ds:X509SerialNumber>
              </ds:X509IssuerSerial>
            </ds:X509Data>
          </wsse:SecurityTokenReference>
        </ds:KeyInfo>
      </ds:Signature>
    </wsse:Security>
  </SOAP-ENV:Header>
  <soap:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="_2d4d85db-41d7-446b-87f1-0a839b9b3e7f">
    <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="ED-3900ed5b-952f-4d4a-976b-6a3e86967010" Type="http://www.w3.org/2001/04/xmlenc#Content">
      <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"></xenc:EncryptionMethod>
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" wsse11:TokenType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey">
          <wsse:Reference URI="#EK-fede8959-6d80-4166-9e79-4a4229efee4f"></wsse:Reference>
        </wsse:SecurityTokenReference>
      </ds:KeyInfo>
      <xenc:CipherData>
        <xenc:CipherValue>7KCEA0yCcd.....Encrypted....Body....O0AIbjdJ3gKQy8=</xenc:CipherValue>
      </xenc:CipherData>
    </xenc:EncryptedData>
  </soap:Body>
</soap:Envelope>

THE PROBLEM : How do I configure the .NET client to: read the x509SerialNumber to get the cert to decrypt EncryptedKey.CipherValue (encrypted...key) then use this to decrypt the body????

When I try and get the Response in code:

Try
     Dim response As TheirService.TheirMethodResponse = client.DoMethodAction(request)
 Catch ex As Exception
     Dim test As String = ex.Message
 End Try

I get the following Exception (taken from trace logs):

<Exception>
  <ExceptionType>System.ServiceModel.Security.MessageSecurityException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
  <Message>
    Cannot resolve KeyInfo for unwrapping key: KeyInfo 'SecurityKeyIdentifier
    (
    IsReadOnly = False,
    Count = 1,
    Clause[0] = X509IssuerSerialKeyIdentifierClause(Issuer = 'CN=Their Name,O=Their Organisation', Serial = '1234567*************************987654')
    )
    ', available tokens 'SecurityTokenResolver
    (
    TokenCount = 1,
    TokenEntry[0] = (AllowedReferenceStyle=External, Token=System.ServiceModel.Security.Tokens.WrappedKeySecurityToken, Parameters=System.ServiceModel.Security.Tokens.WrappedKeySecurityTokenParameters:
    InclusionMode: Once
    ReferenceStyle: Internal
    RequireDerivedKeys: True)
    )
    '.
  </Message>
  <StackTrace>
    at System.ServiceModel.Security.WSSecurityJan2004.WrappedKeyTokenEntry.CreateWrappedKeyToken(String id, String encryptionMethod, String carriedKeyName, SecurityKeyIdentifier unwrappingTokenIdentifier, Byte[] wrappedKey, SecurityTokenResolver tokenResolver)
    at System.ServiceModel.Security.WSSecurityJan2004.WrappedKeyTokenEntry.ReadTokenCore(XmlDictionaryReader reader, SecurityTokenResolver tokenResolver)
    at System.ServiceModel.Security.WSSecurityTokenSerializer.ReadTokenCore(XmlReader reader, SecurityTokenResolver tokenResolver)
    at System.IdentityModel.Selectors.SecurityTokenSerializer.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver)
    at System.ServiceModel.Security.WSSecurityOneDotZeroReceiveSecurityHeader.DecryptWrappedKey(XmlDictionaryReader reader)
    at System.ServiceModel.Security.ReceiveSecurityHeader.ReadEncryptedKey(XmlDictionaryReader reader, Boolean processReferenceListIfPresent)
    at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteFullPass(XmlDictionaryReader reader)
    at System.ServiceModel.Security.StrictModeSecurityHeaderElementInferenceEngine.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; message, SecurityToken requiredSigningToken, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
    at System.ServiceModel.Security.SymmetricSecurityProtocol.VerifyIncomingMessageCore(Message&amp; message, String actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
    at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message&amp; message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
    at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout)
    at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
    at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
    at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
    at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
    at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
    at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&amp; msgData, Int32 type)
    at SIA_Test_Project.SiaSetupCard.SetupCardService.setupCard2(setupCard2Request request)
    at SIA_Test_Project.SiaSetupCard.SetupCardServiceClient.SiaSetupCard_SetupCardService_setupCard2(setupCard2Request request)
    at SIA_Test_Project.Module1.Main()
    at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
    at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
    at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
    at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
    at System.Threading.ThreadHelper.ThreadStart()
  </StackTrace>
  <ExceptionString>
    System.ServiceModel.Security.MessageSecurityException: Cannot resolve KeyInfo for unwrapping key: KeyInfo 'SecurityKeyIdentifier
    (
    IsReadOnly = False,
    Count = 1,
    Clause[0] = X509IssuerSerialKeyIdentifierClause(Issuer = 'CN=Their Name,O=Their Organisation', Serial = '1234567*************************987654')
    )
    ', available tokens 'SecurityTokenResolver
    (
    TokenCount = 1,
    TokenEntry[0] = (AllowedReferenceStyle=External, Token=System.ServiceModel.Security.Tokens.WrappedKeySecurityToken, Parameters=System.ServiceModel.Security.Tokens.WrappedKeySecurityTokenParameters:
    InclusionMode: Once
    ReferenceStyle: Internal
    RequireDerivedKeys: True)
    )
    '.
  </ExceptionString>
</Exception>

How I'm setting up the Client:

Dim binding As New Channels.CustomBinding
 
        Dim securityBE As SymmetricSecurityBindingElement = SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10)
 
        securityBE.MessageProtectionOrder = Security.MessageProtectionOrder.SignBeforeEncrypt
        securityBE.RequireSignatureConfirmation = False  
        securityBE.EnableUnsecuredResponse = False 
        binding.Elements.Add(securityBE) 
 
        binding.Elements.Add(New TextMessageEncodingBindingElement(MessageVersion.Soap11, System.Text.Encoding.UTF8))
 
        Dim http As New HttpsTransportBindingElement()
        http.RequireClientCertificate = True  

        binding.Elements.Add(http)

         Dim endPoint As New EndpointAddress(New Uri("https://blar/blar/services/TheirMethodService"), EndpointIdentity.CreateDnsIdentity("Their Name"))
 
 
       Dim client As New TheirService.TheirServiceServiceClient(binding, endPoint)
 
       Dim credentials As New ClientCredentials
       'Their cert where we have the public key only
       credentials.ServiceEncryptingCert = GetCert("c40ca927................c94640cdb7")
       'our their company's mutual auth cert where we have the private key
       credentials.ClientEncryptingCert = GetCert("e3debd49................e9a6cd39c5")
       'our their company's digital signing cert where we have the private key
       credentials.ClientSigningCert = GetCert("40091641................d622761b")
 
       client.ChannelFactory.Endpoint.EndpointBehaviors.Remove(GetType(Description.ClientCredentials))
       client.ChannelFactory.Endpoint.EndpointBehaviors.Add(credentials)
 
       'only sign the message do not encrypt it
       client.Endpoint.Contract.ProtectionLevel = ProtectionLevel.EncryptAndSign
 
       System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls Or System.Net.SecurityProtocolType.Tls12 
 
       Dim request As New TheirService.TheirMethodRequest
       request.ProductRequestItem = New TheirService.ProductRequestItem
       'Construct Request

Try
    Dim response As TheirService.TheirMethodResponse = client.DoMethodAction(request)
Catch ex As Exception
    Dim test As String = ex.Message
End Try

When debugging, requirement.GetProperty in the following Function throws an Exception when querying the Response:

Public Overrides Function CreateSecurityTokenProvider(requirement As SecurityTokenRequirement) As SecurityTokenProvider
    Dim result As SecurityTokenProvider
    If requirement.TokenType = System.IdentityModel.Tokens.SecurityTokenTypes.X509Certificate Then
 
        Dim direction As MessageDirection
        Dim noDirection  As Boolean = False
        Try
            direction = requirement.GetProperty(Of MessageDirection)(ServiceModelSecurityTokenRequirement.MessageDirectionProperty)
        Catch ex As Exception
            noDirection  = True
        End Try
 
        'this may be the client cert
        If noDirection Then
            result = New X509SecurityTokenProvider(Me.credentials.ClientEncryptingCert) 
        Else  
            If direction = MessageDirection.Output Then
                If requirement.KeyUsage = IdentityModel.Tokens.SecurityKeyUsage.Signature Then
                    result = New X509SecurityTokenProvider(Me.credentials.ClientSigningCert)
                Else
                    result = New X509SecurityTokenProvider(Me.credentials.ServiceEncryptingCert)
                End If
            Else
                If requirement.KeyUsage = IdentityModel.Tokens.SecurityKeyUsage.Signature Then
                    result = New X509SecurityTokenProvider(Me.credentials.ServiceEncryptingCert)
                Else
                    result = New X509SecurityTokenProvider(Me.credentials.ClientSigningCert)
                End If
            End If
        End If
    Else
        result = MyBase.CreateSecurityTokenProvider(requirement)
    End If 
    Return result
End Function

This is incredibly frustrating. Any help will be much appreciated. Thanks in advance.

Ivan
2#
Ivan Reply to 2018-01-17 17:50:34Z

Found the resolution - I was very close: Use the AsymmetricSecurityBindingElement and CreateMutualCertificateDuplexBindingElement objects.

Under How I'm setting up the Client:

I was using this which caused the Exception...

Dim securityBE As SymmetricSecurityBindingElement = SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10)

Replace with this line and all will work:

Dim securityBE As AsymmetricSecurityBindingElement = SecurityBindingElement.CreateMutualCertificateDuplexBindingElement(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10)

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.299566 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO