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

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.

Related

How to properly verify SSL certificate in using HttpURLConnection?

Recently JSSA (Japan Smartphone Security Association) issued the 2017 edition of their Android Application Secure Design/Secure Coding Guidebook in which they have given examples of communicating via HTTPS with trusted as well as private certificates. For trusted certificate the code is supposed to check for:
The server certificate is signed by a trusted third party certificate
authority
The period and other properties of the server certificate are valid
The server's host name matches the CN (Common Name) or SAN (Subject
Alternative Names) in the Subject field of the server certificate
The example code they have given for connecting to a secure server with trusted certificate is same as normal HTTP unsecured connection as below
.
.
URL url = new URL(strUrl);
response = (HttpURLConnection) url.openConnection();
response.setRequestMethod("GET");
response.connect();
checkResponse(response);
.
.
However, the sample given for private certificate connection seems to be a bit more elaborate and looks adequate for its intended purpose.
Expecting expert advice on the credibility of the sample code in securing the transaction, since they are not even using HttpsURLConnection, or any or all of the above mentioned validation goals seems to be left unaddressed as per the given sample code.
Thanks in advance.
PS: The document link for reference.
http://www.jssec.org/dl/android_securecoding_en.pdf

Secure WebSocket (WSS) with HTTPS localhost SSL certificate?

I am a little new to this whole WebSocket and SSL certificate.
So I have created my own WebSocket server on Android side and the website is the client. I was able to make it work with regular WebSocket (ws://) but not secure WebSocket (wss://) due to the fact that it requires SSL certificate.
My question is how can I get a SSL certificate? From what I've read, SSL certificate is based on a domain. I need it for localhost. I need it for something like this address:
wss://localhost:8080/ws/main
How can I go about getting a SSL certificate that will work with localhost.
Thank you for your time!
====================== EDIT =====================
Reason why I am doing this:
I have a Bluetooth service in my Android application that will be getting data from connected health bluetooth devices like Weight Scale and Blood Pressure machine. I have this part implemented already and I want to take this data and pass it to a website. WebSocket seemed easier because the user will have my application open and when they do their weight, it would automatically fill the field on the website with the weight from the Weight Scale. I hope I am making this clear.
To do this, I need to have a way to pass the weight or blood pressure values from Java (Android) to the website that loads within a WebView. So I thought WebSocket would the easiest way.
Please tell me if you think there is an easier way.
Also, I've already tried self-signed certificate and I get the following error:
I/X509Util: Failed to validate the certificate chain, error: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
OR
Exception=javax.net.ssl.SSLException: Error occured in delegated task:javax.net.ssl.SSLException: Not trusted server certificate
Thank you!!!
We faced a similar problem, our solution was to register a subdomain to one of our domains with an A record to 127.0.0.1 and get a certificate for that domain.
local.example.com -> A record to 127.0.0.1
SSL certificate requested for local.example.com
I'm afraid this answer is too late for you however, it can be helpful for others finding this article.

HTTPS url not encrypted

I'm using Charles proxy to fetch all the requests coming from my Android app to a webservice.
The thing is Charles shows me the complete request, meaning I can see the whole URL, headers and body so I can see www.example.com/rest/resource/param1/param2,
the JSON I send with it and also the authentication header.
After reading several posts like this and this one I thought the good part of working with the TLS was that one could only get the domain name from the URL, in this case www.example.com
To make sure it's not the client's fault, I requested the webservice resource with Retrofit and HttpsURLConnection and I could see the whole request both times.
I guess also the certificate is properly installed because it is shown in the browser every time an https request is made. Am I missing something else here or is this the normal behaviour?
So far I couldn't find a reason for this to happen so any help will be appreciated.
To debug with Charles proxy you must install a certificate on your browser (client).
With https the URL is encrypted.
But because you choose to use that proxy, your browser establish a secure connection to that proxy, and the proxy to the website. So, only 1) you, 2) the proxy 3)the website can decrypt the https traffic.
By installing a CA certificate on your browser, you allow the person detaining the corresponding private key (in your case, your proxy) to impersonate (so, decrypt with a MITM) any website.

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.

Categories

Resources