Как использовать SSL-сертификаты с HttpWebRequest в C #? - PullRequest
8 голосов
/ 11 марта 2011

В настоящее время я пишу служебное приложение, которое будет подключаться к заданному IP-адресу и порту и проверять информацию в сертификате SSL с помощью HttpWebRequest.Когда я пытаюсь извлечь сертификат, я получаю сообщение об ошибке, что возникло исключение.Похоже, исключение заключается в том, что процесс копирования сертификата SSL, по-видимому, вызывает еще одну проверку проверки.

Вот код, и, возможно, кто-то может либо показать мне лучший способ сделать это, либо я пропустилчто-то.Мне все равно, если срок действия сертификата SSL истек или не соответствует URL.Ничто из этого не имеет отношения к тому, что я делаю.

Когда я назначаю сертификат X509 в делегате новой переменной и смотрю на переменную в отладчике, все свойства показывают SSLCert.Issuerсгенерировал исключение типа 'System.Security.Cryptography.CyrptographicException'

Когда я пытаюсь получить доступ к свойству SSLCert, я получаю следующее исключение: m_safeCertContext - недопустимый дескриптор

Я искал это исключение, но все указывает на недействительный сертификат, который может быть истинным, если срок действия сертификата истек, и может быть истинным для комбинации IP и порта, к которому я подключаюсь.Но так как я подключаюсь к IP-адресу с использованием IP-адреса, а не чего-либо, что могло бы соответствовать общему имени, я ожидаю, что это может меня беспокоить, поскольку мне все еще нужна информация.

Код приведен ниже, я добавил несколько комментариева также за то, что не работает и что работает.

 // 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;

Ответы [ 2 ]

1 голос
/ 12 марта 2011

Это всего лишь предположение с моей стороны.Я думаю, что происходит из-за того, что информация о сертификате, передаваемая в рукопожатии SSL, используется .NET для создания объекта сертификата, который передается вам в делегате.Делегат должен использоваться только для валидации.После завершения вызова .NET закрывает безопасный дескриптор сертификата.Вот почему при попытке доступа к сертификату за пределами обратного вызова произойдет сбой вызова.

Чтобы обойти это, вы можете сериализовать сертификат внутри делегата и десериализовать его вне делегата.

0 голосов
/ 11 марта 2011

(Изменить из наших комментариев ниже)

Полагаю, вам нужно создать собственный класс и сохранить в нем необходимые данные внутри кода делегата, а не передавать фактическую ссылку на сертификат.

...