开发者

.NET 4.0 client certificate validation error

开发者 https://www.devze.com 2023-04-01 06:11 出处:网络
I have the following code var factory = new ChannelFactory<INewsClient>(); factory.Credentials.ClientCertificate.Certificate = GetCertificate();

I have the following code

var factory = new ChannelFactory<INewsClient>();
factory.Credentials.ClientCertificate.Certificate = GetCertificate();
factory.Endpoint.Address = new EndpointAddress("https://blabla.com/myservice/");
var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
factory.Endpoint.Binding = binding;
var channel = factory.CreateChannel();
channel.GetNews();

It works in .NET 3.5, but not in .NET4.0. Bizzare huh? The Certificate I am using doesn't validate on the local mach开发者_运维百科ine (no chain). In 3.5, the client cert's validity is irrelevant to establishing SSL, but when migrating to 4.0, the certificate is validated before being used for SSL. (I can see errors in the CAPI2 Event logs). Resulting in an ugly SecurityNegotiationException...

Stack Trace:

System.ServiceModel.Security.SecurityNegotiationException: Could not establish secure   channel for SSL/TLS with authority 'pep.uat.dialectpayments.com'. ---> System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   --- End of inner exception stack trace ---

Server stack trace: 
   at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.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 ConsoleApplication2.Program.INewsClient.Get()
   at ConsoleApplication2.Program.Main(String[] args) in d:\dev\ConsoleApplication2\Program.cs:line 44

In our security architecture, certs are validated against an LDAP directory on the server, therefore no need for clients to know the full chain.

Question is, how do I disable this new behaviour?


Ok, I'll provide my own answer here...

In a nutshell: It seems you cannot use a non-persistent CSP with .NET 4 for X509. I.e. Your CSP must have a KeyContainerName for it to work.

My GetCertificate() method was doing the following: (i.e. Non-Persistent)

var certificate = new X509Certificate2(@"C:\public.cer");
var rsa = RSA.Create();
rsa.FromXmlString("<RSAKeyValue>......</RSAKeyValue>");
certificate.PrivateKey = rsa;
return certificate;

Changing it to this makes my sample work in 3.5 and 4.0: (Setting KeyContainerName will create a physical entry in your crypto folders)

var certificate = new X509Certificate2(@"C:\public.cer");
CspParameters parameters = new CspParameters { KeyContainerName = "KeyContainer" };
var rsa = new RSACryptoServiceProvider(parameters);
rsa.FromXmlString("<RSAKeyValue>......</RSAKeyValue>");
certificate.PrivateKey = rsa;
return certificate;

For simplicity, I was trying to export the private key into a .pfx file, but couldn't using the first approach in .NET 4.0, but could using .NET 3.5. Somwhow, the private key is not exportable in .NET 4.0. This link helped me fix it.

Still, would be nice to know what's changed between 3.5 and 4.0 here.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号