Autenticación de cliente SSL con certificado en Android

Estoy escribiendo una aplicación para Android que se conecta a un servidor para llamar a algunos servicios web. Este servidor utiliza un certificado auto-firmado para SSL y requiere un certificado de cliente para la autenticación.

Cuando me conecto al servidor con el navegador de Chrome de Android o con el navegador de safari de un Iphone funciona perfectamente. La conexión SSL se está estableciendo y la autenticación de certificados de cliente se realiza correctamente y se redirecciona a mis servicios web. Pero cuando me conecto con otros navegadores, como el navegador androide de acciones, delfín, etc, se traduce en un Network-Timeout.

También cuando me conecto con mi aplicación de Android me sale el siguiente error:

javax.net.ssl.SSLException: Read error: ssl=0x12746b8: I/O error during system call, Connection reset by peer at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_read(Native Method) at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:671) at libcore.io.Streams.readSingleByte(Streams.java:41) at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:655) at libcore.io.Streams.readAsciiLine(Streams.java:201) at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:544) 

He seguido el blog de chariotsolutions: http://chariotsolutions.com/blog/post/https-with-client-certificates-on/

También convertí el certificado del cliente al formato de BKS con GUI del portecle.

Aquí está mi código:

 private static final String USER_AGENT = "Mozilla/5.0 (Linux; U; Android 4.0.3; et-ee; GT-P5100 Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30"; .... @Override protected Object doInBackground(String... urlString) { .... URL url = new URL(urlString[0]); HttpsURLConnection urlConnection =(HttpsURLConnection)url.openConnection(); urlConnection.setSSLSocketFactory(getSSLContext().getSocketFactory()); urlConnection.addRequestProperty("User-Agent", USER_AGENT); urlConnection.setDoInput(true); urlConnection.connect(); .... } private SSLContext getSSLContext() throws CertificateException,IOException, KeyStoreException, NoSuchAlgorithmException,KeyManagementException, java.security.cert.CertificateException { CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream caRootInput = context.getAssets().open("MySSLCertificate_here.crt"); InputStream caClientAuth = context.getAssets().open("MyCientCertificate_here"); .... Certificate caRoot; caRoot = cf.generateCertificate(caRootInput); // KeyStore and KeyManager for Client Certificate KeyStore keystore_client = KeyStore.getInstance("BKS"); keystore_client.load(caClientAuth, "My_passWord_here".toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(keystore_client, "My_passWord_here".toCharArray()); KeyManager[] keyManagers = kmf.getKeyManagers(); // KeyStore and Trustmanager for SSL Certificate KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null, null); keyStore.setCertificateEntry("caRoot", caRoot); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(keyStore); SSLContext context = SSLContext.getInstance("TLSv1"); context.init(keyManagers, tmf.getTrustManagers(), null); return context; .... } 

Aviso : También tengo una opción de conectar al servidor sin autenticación del certificado del cliente (que resulta en una diversa URL) para los propósitos de la prueba. El código anterior en este caso es el mismo, pero sólo con context.init (null, tmf.getTrustManagers (), null) . Esto funciona perfectamente, estableciendo una conexión SSL y redirigiéndome a mis Webservices.

Lo que realmente me molesta es que todo funciona con Chrome y Safari en Iphone. Así que supongo que el problema sólo podría estar en mi código de Android?

¿Alguien tenía un problema similar y tiene una idea o quizás una solución a su?

¡Muchas gracias!

EDIT :

Olvidé mencionar, que también configuré un Administrador de cookies, que era necesario para la conexión SSL en primer lugar. (Configurado en MainActivity en onCreate ())

 // Required for SSL connection CookieHandler.setDefault(new CookieManager()); 

Sin eso, estaba recibiendo el mismo error al tratar de establecer una conexión SSL (sin certificado de cliente), pero lamentablemente no está ayudando con el cliente Cert también.

ACTUALIZACIÓN # 2

Con mucho Backgroundinformation de nelenkov.blogspot.de/2011/12/using-custom-certificate-trust-store-on.html (Gracias por este artículo gread @ Nikolay) y su aplicación Android Connectiontest en Github he encontrado algunas cosas interesantes.

El servidor está configurado para darme una cookie al conectar. Que para el Conncetion "funciona" si me conecto sin la autenticación de cliente en un paso anterior, de modo que en la segunda conexión (con autenticación de cliente) que sólo verifica que Cookie y dejarme pasar.

La segunda cosa que noté finalmente, el servidor me da un Nonce . Supongo que la conexión debe seguir que Redirigir automáticamente al devolver ese Nonce. Algunos Navegadores, como Firefox y el Navegador de Stock están deteniendo la conexión, (después de ser redirigido con el Responsecode 302) y finalmente detener con 404 resultando una URL como ..policy? Nonce = fno3i9Hsfn3uz. Entonces tengo que cargar manualmente esta URL para conseguir a través a los Webservices. Lamentablemente esto no funciona con mi aplicación de Android.

Supongo, este problema puede ser una configuración errónea en el serverside entonces?

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.