2017-10-11 28 views
7

我试图使用WCF客户端连接到 WCF:该EncryptedKey条款不包裹所需的加密令牌“System.IdentityModel.Tokens.X509SecurityToken”

证书我已经提供了基于Java的Web服务

(自签名)在SOAPUI中完美工作。

这里是我的设置:

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

不过,我在使用WCF客户端时遇到问题。

的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> 

使用密钥库资源管理器中,我从JKS同时导出证书为:

  • public_test_hci_cert.cer
  • test_soap_ui.p12

Web服务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); 

请求完全到达服务器,但它似乎WCF不理解响应,因为我得到这个异常:

"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 ... 

服务跟踪,得出:

The security protocol cannot verify the incoming message 

UPDATE1:通过使用相同的证书进行签名和加密来简化任务。同样的信息。

UPDATE2:我写了CustomTextMessageEncoder,我手动解密邮件正文,它的工作原理。但是,在ReadMessage中返回它仍会引发错误。

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; 
    } 

回答

7

我离开了这个问题,在我的项目中进行了最后的冲刺,最后回到了它。
这是证书问题。基于Java的Web服务提供的自签名证书是使用KeyStore Explorer生成的。这两个证书中缺少的重要组成部分:

Subject Key Identifier 

enter image description here

一旦再生WCF能够解密,而无需使用编码器。

我也只好:

  1. 受信任的根CA安装服务证书(用户)
  2. 组Web服务与时间戳回复

我删除了所有的配置从代码(除了客户端用户名和密码)并放置在app.config中。这里是完整的配置:

<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> 

我是如何到达那里的。那么看着堆栈跟踪:

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) 

我调试CreateWrappedKeyTokenJetBrains公司dotPeek的帮助下,看到它试图从证书读取原始SKI,它不是找到它。

+0

它确实:证书是错误的。你还想知道什么? –

相关问题