How do I use WebRequest to access an SSL encrypted site using HTTPS?

C#.NetHttpsHttpwebrequestWebrequest

C# Problem Overview


I'm writing a program that reads content from a user provided URL. My problem is in the code that goes something like this:

Uri uri = new Uri(url);
WebRequest webRequest = WebRequest.Create(uri);
WebResponse webResponse = webRequest.GetResponse();
ReadFrom(webResponse.GetResponseStream());

And this is breaking if the provided url is an https:// URL. Can anyone help me with changing this code so that it will work with SSL encrypted content. Thanks.

C# Solutions


Solution 1 - C#

You're doing it the correct way but users may be providing urls to sites that have invalid SSL certs installed. You can ignore those cert problems if you put this line in before you make the actual web request:

ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications);

where AcceptAllCertifications is defined as

public bool AcceptAllCertifications(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certification, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
    return true;
}

Solution 2 - C#

This one worked for me:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Solution 3 - C#

This link will be of interest to you: http://msdn.microsoft.com/en-us/library/ds8bxk2a.aspx

> For http connections, the WebRequest and WebResponse classes use SSL to communicate with web hosts that support SSL. The decision to use SSL is made by the WebRequest class, based on the URI it is given. If the URI begins with "https:", SSL is used; if the URI begins with "http:", an unencrypted connection is used.

Solution 4 - C#

As the most voted answer by @LukeDuff correctly says, it is probable that the server uses an invalid or untrusted (or self-signed, what is technically also untrusted) certificate. But the answer blindly accepts any certificate. And what's worse, even any certificate for any site, even for sites, where you expect trusted and valid certificate. That's a security flaw.

When implementing ServicePointManager.ServerCertificateValidation callback one should validate the certificate. E.g. by checking certificate's hash against a known value:

using System.Net;
using System.Net.Security;
using System.Security.Cryptography;
ServicePointManager.ServerCertificateValidationCallback +=
    (sender, certificate, chain, errors) =>
    {
        return
            (errors == SslPolicyErrors.None) ||
            certificate.GetCertHashString(HashAlgorithmName.SHA256).Equals(
                "EB8E0B28AE064ED58CBED9DAEB46CFEB3BD7ECA677...");
    };

For the X509Certificate.GetCertHashString overload that takes HashAlgorithmName.SHA256, you need .NET 4.8. On older versions use the parameter-less overload that returns an SHA-1 hash.


Based on https://stackoverflow.com/q/34642606/850848

For VB.NET version of the code, see https://stackoverflow.com/q/5998004/850848#66559532.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlfred B. ThordarsonView Question on Stackoverflow
Solution 1 - C#LukeDuffView Answer on Stackoverflow
Solution 2 - C#NaniView Answer on Stackoverflow
Solution 3 - C#GurdeepSView Answer on Stackoverflow
Solution 4 - C#Martin PrikrylView Answer on Stackoverflow