No peer cert. Not sure which route to take - android

I'm trying to hit an https url with my app. I've followed this tutorial. The store I've created has the correct CA. However, when I try to make the connection, I get the following error:
ERROR/IOException(1843): webPost: javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
I've done some reading about this error and people have decided to allow their apps to accept all certificates. I don't think that's really acceptable. What should I check next to see what the issue is?

You can configure your device to ignore SSL certificates:
http://www.virtualzone.de/2011-02-27/how-to-use-apache-httpclient-with-httpsssl-on-android/(dead link)
UPDATE: Much better answer is visible here:
Trusting all certificates using HttpClient over HTTPS
Or do things specific to your HttpClient version:
HttpGet with HTTPS : SSLPeerUnverifiedException

Related

Xamarin Forms HttpClient SSL Certification validation error

I got pretty stuck with a problem in Xamarin.Forms (Forms though, but I only have an Android project, I need to support only that).
The app must post to the backend, and the backend do SSL cert validation.
I have a test device, an Android 11 Samsung. Among the user certificates on the device, there is the cert I need (Settings - Security - User certificates).
When I open a Google Chrome on my phone, it loads the swagger UI of the backend, and I think it first asked me if I wanted to use my cert.
The swagger works, I was able to try the endpoints there.
The problem is that I can't make a backend call from the app because it immediately drops my request with an SSL certification validation failed message.
I wrote some quick test code with exact namespaces to understand what I'm doing:
// This returns the cert of the user's certificates:
Java.Security.Cert.X509Certificate myJavaCert = KeyChain.GetCertificateChain(this.ApplicationContext, "MyCertAlias").FirstOrDefault();
//Convert to X509Certificate2:
var myDotNetCert = new System.Security.Cryptography.X509Certificates.X509Certificate2(myJavaCert.GetEncoded());
//I'm doing HttpClient manually, I don't want to use IHttpClientFactory yet:
var httpClientHandler = new HttpClientHandler();
httpClientHandler.ClientCertificates.Add(myDotNetCert);
var httpClient = new HttpClient(httpClientHandler);
// Finally I call the post that runs for the above mentioned error:
await httpClient.PostAsync(url, objectToPost);
I’m pretty stuck with this task, I don’t really know where to try.
Thanks for the help in advance too!
After one week of research I finally figured it out to myself.
Here is the full-detailed answer for my own question:
Xamarin Forms (Android) Client certificate from KeyStore vs PFX file

HttpClient generates SSLException after acquiring new domain name

Recently I acquired a new domain name to use with an existing Android application. I also bought SSL certificate from a trusted CA (Comodo). When I browse to the new domain with a web browser, everything works as expected - no errors about SSL certificate. Same with HttpUrlConnection, but for some reason Apaches HttpClient generates an SSLException:
javax.net.ssl.SSLException: hostname in certificate didn't match: my.new.domain != my.old.domain OR my.old.domain
What's more interesting, some of the devices that I tried with worked fine for about a week after the change, and stopped working after that. Other devices stopped working right away.
If I use the old domain name in client code, everything works correctly.
I'm using version 4.3.3 from here of the HttpClient for Android. I realize that converting to HttpUrlConnection would indeed solve my problem, but I'm interested in WHY this is happening - from where does the HttpClient pick up the old domain name? Is it some misconfiguration on the server, or does Apaches HttpClient have some sort of internal dns cache? Testing with a fresh emulator instance raised the same exception, so the problem is not related to caching.
My own investigations got stuck - all I could find was instructions for disabling hostname verification completely, or instructions for self-signed certificates.
That's probably because Apache HttpClient does not support SNI (server name indication), where you can have multiple certificates behind the same IP address. This means, that it does not send the target hostname inside the SSL handshake and thus the server has only the target IP address to decide which certificate it should use and just uses the default certificate for the IP - which is probably the wrong one.

AsyncHttpClient and org.apache.http.client fails on SSL site while standard Android method works well

There was recently certificate change on staging servers of my app. The server passes Qualys SSL test with grade A- ("The server does not support Forward Secrecy with the reference browsers. Grade reduced to A-") so I should be able to connect via https without adding any certs to my app, keystore or whatever. Indeed, the standard Android connection method works well (http://developer.android.com/training/basics/network-ops/connecting.html).
The problem is, I am using android-async-http all over the code, which uses org.apache.http.client. And that returns javax.net.ssl.SSLPeerUnverifiedException: No peer certificate when I connect to the site!
I can't really change the connection method in current circumstances. I'd like to stay with android-async-http and connect to my site without bypassing the SSL security.
Any tips? Some additional settings to android-async-http? Or maybe altering android-async-http source code would help?
I encountered a same problem 6 months back.
I think you will be able to solve it by :
MySSLSocketFactory extends SSLSocketFactory
Then u need to use this Class where you are creating an instace of HTTPClient and pass some parameters...
I think the link below would be helpful. If it doesn't help then i can share concrete code later...
https://stackoverflow.com/a/13812958/1386533

Why does android get the wrong ssl certificate? (two domains, one server)

I have two domains: foo.net and bar.com. They both have SSL certificates, and they work well in all desktop and mobile browsers. They are hosted on the same server configured with nginx.
However, when I make a request to a domain from within a native android app, it somehow gets the certificate from the wrong domain! This results in an IO Exception:
request = new HttpPost("https://foo.net/api/v1/baz");
request.setHeader("Authorization", "user:pass");
response = httpClient.execute(request);
...
javax.net.ssl.SSLException: hostname in certificate didn't match: <foo.net> != <bar.com> OR <bar.com> OR <www.bar.com>
What would cause android/java to try using the certificate from bar.com when every other measure seems to indicate that the server is correctly configured? Nothing appears in the nginx access or error log. There is no mention of bar.com anywhere in my android project.
Edit: I'm not sure why, but it appears that the server is using the certificate for bar.com for the server IP https://198.245.xx.xxx
The most likely cause for this problem is that the server uses Server Name Indication to choose which certificate to send. If the client doesn't support SNI, the server cannot choose which certificate to send during the SSL/TLS handshake (before any HTTP traffic is sent). SNI is required when you want to use multiple certificates on the same IP address and port, but not all clients support it (notoriously, IE on any version of Windows XP, and a number of mobile browsers).
You're also visibly using the Apache HTTP Client library (not HttpsURLConnection, for which there can be SNI support with some Android versions.
Support for SNI in the Apache HTTP Client library is quite recent, and certainly hasn't made it into the Android stack.
You may find the workaround described in this article useful (although it seems only to work for Android 4.2+).
Another two options would be:
to use a distinct IP address for each host (so as not to need SNI), if you're in control of server, or
to use another HTTP Client library (e.g. HttpsURLConnection).
A solution for Apache, more like a trick:
the SSL certificates are loaded based on the vhost name from /etc/apache2/sites-enabled. So, to trick that check make sure the problematic certificate is loaded first (remember that the vhosts are loaded by name).
It looks like the certificate of foo.net is misconfigured, and is using the same hostname as bar.com
Try to run an online certificate validation tool, like https://www.digicert.com/help/ on foo.net, just to be sure.
I think that you need to regenerate the certificate of foo.net with the right hostname, or reconfigure ngix to make sure that nginx serve the right certificate for the right host.

Android ssl connection using HttpsURLConnection and verifying hostname using .pem files?

In android app I am developing I need to make connection to https server.
Client has provided me with 2 files mycert.pem and mykey.pem, which I think is certificate and public keystrore of server.
I need to make secure connection using HttpsURLConnection and verify host name of server to avoid man in middle attack. I have little understanding about making https connection and cryptography terms. Most of tutorial I came across uses HttpClient and they trust all host. Can someone point me in right direction how to use .pem files to make a secure https connection using HttpsURLConnection and verify hostname.
Thanks in advance.
OK done by using following
httpsConn.setHostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
I am using BROWSER_COMPATIBLE_HOSTNAME_VERIFIER, I hope it works well.

Categories

Resources