I added WCF connected service reference in my project and set ServicePointManager.ServerCertificateValidationCallback function. For some reason, this callback function is ignored when i am requesting server. I have to notify user about certificate problems and proceed request if user confirms.
static async Task Main(string[] args)
{
ServicePointManager.ServerCertificateValidationCallback = MyServerCertificateValidationCallback;
var data = new DataSoapClient(DataSoapClient.EndpointConfiguration.DataSoap);
data.Endpoint.Address = new EndpointAddress("https://open.helios.eu/demo/Data.asmx");
(data.Endpoint.Binding as BasicHttpBinding).Security.Mode = BasicHttpSecurityMode.Transport;
var result = (await data.GetInfoAsync("GETREDIRECTINFO", string.Empty)).Body.GetInfoResult;
Console.WriteLine(result);
}
private static bool MyServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
// function won't execute
return true;
}
Finally i found a solution for my problem. As Abraham Quian mentioned, callback is not working in .net core so I had to use different approach and use X509CertificateValidator. Here is a code snippet:
static async Task Main(string[] args)
{
var data = new ServiceReference1.Service1Client(Service1Client.EndpointConfiguration.BasicHttpsBinding_IService1);
data.Endpoint.Address = new EndpointAddress("https://localhost:5035/Service1.svc");
(data.Endpoint.Binding as BasicHttpBinding).Security.Mode = BasicHttpSecurityMode.Transport;
data.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication();
data.ClientCredentials.ServiceCertificate.SslCertificateAuthentication.CertificateValidationMode = X509CertificateValidationMode.Custom;
data.ClientCredentials.ServiceCertificate.SslCertificateAuthentication.CustomCertificateValidator = new Validator();
var result = await data.GetDataAsync(1);
Console.WriteLine(result);
}
And there is validator:
internal class Validator : X509CertificateValidator
{
public override void Validate(X509Certificate2 certificate)
{
X509Chain chain = new X509Chain();
if (!chain.Build(certificate))
{
Console.WriteLine($"{chain.ChainStatus.FirstOrDefault().StatusInformation}. Press y to proceed...");
if(Console.ReadKey().KeyChar != 'y')
throw new SecurityTokenValidationException("Service certification is not valid.");
}
}
}
ServicePointManager.ServerCertificateValidationCallback += delegate
{
return true;
};
This code snippet is valid in the Dotnetframework project, it is invalid in the Dotnet Core project.
Generally, in the case of ensuring that the certificate can be trusted, we should install the certificate provided by the server to the Root CA certificate store on the client-side.
In addition, the following code snippet applies to both the DotNet Core project and the Dotnetframework project.
ServiceReference1.TestServiceClient client = new ServiceReference1.TestServiceClient();
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new System.ServiceModel.Security.X509ServiceCertificateAuthentication
{
CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None,
RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
};
Feel free to let me know if the problem still exists.
Related
I'm trying to utilize a REST API on a local web server with a self-signed certificate. At runtime, the application throws the error
AuthenticationException: The remote certificate is invalid according to the validation procedure.
I have tried the fix in this answer: https://stackoverflow.com/a/1386568/8980983 however the error remains. Code is below:
static void Main(string[] args)
{
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Clear();
ServicePointManager.ServerCertificateValidationCallback = delegate (
object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
};
var loginPage = httpClient.GetAsync("https://<local IP address>/loginpage.html").GetAwaiter().GetResult();
//do stuff with response...
}
Any ideas of what I can do to effectively ignore SSL policy errors?
Figured it out. Turns out the HttpClient class doesn't use the ServicePointManager.ServerCertificateValidationCallback method. Solution was as follows:
static void Main(string[] args)
{
HttpClientHandler httpClientHandler = new HttpClientHandler();
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
HttpClient httpClient = new HttpClient(httpClientHandler);
httpClient.DefaultRequestHeaders.Clear();
var loginPage = httpClient.GetAsync("https://<local IP address>/loginpage.html").GetAwaiter().GetResult();
}
Hello!
I want connect to private repository. I have login and password, but program stopped in SSL Verification..
Error: Additional information: this remote has never connected
How i can fix this error?
My code:
String urls = "url";
HttpWebRequest request = HttpWebRequest.CreateHttp(urls);
request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => false;
Console.WriteLine(request.AuthenticationLevel);
var credentials = new UsernamePasswordCredentials
{
Username = "user",
Password = "password"
};
var remote = Repository.ListRemoteReferences("url", (url, fromUrl, types) => credentials);
foreach (var reference in remote)
{
Console.WriteLine(reference.TargetIdentifier);
}
Can you suggest how to disable the check properly when connected to a repository?
All is decided!
The error was in ignorance of the full server repository!
I talk to my server using SSL, but have self-signed cert.
In Android I use this code to pass my SSL cert to system to be able make requests to my server:
KeyStore ks = KeyStore.getInstance("BKS");
InputStream in = new ByteArrayInputStream(<byte [] my_ssl_data>);
ks.load(in, <string mypassword>.toCharArray());
in.close();
TrustManagerFactory Main_TMF = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
Main_TMF.init(ks);
X509TrustManager Cur_Trust_Manager = new X509TrustManager()
{
public void checkClientTrusted(X509Certificate [] chain, String authType) throws CertificateException { }
public void checkServerTrusted(X509Certificate [] chain, String authType) throws CertificateException { }
public X509Certificate [] getAcceptedIssuers() { return null; }
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { Cur_Trust_Manager }, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
{
#Override
public boolean verify(String hostname, SSLSession session)
{
try
{
Cur_Trust_Manager.checkServerTrusted((X509Certificate []) session.getPeerCertificates(), session.getCipherSuite());
return true;
}
catch (Exception e) {}
return false;
}
});
Now I need something like this in Windows Universal App 8.1+ (Windows+WindowsPhone) and iOS 7.0+.
For network requests I use System.Net.Http.HttpClient which works both with UWP and Xamarin.iOS. I have cert from my server in DER format but still can't add a handler to HttpClient.
Xamarin.iOS version says "Not implemented"
HttpClientHandler myHandler = new HttpClientHandler();
X509Certificate2 certificate = new X509Certificate2();
certificate.Import(my_cert_der_bytes);
myHandler.ClientCertificates.Add(certificate);
myHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
myHandler.AllowAutoRedirect = false;
HttpClient c = new HttpClient(myHandler);
....
UWP version unfortunately (and why the hell?) doesn't know X509Certificate2 and all that stuff. I tried to use WinRtHttpClientHandler but didn't understand where should I pass my cert. I tried to skip errors (started to work), yet that's not a solution, because I don't want my requests to be redirected to another untrasted server.
var filter = new HttpBaseProtocolFilter();
Certificate cer = new Certificate(my_cert_bytes.AsBuffer());
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Expired);
WinRtHttpClientHandler myHandler = new WinRtHttpClientHandler(filter);
HttpClient c = new HttpClient(myHandler);
....
I suspect this is common task for most indies, certs are seldom for tests and small apps. But it seems task is made very difficult by platform devs. Is there any reliable solution?
UWP apps cannot work with invalid (and self-signed) certificates. You may use Fiddler as proxy with fiddler's certificate for tests https.
Telerik Fiddler options - HTTPS - Capture HTTPS connects.
This work only on desktop not a mobile emulator.
I am working on a project that needs to connect to an https site. Every time I connect, my code throws exception because the certificate of that site comes from untrusted site. Is there a way to bypass certificate check in .net core http?
I saw this code from previous version of .NET. I guess I just need something like this.
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
Update:
As mentioned below, not all implementations support this callback (i.e. platforms like iOS). In this case, as the docs say, you can set the validator explicitly:
handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
This works too for .NET Core 2.2, 3.0 and 3.1
Old answer, with more control but may throw PlatformNotSupportedException:
You can override SSL cert check on a HTTP call with the a anonymous callback function like this
using (var httpClientHandler = new HttpClientHandler())
{
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
using (var client = new HttpClient(httpClientHandler))
{
// Make your request...
}
}
Additionally, I suggest to use a factory pattern for HttpClient because it is a shared object that might no be disposed immediately and therefore connections will stay open.
I solve with this:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient("HttpClientWithSSLUntrusted").ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
ClientCertificateOptions = ClientCertificateOption.Manual,
ServerCertificateCustomValidationCallback =
(httpRequestMessage, cert, cetChain, policyErrors) =>
{
return true;
}
});
YourService.cs
public UserService(IHttpClientFactory clientFactory, IOptions<AppSettings> appSettings)
{
_appSettings = appSettings.Value;
_clientFactory = clientFactory;
}
var request = new HttpRequestMessage(...
var client = _clientFactory.CreateClient("HttpClientWithSSLUntrusted");
HttpResponseMessage response = await client.SendAsync(request);
Came here looking for an answer to the same problem, but I'm using WCF for NET Core. If you're in the same boat, use:
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None,
RevocationMode = X509RevocationMode.NoCheck
};
ServicePointManager.ServerCertificateValidationCallback isn't supported in .Net Core.
Current situation is that it will be a
a new ServerCertificateCustomValidationCallback method for the upcoming 4.1.* System.Net.Http contract (HttpClient). .NET Core team are finalizing the 4.1 contract now. You can read about this in here on github
You can try out the pre-release version of System.Net.Http 4.1 by using the sources directly here in CoreFx or on the MYGET feed:
https://dotnet.myget.org/gallery/dotnet-core
Current WinHttpHandler.ServerCertificateCustomValidationCallback definition on Github
In .NetCore, you can add the following code snippet at services configure method , I added a check to make sure only that we by pass the SSL certificate in development environment only
services.AddHttpClient("HttpClientName", client => {
// code to configure headers etc..
}).ConfigurePrimaryHttpMessageHandler(() => {
var handler = new HttpClientHandler();
if (hostingEnvironment.IsDevelopment())
{
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
}
return handler;
});
I faced off the same problem when working with self-signed certs and client cert auth on .NET Core 2.2 and Docker Linux containers. Everything worked fine on my dev Windows machine, but in Docker I got such error:
System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure
Fortunately, the certificate was generated using a chain.
Of course, you can always ignore this solution and use the above solutions.
So here is my solution:
I saved the certificate using Chrome on my computer in P7B format.
Convert certificate to PEM format using this command:
openssl pkcs7 -inform DER -outform PEM -in <cert>.p7b -print_certs > ca_bundle.crt
Open the ca_bundle.crt file and delete all Subject recordings, leaving a clean file. Example below:
-----BEGIN CERTIFICATE-----
_BASE64 DATA_
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
_BASE64 DATA_
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
_BASE64 DATA_
-----END CERTIFICATE-----
Put these lines to the Dockerfile (in the final steps):
# Update system and install curl and ca-certificates
RUN apt-get update && apt-get install -y curl && apt-get install -y ca-certificates
# Copy your bundle file to the system trusted storage
COPY ./ca_bundle.crt /usr/local/share/ca-certificates/ca_bundle.crt
# During docker build, after this line you will get such output: 1 added, 0 removed; done.
RUN update-ca-certificates
In the app:
var address = new EndpointAddress("https://serviceUrl");
var binding = new BasicHttpsBinding
{
CloseTimeout = new TimeSpan(0, 1, 0),
OpenTimeout = new TimeSpan(0, 1, 0),
ReceiveTimeout = new TimeSpan(0, 1, 0),
SendTimeout = new TimeSpan(0, 1, 0),
MaxBufferPoolSize = 524288,
MaxBufferSize = 65536,
MaxReceivedMessageSize = 65536,
TextEncoding = Encoding.UTF8,
TransferMode = TransferMode.Buffered,
UseDefaultWebProxy = true,
AllowCookies = false,
BypassProxyOnLocal = false,
ReaderQuotas = XmlDictionaryReaderQuotas.Max,
Security =
{
Mode = BasicHttpsSecurityMode.Transport,
Transport = new HttpTransportSecurity
{
ClientCredentialType = HttpClientCredentialType.Certificate,
ProxyCredentialType = HttpProxyCredentialType.None
}
}
};
var client = new MyWSClient(binding, address);
client.ClientCredentials.ClientCertificate.Certificate = GetClientCertificate("clientCert.pfx", "passwordForClientCert");
// Client certs must be installed
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication
{
CertificateValidationMode = X509CertificateValidationMode.ChainTrust,
TrustedStoreLocation = StoreLocation.LocalMachine,
RevocationMode = X509RevocationMode.NoCheck
};
GetClientCertificate method:
private static X509Certificate2 GetClientCertificate(string clientCertName, string password)
{
//Create X509Certificate2 object from .pfx file
byte[] rawData = null;
using (var f = new FileStream(Path.Combine(AppContext.BaseDirectory, clientCertName), FileMode.Open, FileAccess.Read))
{
var size = (int)f.Length;
var rawData = new byte[size];
f.Read(rawData, 0, size);
f.Close();
}
return new X509Certificate2(rawData, password);
}
Allowing all certificates is very powerful but it could also be dangerous. If you would like to only allow valid certificates plus some certain certificates it could be done like this.
using (var httpClientHandler = new HttpClientHandler())
{
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) => {
if (sslPolicyErrors == SslPolicyErrors.None)
{
return true; //Is valid
}
if (cert.GetCertHashString() == "99E92D8447AEF30483B1D7527812C9B7B3A915A7")
{
return true;
}
return false;
};
using (var httpClient = new HttpClient(httpClientHandler))
{
var httpResponse = httpClient.GetAsync("https://example.com").Result;
}
}
Original source:
https://stackoverflow.com/a/44140506/3850405
For .NET 6 you can configure your primary Http message handler like this:
services.AddHttpClient<ITodoListService, TodoListService>()
.ConfigurePrimaryHttpMessageHandler(() => {
var handler = new HttpClientHandler();
if (currentEnvironment.IsDevelopment()) {
handler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
}
return handler;
});
Link to official docs
Firstly, DO NOT USE IT IN PRODUCTION
If you are using AddHttpClient to install Http service this will be usefull.
I think it is needed for development purpose not production. Until you create a valid certificate you could use this Func.
Func<HttpMessageHandler> configureHandler = () =>
{
var bypassCertValidation = Configuration.GetValue<bool>("BypassRemoteCertificateValidation");
var handler = new HttpClientHandler();
//!DO NOT DO IT IN PRODUCTION!! GO AND CREATE VALID CERTIFICATE!
if (bypassCertValidation)
{
handler.ServerCertificateCustomValidationCallback = (httpRequestMessage, x509Certificate2, x509Chain, sslPolicyErrors) =>
{
return true;
};
}
return handler;
};
and apply it like
services.AddHttpClient<IMyClient, MyClient>(x => { x.BaseAddress = new Uri("https://localhost:5005"); })
.ConfigurePrimaryHttpMessageHandler(configureHandler);
I'm struggling to get my Windows 8 application to communicate with my test web API over SSL.
It seems that HttpClient/HttpClientHandler does not provide and option to ignore untrusted certificates like WebRequest enables you to (albeit in a "hacky" way with ServerCertificateValidationCallback).
Any help would be much appreciated!
A quick and dirty solution is to use the ServicePointManager.ServerCertificateValidationCallback delegate. This allows you to provide your own certificate validation. The validation is applied globally across the whole App Domain.
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
I use this mainly for unit testing in situations where I want to run against an endpoint that I am hosting in process and am trying to hit it with a WCF client or the HttpClient.
For production code you may want more fine grained control and would be better off using the WebRequestHandler and its ServerCertificateValidationCallback delegate property (See dtb's answer below). Or ctacke answer using the HttpClientHandler. I am preferring either of these two now even with my integration tests over how I used to do it unless I cannot find any other hook.
If you're attempting to do this in a .NET Standard library, here's a simple solution, with all of the risks of just returning true in your handler. I leave safety up to you.
var handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ServerCertificateCustomValidationCallback =
(httpRequestMessage, cert, cetChain, policyErrors) =>
{
return true;
};
var client = new HttpClient(handler);
Have a look at the WebRequestHandler Class and its ServerCertificateValidationCallback Property:
using (var handler = new WebRequestHandler())
{
handler.ServerCertificateValidationCallback = ...
using (var client = new HttpClient(handler))
{
...
}
}
If you are using System.Net.Http.HttpClient I believe correct pattern is
var handler = new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
};
var http = new HttpClient(handler);
var res = http.GetAsync(url);
Link to official doc
Most answers here suggest to use the typical pattern:
using (var httpClient = new HttpClient())
{
// do something
}
because of the IDisposable interface. Please don't!
Microsoft tells you why:
Improper Instantiation antipattern
HttpClient, HttpClientHandler, and WebRequestHandler Explained
And here you can find a detailed analysis whats going on behind the scenes:
You're using HttpClient wrong and it is destabilizing your software
Official Microsoft link: HttpClient
HttpClient is intended to be instantiated once and re-used throughout the life of an application. Instantiating an HttpClient class for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors.
Regarding your SSL question and based on Improper Instantiation antipattern # How to fix the problem
Here is your pattern:
class HttpInterface
{
// https://learn.microsoft.com/en-us/azure/architecture/antipatterns/improper-instantiation/#how-to-fix-the-problem
// https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient#remarks
private static readonly HttpClient client;
// static initialize
static HttpInterface()
{
// choose one of these depending on your framework
// HttpClientHandler is an HttpMessageHandler with a common set of properties
var handler = new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = delegate { return true; },
};
// derives from HttpClientHandler but adds properties that generally only are available on full .NET
var handler = new WebRequestHandler()
{
ServerCertificateValidationCallback = delegate { return true; },
ServerCertificateCustomValidationCallback = delegate { return true; },
};
client = new HttpClient(handler);
}
.....
// in your code use the static client to do your stuff
var jsonEncoded = new StringContent(someJsonString, Encoding.UTF8, "application/json");
// here in sync
using (HttpResponseMessage resultMsg = client.PostAsync(someRequestUrl, jsonEncoded).Result)
{
using (HttpContent respContent = resultMsg.Content)
{
return respContent.ReadAsStringAsync().Result;
}
}
}
Or you can use for the HttpClient in the Windows.Web.Http namespace:
var filter = new HttpBaseProtocolFilter();
#if DEBUG
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Expired);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
#endif
using (var httpClient = new HttpClient(filter)) {
...
}
With Windows 8.1, you can now trust invalid SSL certs. You have to either use the Windows.Web.HttpClient or if you want to use the System.Net.Http.HttpClient, you can use the message handler adapter I wrote:
http://www.nuget.org/packages/WinRtHttpClientHandler
Docs are on the GitHub:
https://github.com/onovotny/WinRtHttpClientHandler
If this is for a Windows Runtime application, then you have to add the self-signed certificate to the project and reference it in the appxmanifest.
The docs are here:
http://msdn.microsoft.com/en-us/library/windows/apps/hh465031.aspx
Same thing if it's from a CA that's not trusted (like a private CA that the machine itself doesn't trust) -- you need to get the CA's public cert, add it as content to the app then add it to the manifest.
Once that's done, the app will see it as a correctly signed cert.
Use this in Startup.cs for ASP.NET Core project:
public void ConfigureServices(IServiceCollection services)
{
// other code
services
.AddHttpClient<IMyService, MyService>(client =>
{
client.BaseAddress = new Uri(myConfiguration.BaseUrl);
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
// Allowing Untrusted SSL Certificates
var handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ServerCertificateCustomValidationCallback =
(httpRequestMessage, cert, cetChain, policyErrors) => true;
return handler;
});
}
I found an example in this Kubernetes client where they were using X509VerificationFlags.AllowUnknownCertificateAuthority to trust self-signed root certificates. I slightly reworked their example to work with our own PEM encoded root certificates. Hopefully this helps someone.
namespace Utils
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
/// <summary>
/// Verifies that specific self signed root certificates are trusted.
/// </summary>
public class HttpClientHandler : System.Net.Http.HttpClientHandler
{
/// <summary>
/// Initializes a new instance of the <see cref="HttpClientHandler"/> class.
/// </summary>
/// <param name="pemRootCerts">The PEM encoded root certificates to trust.</param>
public HttpClientHandler(IEnumerable<string> pemRootCerts)
{
foreach (var pemRootCert in pemRootCerts)
{
var text = pemRootCert.Trim();
text = text.Replace("-----BEGIN CERTIFICATE-----", string.Empty);
text = text.Replace("-----END CERTIFICATE-----", string.Empty);
this.rootCerts.Add(new X509Certificate2(Convert.FromBase64String(text)));
}
this.ServerCertificateCustomValidationCallback = this.VerifyServerCertificate;
}
private bool VerifyServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
// If the certificate is a valid, signed certificate, return true.
if (sslPolicyErrors == SslPolicyErrors.None)
{
return true;
}
// If there are errors in the certificate chain, look at each error to determine the cause.
if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) != 0)
{
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
// add all your extra certificate chain
foreach (var rootCert in this.rootCerts)
{
chain.ChainPolicy.ExtraStore.Add(rootCert);
}
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
var isValid = chain.Build((X509Certificate2)certificate);
var rootCertActual = chain.ChainElements[chain.ChainElements.Count - 1].Certificate;
var rootCertExpected = this.rootCerts[this.rootCerts.Count - 1];
isValid = isValid && rootCertActual.RawData.SequenceEqual(rootCertExpected.RawData);
return isValid;
}
// In all other cases, return false.
return false;
}
private readonly IList<X509Certificate2> rootCerts = new List<X509Certificate2>();
}
}
I don't have an answer, but I do have an alternative.
If you use Fiddler2 to monitor traffic AND enable HTTPS Decryption, your development environment will not complain. This will not work on WinRT devices, such as Microsoft Surface, because you cannot install standard apps on them. But your development Win8 computer will be fine.
To enable HTTPS encryption in Fiddler2, go to Tools > Fiddler Options > HTTPS (Tab) > Check "Decrypt HTTPS Traffic".
I'm going to keep my eye on this thread hoping for someone to have an elegant solution.
I found an example online which seems to work well:
First you create a new ICertificatePolicy
using System.Security.Cryptography.X509Certificates;
using System.Net;
public class MyPolicy : ICertificatePolicy
{
public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request,
int certificateProblem)
{
//Return True to force the certificate to be accepted.
return true;
}
}
Then just use this prior to sending your http request like so:
System.Net.ServicePointManager.CertificatePolicy = new MyPolicy();
http://www.terminally-incoherent.com/blog/2008/05/05/send-a-https-post-request-with-c/
For Xamarin Android this was the only solution that worked for me: another stack overflow post
If you are using AndroidClientHandler, you need to supply a SSLSocketFactory and a custom implementation of HostnameVerifier with all checks disabled. To do this, you’ll need to subclass AndroidClientHandler and override the appropriate methods.
internal class BypassHostnameVerifier : Java.Lang.Object, IHostnameVerifier
{
public bool Verify(string hostname, ISSLSession session)
{
return true;
}
}
internal class InsecureAndroidClientHandler : AndroidClientHandler
{
protected override SSLSocketFactory ConfigureCustomSSLSocketFactory(HttpsURLConnection connection)
{
return SSLCertificateSocketFactory.GetInsecure(1000, null);
}
protected override IHostnameVerifier GetSSLHostnameVerifier(HttpsURLConnection connection)
{
return new BypassHostnameVerifier();
}
}
And then
var httpClient = new System.Net.Http.HttpClient(new InsecureAndroidClientHandler());