Как использовать SSL-сертификаты с HttpWebRequest в C#?
В настоящее время я пишу служебное приложение, которое будет подключаться к данному IP и Порту и проверять информацию в сертификате SSL с помощью HttpWebRequest. Когда я пытаюсь извлечь сертификат, я получаю сообщение об ошибке, вызвавшей исключение. Исключение, по-видимому, связано с тем, что акт преодоления SSL-сертификата, похоже, запускает еще одну проверку проверки.
вот код, и, возможно, кто-то может показать мне лучший способ сделать это, или если я что-то упускаю. Я не важно, истек ли срок действия SSL-сертификата или не соответствует URL-адресу. Все это не имеет отношения к тому, что я делаю.
когда я назначаю X509Certificate в делегате новой переменной и смотрю на переменную в отладчике, все свойства показывают SSLCert.Эмитент выдал исключение типа ' System.Безопасность.Криптография.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 ответов
(редактировать из наших комментариев ниже)
Я полагаю, что вам нужно создать пользовательский класс и сохранить необходимые данные в нем внутри кода делегата, а не передавать фактическую ссылку на сертификат.
Это просто догадка с моей стороны. Я думаю, что происходит то, что информация о сертификате, проходящая через SSL-рукопожатие, используется .NET для создания объекта cert, который передается вам в делегате. Делегат должен использоваться только для целей проверки. После завершения вызова .NET закрывает безопасный дескриптор сертификата. Вот почему вызов не выполняется при попытке получить доступ к сертификату вне обратного вызова.
чтобы обойти это, вы можете сериализовать сертификат внутри делегата и десериализуйте его вне делегата.