Autenticación de cliente SSL con certificado en Android

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

Cuando me conecto al servidor con el navegador Android Chrome o con el navegador Safari desde un iPhone, funciona perfectamente. La conexión SSL se está estableciendo y la autenticación del certificado del cliente está teniendo éxito y se está redirigiendo a mis servicios web. Pero cuando me conecto con otros navegadores, como el navegador de Android, Dolphin, etc., se produce un tiempo de espera de la red.

Además, cuando me conecto con mi aplicación de Android, aparece 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)

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

También convertí el Certificado de cliente al formato BKS con la interfaz gráfica de usuario de 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 la opción de conectarme al servidor sin autenticación de certificado de cliente (lo que da como resultado una URL diferente) para fines de prueba. El Código anterior en este caso es el mismo pero solo concontext.init (nulo, tmf.getTrustManagers (), nulo). Esto funciona perfectamente, establece una conexión SSL y me redirige a mis servicios web.

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

¿Alguien tuvo un problema similar y tiene una idea o tal vez una solución a la suya?

¡Muchas gracias!

EDITAR:

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

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

Sin eso, recibí el mismo error al intentar establecer una conexión SSL (sin el Certificado de cliente), pero lamentablemente no está ayudando con el Certificado de cliente también.

ACTUALIZACIÓN # 2

Con mucha información de fondo de nelenkov.blogspot.de/2011/12/using-custom-certificate-trust-store-on.html (Gracias por este artículo de lectura @ Nikolay) y su aplicación Android Connectiontest en Github, encontré algunas cosas interesantes.

El servidor está configurado para darme una cookie cuando se conecta. Eso para Conncetion "funciona" si me conecto sin autenticación de cliente en un paso anterior, de modo que en la segunda conexión (con autenticación de cliente) solo verifica esa cookie y me deja pasar.

Lo segundo que finalmente noté, el servidor me da unMientras tanto. Supongo que la conexión debería seguir ese redireccionamiento automáticamente al devolver ese Nonce. Algunos navegadores, como Firefox y el navegador estándar, están deteniendo la conexión (después de ser redirigidos con Responsecode 302) y finalmente se detienen con 404, lo que da como resultado una URL como ...policy? Nonce = fno3i9Hsfn3uz. Luego tengo que recargar manualmente esta URL para acceder a los servicios web. Lamentablemente, esto no funciona con mi aplicación de Android.

Supongo que este problema podría ser una configuración incorrecta en el lado del servidor.

Respuestas a la pregunta(0)

Su respuesta a la pregunta