我正在使用WCF使用第三方的Web服务。我有一个PFX证书文件,我通过ClientCredentials.ClientCertificate.SetCertificate
方法附加。我正在使用“消息安全版”WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10
。
一切正常。现在第三方证书即将到期,所以他们发布了新证书。但是,这次只是公钥的P7B文件。
当我尝试使用此证书时,我收到一条NotSupportedException
,上面写着“X.509证书中没有私钥。”
我的代码中没有任何部分提供私钥密码,因此我假设这意味着私钥未被使用。如果是这种情况,如何仅使用公钥来使用此Web服务?或者我误解了什么? (非常可能)
修改
好的,这是一些代码。我正在使用的服务客户端类由svcutil
生成,并已通过部分类进行修改以实现IDisposable
。这些是相关的片段:
private ServiceResponse CallService(ServiceParameters serviceParameters)
{
...
using (var client = new ThirdPartyServiceClient())
{
SetClientCredentials(client);
client.RemoteCall(serviceParameters);
}
...
}
private void SetClientCredentials(ThirdPartyServiceClient client)
{
if (client.ClientCredentials == null)
{
throw new InvalidOperationException("ClientCredentials was null and certificate could not be set");
}
client.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName,
_configuration.CertificateSubject);
}
这是我的WCF配置:
<system.serviceModel>
<bindings>
<customBinding>
<binding name="ThirdPartyServiceBinding">
<security includeTimestamp="true" enableUnsecuredResponse="true" authenticationMode="CertificateOverTransport" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10" />
<textMessageEncoding messageVersion="Soap11WSAddressing10" />
<httpsTransport requireClientCertificate="true" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="https://third-party.com/service" binding="customBinding" bindingConfiguration="ThirdPartyServiceBinding" contract="Namespace.To.ProxyClasses" name="ThirdPartyService" />
</client>
</system.serviceModel>
client.RemoteCall(serviceParameters);
调用抛出异常,堆栈跟踪为
Server stack trace: at System.IdentityModel.Tokens.X509AsymmetricSecurityKey.GetSignatureFormatter(String algorithm) at System.IdentityModel.SignedXml.ComputeSignature(SecurityKey signingKey) at System.ServiceModel.Security.WSSecurityOneDotZeroSendSecurityHeader.CompletePrimarySignatureCore(SendSecurityHeaderElement[] signatureConfirmations, SecurityToken[] signedEndorsingTokens, SecurityToken[] signedTokens, SendSecurityHeaderElement[] basicTokens, Boolean isPrimarySignature) at System.ServiceModel.Security.WSSecurityOneDotZeroSendSecurityHeader.CreateSupportingSignature(SecurityToken token, SecurityKeyIdentifier identifier) at System.ServiceModel.Security.SendSecurityHeader.SignWithSupportingToken(SecurityToken token, SecurityKeyIdentifierClause identifierClause) at System.ServiceModel.Security.SendSecurityHeader.SignWithSupportingTokens() at System.ServiceModel.Security.SendSecurityHeader.CompleteSecurityApplication() at System.ServiceModel.Security.SecurityAppliedMessage.OnWriteMessage(XmlDictionaryWriter writer) at System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(Message message, BufferManager bufferManager, Int32 initialOffset, Int32 maxSizeQuota) at System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset) at System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message, Boolean shouldRecycleBuffer) at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout) at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.SendRequest(Message message, TimeSpan timeout) at System.ServiceModel.Channels.RequestChannel.Request(Message message, 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) Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at Namespace.To.ProxyClasses.ThirdPartyService.RemoteCall(ServiceParameters request) [back up the normal call hierarchy of my code]
答案 0 :(得分:0)
使用邮件安全性,您可以使用私钥对文档进行签名,并使用其他方公钥加密文档。他们可以使用私钥对其进行解密,并且可以使用您的公钥验证您的签名。听起来他们更换了他们的密钥,因此他们为您提供了新的公钥。如果他们的公钥没有可公开验证的信任链,那么您需要将其公钥作为可信密钥安装在本地证书存储中。如果您不这样做并且它们不可公开验证,那么您将获得关于无法验证链信任的例外情况。如果你的钥匙即将到期,那么他们需要一把公钥来识别你,你需要他们不应该拥有的私人一半。