WCF:EncryptedKey子句未包含所需的加密令牌’System.IdentityModel.Tokens.X509SecurityToken’

我正在尝试使用WCF客户端连接到基于Java的Web服务

证书我已经提供(自签名)在SOAPUI中完美地工作。

这是我的设置:

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

但是,我在使用WCF客户端时遇到问题。

我的app.config

               

使用Keystore Explorer我从JKS导出两个证书:

  • public_test_hci_cert.cer
  • test_soap_ui.p12

网络服务电话:

  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不理解响应,因为我得到此exception:

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

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

 Subject Key Identifier 

在此处输入图像描述

一旦重新生成,WCF就能够在不使用编码器的情况下对其进行解密。

我还必须:

  1. 在受信任的根CA(用户)中安装服务证书
  2. 将Web服务设置为使用时间戳进行回复

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

                                 

我是怎么到那儿的 仔细看堆栈跟踪:

 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) 

我在JetBrains dotPeek的帮助下调试了CreateWrappedKeyToken方法,看到它试图从证书中读取原始SKI并且没有找到它。