使用客户端证书身份验证连接到Web服务

使用客户端证书身份验证连接到Web服务

问题描述:

我获得了一个.p12文件,可以使用客户端证书身份验证通过SSL连接到网络服务。我已经使用cURL在PHP中成功工作了。这些是我在执行请求时使用的选项:

I've been give a .p12 file to connect to a web service over SSL using client certificate authentication. I have this successfully working in PHP, using cURL. These are the options I'm using when perform the request:

$headers = array(
    'Method: POST',
    'Connection: Keep-Alive',
    'User-Agent: PHP-SOAP-CURL',
    'Content-Type: text/xml; charset=utf-8',
    'SOAPAction: "'.$action.'"',
);

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $location);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_SSLCERT, $this->clientcert);
curl_setopt($ch, CURLOPT_SSLKEYTYPE, $this->clientcerttype);
curl_setopt($ch, CURLOPT_SSLKEY, $this->keyfile);
curl_setopt($ch, CURLOPT_SSLKEYPASSWD, $this->keypassword);
curl_setopt($ch, CURLOPT_SSLVERSION, 3);

$response = curl_exec($ch);

我现在正在尝试使用C#和.NET执行相同的任务,但是我一直在错误无法使用权​​限':'为SSL / TLS建立安全通道。。

I'm now trying to do the same task using C# and .NET, but I keep getting the error "Could not establish secure channel for SSL/TLS with authority ':'.".

我似乎在查找密钥时没有问题,并且在那里似乎没有任何信任问题。

I don't seem to have an issue with locating the key, and there don't appear to be any trust issues. Still, something isn't right, somewhere along the line.

我已经编写了一个测试程序,只是为了测试基本调用是否可以正常工作。

I've made a test program, just so I can test that a basic call will work.

public void StartviaWSHttp()
{
    var binding = new WSHttpBinding();
    binding.Security.Mode = SecurityMode.Transport;
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
    binding.Security.Message.NegotiateServiceCredential = false;
    binding.Security.Message.ClientCredentialType = MessageCredentialType.None;

    var baseAddress = new Uri("https://<host>:<port>/LineEndpoint1");
    var endpointAddress = new EndpointAddress(baseAddress);

    var client = new LinePortTypeClient(binding, endpointAddress);

    client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySerialNumber, "00d48a233bf4b77523");

    Debug.Assert(client.ClientCredentials.ClientCertificate.Certificate.SerialNumber.ToLower() == "00d48a233bf4b77523");

    var header = new ctSoapHeaderMsg();
    var response = new object();
    client.Open();
    var responseCode = client.PerformFunction(ref header, "0893411111", out response);
    client.Close();

    Console.WriteLine("Response Code :" + responseCode);
    Console.WriteLine("Response :" + response);
}

当我在当前用户的个人/证书中查看证书时,不报告任何有关信任的问题。在证书信息中,它表示该证书旨在用于以下目的:所有发行策略和所有应用程序策略。证书路径只有一个条目,并且证书状态报告此证书是可以的。

When I view the certificate in the Personal/Certificates for Current User, it does not report any issues, with regards to trust. In the certificate information, it says that the certificate in intended for the following purposes: All issuance policies and all application policies. The Certification Path only has one entry, and the Certificate status reports that "This certificate is OK."

我对问题的所在感到困惑。也许有一个信任问题,因为我取消了PHP调用的PEER和HOST验证。我不确定是否可以使用C#。

I'm at a loss for what the issue is. Perhaps there is a trust issue, since I have PEER and HOST verification off for the PHP call. I'm not sure if that is an option for C#.

更新:(2013年8月9日)
我为System.Net和System.Net.Socket设置了一些详细的跟踪。这是输出的开始。

Update: (9 August 2013) I set up some verbose tracing for System.Net and System.Net.Socket. This is the start of the output.

System.Net Verbose: 0 : [16124] WebRequest::Create(https://dsl-wholesale-testing.iinet.net.au:50500/LineEndpoint1)
System.Net Verbose: 0 : [16124] HttpWebRequest#58508234::HttpWebRequest(https://dsl-wholesale-testing.iinet.net.au:50500/LineEndpoint1#128335743)
System.Net Information: 0 : [16124] Current OS installation type is 'Client'.
System.Net Information: 0 : [16124] RAS supported: True
System.Net Verbose: 0 : [16124] Exiting HttpWebRequest#58508234::HttpWebRequest() 
System.Net Verbose: 0 : [16124] Exiting WebRequest::Create()    -> HttpWebRequest#58508234
System.Net Verbose: 0 : [16124] ServicePoint#36898364::ServicePoint(dsl-wholesale-testing.iinet.net.au:50500)
System.Net Information: 0 : [16124] Associating HttpWebRequest#58508234 with ServicePoint#36898364
System.Net Verbose: 0 : [16124] HttpWebRequest#58508234::GetRequestStream()
System.Net Information: 0 : [16124] Associating Connection#47995487 with HttpWebRequest#58508234
System.Net.Sockets Verbose: 0 : [16124] Socket#31002555::Socket(AddressFamily#2)
System.Net.Sockets Verbose: 0 : [16124] Exiting Socket#31002555::Socket() 
System.Net.Sockets Verbose: 0 : [16124] Socket#6243847::Socket(AddressFamily#23)
System.Net.Sockets Verbose: 0 : [16124] Exiting Socket#6243847::Socket() 
System.Net.Sockets Verbose: 0 : [16124] DNS::TryInternalResolve(dsl-wholesale-testing.iinet.net.au)
System.Net.Sockets Verbose: 0 : [16124] Socket#31002555::Connect(203.173.51.130:50500#-2110560113)
System.Net.Sockets Information: 0 : [16124] Socket#31002555 - Created connection from 192.168.190.202:55397 to 203.173.51.130:50500.
System.Net.Sockets Verbose: 0 : [16124] Exiting Socket#31002555::Connect() 
System.Net.Sockets Verbose: 0 : [16124] Socket#6243847::Close()
System.Net.Sockets Verbose: 0 : [16124] Socket#6243847::Dispose()
System.Net.Sockets Verbose: 0 : [16124] Exiting Socket#6243847::Close() 
System.Net Information: 0 : [16124] Connection#47995487 - Created connection from 192.168.190.202:55397 to 203.173.51.130:50500.
System.Net Information: 0 : [16124] TlsStream#29695768::.ctor(host=dsl-wholesale-testing.iinet.net.au, #certs=0)
System.Net Information: 0 : [16124] Associating HttpWebRequest#58508234 with ConnectStream#25001628
System.Net Verbose: 0 : [16124] Exiting HttpWebRequest#58508234::GetRequestStream()     -> ConnectStream#25001628
System.Net Verbose: 0 : [16124] ConnectStream#25001628::Write()
System.Net Verbose: 0 : [16124] Data from ConnectStream#25001628::Write
System.Net Verbose: 0 : [16124] (printing 1024 out of 1206)
System.Net Verbose: 0 : [16124] 00000000 : 3C 73 3A 45 6E 76 65 6C-6F 70 65 20 78 6D 6C 6E : <s:Envelope xmln

System.Net行信息: 0:[16124] TlsStream#29695768 ::。ctor(host = dsl-wholesale-testing.iinet.net.au,#certs = 0)表示未选择使用证书,即使我已将证书附加到client.ClientCredentials.ClientCertificate,但我不确定为什么会发生这种情况或如何使其坚持下去。证书的任何属性是否必须与我要连接的主机名匹配?

The line System.Net Information: 0 : [16124] TlsStream#29695768::.ctor(host=dsl-wholesale-testing.iinet.net.au, #certs=0) suggests that no certificates have been picked up for use, even though I've attached the certificate to the client.ClientCredentials.ClientCertificate, but I'm not sure why this is happening or how to make it stick. Do any properties of the certificate have to match the hostname that I'm connecting to?

服务器似乎没有理解TLS。

It appears that the server did not understand TLS.

我必须通过

System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Ssl3;