6

I'm developing an Android App which sends some HTTPS requests to our own Webserver (Linux, Nginx, SSL zertificate from "Let's Encrypt").

The requests worked fine on my test devices (Android 4.2.2 & Android 6.0.1), but on another device (5.1.1) the request threw the Exception:

Cannot verify hostname [my_domain]

Looking at the certificate in my browser, it seems to work fine, using the following connection:

TLS 1.2 AES_128_GCM ECDHE_RSA

After searching the web for any help, I finally tried to apply a custom SSLSocketFactory, which forces the client to use the Cipher Suite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (which has been used by my other test devices, at which the request worked).

Long story short: The request then did work on any device, which indicates that it's the clients fault that the connection hasn't been successful.

So now to my questions:

  • Why does the SSL verifying work on some Android devices, but on some not?

  • Why does the Exception say that the hostname couldn't be verified, while the certificate is valid and the hostname stated in the certificate is the right one?

  • Is it bad to bind the requests to one specific cipher suite? (Looking at those lists, the given cipher suite should be available on all needed Android devices (4.1.0 and higher))

I'm quite a newby in SSL and am looking forward to any answer that could help me to understand this.

2 Answers2

2

Some background on TLS (aka SSL) - When you try to establish a secure connection from your client to the server the server will send the client its certificate to prove its identity to the client, along with a list of ciphersuites that it supports. The client verifies the identity by making sure the domain it is connecting to is the domain stated in the certificate, and that the certificate is signed by a valid certificate authority. After this is done the client and server establish some shared secret from which to derive keys and also agree on a ciphersuite.

You may notice above that ciphersuites (e.g. TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) are negotiated after the servers identity is established. This means that if there was a problem verifying the hostname it would happen when the the server sends the client its certificate, not when ciphersuites are negotiated. In other words this error should not be linked to the ciphersuite that the server and the client agree on, since it would happen before a ciphersuite is ever agreed upon.

My hunch is that this may be a misleading exception message being given to you by the SSL library being used on Android. I am not familiar with what ciphersuites come with SSL libraries on Android 5 "out of the box" so to speak, but perhaps when the server sends the client it's list of supported ciphers, the client does not see any ciphers that it supports and this cascades to some misleading exception logic. I'd suggest looking at what ciphersuites your server is configured to support and also look at the documentation for Android 5 regarding supported ciphersuites. One thing that seems to be true given what you stated is that your certificate is not the issue here.

puzzlepalace
  • 681
  • 3
  • 11
1
  • CA which is signing the certificate is not the some android certificate stores, so it does not validate. See for some ways how to update it
  • certificate is deemed valid only if full trust path (your_cert -> intermediate_CA1 -> intermediate_CA2.. -> root CA) can be established (there can be 0 or more intermediate CAs, but root CA must be present in that android version certificate store). You should check for any problems on the server side (like not sending intermediate certs, for example) with ssllabs (aim for "A" and no orange/red warnings) and/or htbridge. Note that devices do cache intermediate certs, so your app might have worked even without your changing the cipher. Or it might be specific cipher is buggy in that android version.
  • it is bad. Recommendations change from time to time, and not all people will update their apps all the time. You should leave it to automatics. If best SSL cipher security is wanted, it should be recommended/required automatically on the server side, not on the client. It would also help with varying levels of existing support depending on android versions. In short: you should only change preferred cipher order on your server, and on android app use defaults.
Matija Nalis
  • 2,115
  • 12
  • 18