2017-10-11 47 views
7

Tôi đang cố gắng để sử dụng WCF client để kết nối với các dịch vụ web dựa trên JavaWCF: Mệnh đề EncryptedKey không được bao bọc bởi các thẻ mã hóa cần thiết 'System.IdentityModel.Tokens.X509SecurityToken'

Certificates tôi đã được cung cấp (tự ký) hoạt động hoàn hảo trong SOAPUI.

Đây là thiết lập của tôi:

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

Tuy nhiên, tôi đang gặp sự cố khi sử dụng ứng dụng khách WCF.

My app.config

<bindings> 
     <customBinding> 
     <binding name="Example_TestBinding">    
      <security defaultAlgorithmSuite="TripleDesRsa15" 
        authenticationMode="MutualCertificate" 
        requireDerivedKeys="false" 
        includeTimestamp="false" 
        messageProtectionOrder="SignBeforeEncrypt" 
        messageSecurityVersion="WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10" 
        requireSignatureConfirmation="false">     
      <localClientSettings detectReplays="true"/> 
      <localServiceSettings detectReplays="true"/>     
      </security>    
      <textMessageEncoding messageVersion="Soap11"/>    
      <httpsTransport authenticationScheme="Basic" manualAddressing="false" maxReceivedMessageSize="524288000" transferMode="Buffered"/>    
     </binding> 
     </customBinding> 
    </bindings> 
    <client> 
    <endpoint 
     address="https://blabla.hana.ondemand.com/Example_Test" 
     binding="customBinding" 
     bindingConfiguration="Example_TestBinding" 
     contract="WebServiceTest.Example_Test" 
     name="Example_Test" 
    /> 
    </client> 

Sử dụng Keystore Explorer tôi xuất khẩu cả hai giấy chứng nhận từ JKS như:

  • public_test_hci_cert.cer
  • test_soap_ui.p12

Dịch vụ web c tất cả:

  var client = new Example_TestClient(); 
      client.ClientCredentials.UserName.UserName = "user"; 
      client.ClientCredentials.UserName.Password = "pass"; 

      X509Certificate2 certClient = new X509Certificate2(certClientPath, certClientPassword); 
      client.ClientCredentials.ClientCertificate.Certificate = certClient; 

      X509Certificate2 certService= new X509Certificate2(certServicePath); 
      client.ClientCredentials.ServiceCertificate.DefaultCertificate = certService; 

      var response = client.Example_Test(requestObj); 

Yêu cầu đến một cách hoàn hảo tại máy chủ nhưng có vẻ như WCF không hiểu được những phản ứng kể từ khi tôi có được ngoại lệ này:

"The EncryptedKey clause was not wrapped with the required 
encryption token 'System.IdentityModel.Tokens.X509SecurityToken'." 
    at System.ServiceModel.Security.WSSecurityJan2004.WrappedKeyTokenEntry.CreateWrappedKeyToken(String id, String encryptionMethod, String carriedKeyName, SecurityKeyIdentifier unwrappingTokenIdentifier, Byte[] wrappedKey, SecurityTokenResolver tokenResolver)\r\n ... 

Dịch vụ vết cho:

The security protocol cannot verify the incoming message 

UPDATE1: đơn giản hóa tác vụ bằng cách sử dụng cùng một chứng chỉ để ký và mã hóa. Tin nhắn tương tự.

UPDATE2: Tôi đã viết CustomTextMessageEncoder nơi tôi tự giải mã nội dung thư và nó hoạt động. Tuy nhiên trả lại nó trong ReadMessage vẫn còn ném lỗi.

public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType) 
    { 
     var msgContents = new byte[buffer.Count]; 
     Array.Copy(buffer.Array, buffer.Offset, msgContents, 0, msgContents.Length); 
     bufferManager.ReturnBuffer(buffer.Array); 
     var message = Encoding.UTF8.GetString(msgContents); 

     //return ReadMessage(Decryptor.DecryptBody(message), int.MaxValue); 
     var stream = new MemoryStream(Encoding.UTF8.GetBytes(message)); 
     return ReadMessage(stream, int.MaxValue); 
    } 

    public static MemoryStream DecryptBody(string xmlResponse) 
    { 
     X509Certificate2 cert = new X509Certificate2(clientCertPath, certPass); 
     SymmetricAlgorithm algorithm = new TripleDESCryptoServiceProvider(); 

     XmlDocument xmlDoc = new XmlDocument(); 
     xmlDoc.PreserveWhitespace = true; 
     xmlDoc.LoadXml(xmlResponse); 

     XmlElement encryptedKeyElement = xmlDoc.GetElementsByTagName("EncryptedKey", XmlEncryptionStrings.Namespace)[0] as XmlElement; 
     XmlElement keyCipherValueElement = encryptedKeyElement.GetElementsByTagName("CipherValue", XmlEncryptionStrings.Namespace)[0] as XmlElement; 
     XmlElement encryptedElement = xmlDoc.GetElementsByTagName("EncryptedData", XmlEncryptionStrings.Namespace)[0] as XmlElement; 

     var key = Convert.FromBase64String(keyCipherValueElement.InnerText); 

     EncryptedData edElement = new EncryptedData(); 
     edElement.LoadXml(encryptedElement); 
     EncryptedXml exml = new EncryptedXml(); 

     algorithm.Key = (cert.PrivateKey as RSACryptoServiceProvider).Decrypt(key, false); 

     byte[] rgbOutput = exml.DecryptData(edElement, algorithm); 
     exml.ReplaceData(encryptedElement, rgbOutput); 

     //var body = Encoding.UTF8.GetString(rgbOutput); 

     MemoryStream ms = new MemoryStream(); 
     xmlDoc.Save(ms); 
     return ms; 
    } 

Trả lời

7

Tôi đã để lại vấn đề này cho lần chạy nước rút cuối cùng trong dự án của tôi và cuối cùng đã quay lại.
Đó là sự cố chứng chỉ. Các chứng chỉ tự ký mà tôi đã được cung cấp bởi dịch vụ web dựa trên Java đã được tạo bằng KeyStore Explorer.Cả hai giấy chứng nhận bị mất tích một phần quan trọng:

Subject Key Identifier 

enter image description here

Khi tái sinh WCF đã có thể giải mã nó mà không sử dụng bộ mã hóa.

Ngoài ra tôi đã phải:

  1. Cài đặt giấy chứng nhận dịch vụ trong Trusted Root CA (user)
  2. Set Web Services để trả lời với Timestamp

Tôi đã gỡ bỏ tất cả các cấu hình từ mã (ngoại trừ tên người dùng và mật khẩu của khách hàng) và được đặt trong app.config. Đây là cấu hình hoàn chỉnh:

<system.serviceModel> 
     <bindings> 
      <customBinding> 
      <binding name="Example_TestBinding">    
       <security       
         defaultAlgorithmSuite="TripleDesRsa15" 
         authenticationMode="MutualCertificate" 
         requireDerivedKeys="false" 
         includeTimestamp="true" 
         messageProtectionOrder="SignBeforeEncrypt" 
         messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10" 
         requireSignatureConfirmation="false" 
         allowSerializedSigningTokenOnReply="true" 
         > 
       </security>    
       <textMessageEncoding messageVersion="Soap11"/> 
       <httpsTransport authenticationScheme="Basic" 
           manualAddressing="false" 
           maxReceivedMessageSize="524288000" 
           transferMode="Buffered"/>       
      </binding> 
      </customBinding> 

     </bindings> 
     <client> 
     <endpoint address="https://klaatuveratanecto.com/cxf/Example_TestBinding" 
        behaviorConfiguration="endpointCredentialBehavior" 
        binding="customBinding" 
        bindingConfiguration="Example_TestBinding" 
        contract="WebServiceTest.Example_Test" 
        name="Example_Test"> 
      <identity> 
      <dns value="test.service.klaatuveratanecto.com"/> 
      </identity> 
     </endpoint> 
     </client> 
    <behaviors> 
     <endpointBehaviors> 
     <behavior name="endpointCredentialBehavior"> 
      <clientCredentials> 
      <serviceCertificate> 
       <defaultCertificate findValue="test.service.klaatuveratanecto.com" 
           storeLocation="CurrentUser" 
           storeName="Root" 
           x509FindType="FindBySubjectName" /> 
      </serviceCertificate> 
      <clientCertificate findValue="test.client.klaatuveratanecto.com" 
           storeLocation="CurrentUser" 
           storeName="My" 
           x509FindType="FindBySubjectName" /> 
      </clientCredentials> 
     </behavior> 
     </endpointBehaviors> 
    </behaviors> 
    </system.serviceModel> 

Làm cách nào để đến đó. Vâng nhìn vào stack trace:

Server stack trace: 
    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& message, SecurityToken requiredSigningToken, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates) 
    at System.ServiceModel.Security.AsymmetricSecurityProtocol.VerifyIncomingMessageCore(Message& message, String actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates) 
    at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message& 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) 

tôi sửa lỗi CreateWrappedKeyToken phương pháp với sự giúp đỡ của JetBrains dotPeek và thấy rằng nó cố gắng để đọc SKI liệu từ giấy chứng nhận và nó không tìm thấy nó.

+0

Có: chứng chỉ sai. Bạn muốn biết điều gì khác? –

Các vấn đề liên quan