简体   繁体   English

如何在C#中将SSL证书与HttpWebRequest一起使用?

[英]How do I use SSL certificates with HttpWebRequest in C#?

Currently I'm writing a utility application that will connect to a given IP and port and check the information in the SSL certificate using HttpWebRequest. 目前,我正在编写一个实用程序应用程序,该应用程序将连接到给定的IP和端口,并使用HttpWebRequest检查SSL证书中的信息。 When I try to extract the certificate I get an error that an exception was thrown. 当我尝试提取证书时,出现错误,引发了异常。 The exception seems to be because the act of coping the SSL certificate seems to trigger yet another validation check. 异常似乎是因为应对SSL证书的行为似乎触发了另一次验证检查。

Here is the code, and maybe someone can either show me a better way to do this or if I am missing something. 这是代码,也许有人可以向我展示一种更好的方法来执行此操作,或者如果我缺少某些内容。 I don't care if the SSL Certificate is expired or doesn't match the URL. 我不在乎SSL证书是否过期或与URL不匹配。 None of that is relevant for what I'm doing. 这些都与我的工作无关。

When I assign the X509Certificate in the delegate to a new variable, and look at the variable in the debugger, all the properties show SSLCert.Issuer threw an exception of type 'System.Security.Cryptography.CyrptographicException' 当我将委托中的X509Certificate分配给新变量,并在调试器中查看该变量时,所有属性均显示SSLCert.Issuer引发了类型为'System.Security.Cryptography.CyrptographicException'的异常

When I try to access a property of SSLCert, I get the following Exception thrown: m_safeCertContext is an invalid handle 当我尝试访问SSLCert的属性时,会引发以下异常: m_safeCertContext是无效的句柄

I'be searched for that exception, but everything points to an invalid certificate, which might be true if the certificate is expired, and might be true for the IP and port combination I am connecting to. 我正在搜索该异常,但是所有内容都指向一个无效的证书,如果该证书已过期,则可能为true,并且对于我要连接的IP和端口组合,可能为true。 But since I am connecting to the IP using the IP and not anything that would match the common name, I expect that and could care less as I still need the information. 但是由于我是使用IP而不是与通用名称匹配的任何东西连接到IP的,所以我希望这样,并且由于我仍然需要信息,因此不必担心。

The code is below, I put some comments in as well for what doesn't work and what does work. 下面的代码,对于什么不起作用和什么起作用,我也添加了一些注释。

 // To get around the SSL validation in the HttpWebRequest
        System.Net.ServicePointManager.ServerCertificateValidationCallback =
            delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                        System.Security.Cryptography.X509Certificates.X509Chain chain,
                        System.Net.Security.SslPolicyErrors sslPolicyErrors)
            {
                // The below works but isn't what I want. CertName and ExpireDate are both Strings
                this.CertName = ProcessSubject(certificate.Subject);
                this.ExpireDate = certificate.GetExpirationDateString();
                // The below works but the X509Certificate SSLCert shows exceptions in the debugger for most of the properties.
                this.SSLCert = certificate;

                return true; // **** Always accept
            };
        HttpWebRequest myRequest = (HttpWebRequest)System.Net.WebRequest.Create("https://" + this.IP + ":" + this.Port + "/SSLCheck.html");
        myRequest.KeepAlive = false;
        myRequest.Method = "GET";

        try
        {
            HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
        }
        catch (Exception e)
        {
            if (e.Message != "The remote server returned an error: (404) Not Found.")
            {
                throw Exception("Error");
            }

        }

        // THE BELOW FAILS
        this.CertName = this.SSLCert.Subject;

This is just a guess on my part. 这只是我的猜测。 WHat I think is happening is that the certificate info coming through in the SSL handshake is used by .NET to create a cert object that is passed to you in the delegate. 我认为正在发生的事情是.NET使用SSL握手中传递的证书信息来创建一个证书对象,该对象在委托中传递给您。 The delegate is only to be used for the purpose of validation. 该委托仅用于验证目的。 After the call completes, .NET closes the safe handle of the certificate. 调用完成后,.NET将关闭证书的安全句柄。 THat is why the call fails when trying to access the certificate outside the callback. 这就是为什么尝试在回调之外访问证书时调用失败的原因。

TO get around this, you can serialize the certificate inside the delegate, and deserialize it outside the delegate. 要解决此问题,您可以在代理内部对证书进行序列化,并在代理外部对其进行反序列化。

(Edit from our comments below) (从下面的评论中编辑)

I suppose what you need to do is create a custom class and store the data you need in it inside the delegate code, rather than pass around the actual certificate reference. 我想您需要做的是创建一个自定义类,并将所需的数据存储在委托代码中,而不是传递实际的证书引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM