SSL error with Android

I have a very specific problem with SSL on my Android. If I try to visit a specific website using code, I get the following error:

SSL handshake failure: Failure in SSL library, usually a protocol error error:140773F2:SSL routines:SSL23_GET_SERVER_HELLO: sslv3 alert unexpected message (external/openssl/ssl/s23_cInt.c:500 0xaf076228:0x00000000) 

I get this regardless of the build ... I tried this on API levels 1.5, 1.6, 2.2 and 4.0 and got the same result every time.

After some troubleshooting, I tried to visit the website through a browser and I received the following error:

 Data connectivity problem A secure connection could not be established. 

Here's what though ... the website opens perfectly in Windows browsers (tested on Firefox, IE and Chrome). It also works great on iOS devices that use the same web kit as Android, which is strange. The website also works without problems in the Opera Mini browser.

Here is the website.

I tried workarounds by adding a client certificate to the keystore and ignoring invalid client certificates without any results. However, it seems that the certificate itself is not a problem.

I'm at a dead end. Can anyone give any guidance as to how I can make this work?

+6
source share
3 answers

How do you access this site? Via the Android browser? WebView? Or HttpClient / HTTPSURLConnection? It seems to only respond to SSL3, you need to get it to use it.

+2
source

I found a solution (thanks to Nikolai for pointing me in the right direction).

The problem was two-fold: one, it returned a site certificate that Android did not like, and two, it only had SSLv3 (and not TLS).

Here is my solution. First I had to create my own factory class socket:

 public class MySSLSocketFactory extends SSLSocketFactory { SSLContext sslContext = SSLContext.getInstance("SSLv3"); public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { super(truststore); TrustManager tm = 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.init(null, new TrustManager[] { tm }, null); } @Override public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { SSLSocket S = (SSLSocket) sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); S.setEnabledProtocols(new String[] {"SSLv3"}); return S; } @Override public Socket createSocket() throws IOException { SSLSocket S = (SSLSocket) sslContext.getSocketFactory().createSocket(); S.setEnabledProtocols(new String[] {"SSLv3"}); return S; } 

}

Secondly, I had this custom HttpClient defined in my code:

 public HttpClient getNewHttpClient() { try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); MySSLSocketFactory sf = new MySSLSocketFactory(trustStore); sf.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); registry.register(new Scheme("https", sf, 443)); ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); return new DefaultHttpClient(ccm, params); } catch (Exception e) { return new DefaultHttpClient(); } } 

Third, I called the custom HttpClient and analyzed the results:

 public String test(String URIString) { HttpClient httpClient = getNewHttpClient(); String result = ""; URI uri; try { uri = new URI(URIString); } catch (URISyntaxException e1) { return "ERROR"; } HttpHost host = new HttpHost(uri.getHost(), 443, uri.getScheme()); HttpPost httppost = new HttpPost(uri.getPath()); try { HttpResponse response = httpClient.execute(host, httppost); BufferedReader reader = new BufferedReader( new InputStreamReader( response.getEntity().getContent() ) ); String line = null; while ((line = reader.readLine()) != null){ result += line + "\n"; } return result; } catch (ClientProtocolException e) { return "ERROR"; } catch (IOException e) { return "ERROR"; } } 
+4
source

Use this and call this method HttpsTrustManager.allowAllSSL ()

He solves the problem and its work for me.

Public class HttpsTrustManager implements X509TrustManager {

 private static TrustManager[] trustManagers; private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{}; @Override public void checkClientTrusted( java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { } @Override public void checkServerTrusted( java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { } public boolean isClientTrusted(X509Certificate[] chain) { return true; } public boolean isServerTrusted(X509Certificate[] chain) { return true; } @Override public X509Certificate[] getAcceptedIssuers() { return _AcceptedIssuers; } public static void allowAllSSL() { HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String arg0, SSLSession arg1) { return true; } }); SSLContext context = null; if (trustManagers == null) { trustManagers = new TrustManager[]{new HttpsTrustManager()}; } try { context = SSLContext.getInstance("TLS"); context.init(null, trustManagers, new SecureRandom()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } HttpsURLConnection.setDefaultSSLSocketFactory(context .getSocketFactory()); } 

}

-2
source

Source: https://habr.com/ru/post/918669/


All Articles