Los siguientes pasos principales son necesarios para lograr una conexión segura de las Autoridades de certificación que la plataforma de Android no considera de confianza.
Como lo solicitaron muchos usuarios, he reflejado las partes más importantes de mi artículo de blog aquí:
- Tome todos los certificados requeridos (raíz y cualquier CA intermedia)
- Cree un almacén de claves con keytool y el proveedor BouncyCastle e importe los certificados
- Cargue el almacén de claves en su aplicación de Android y úselo para las conexiones seguras (recomiendo usar el HttpClient de Apache en lugar del estándar
java.net.ssl.HttpsURLConnection
(más fácil de entender, más eficiente)
Agarra los certs
Debe obtener todos los certificados que crean una cadena desde el certificado de punto final hasta la CA raíz. Esto significa que cualquier certificado de CA intermedio (si está presente) y también el certificado de CA raíz. No necesita obtener el certificado de punto final.
Crea el almacén de claves
Descargue el proveedor BouncyCastle y guárdelo en una ubicación conocida. Asegúrese también de que puede invocar el comando keytool (generalmente ubicado debajo de la carpeta bin de su instalación de JRE).
Ahora importe los certificados obtenidos (no importe el certificado de punto final) en un almacén de claves con formato BouncyCastle.
No lo probé, pero creo que el orden de importación de los certificados es importante. Esto significa, primero importe el certificado de CA intermedio más bajo y luego hasta el certificado de CA raíz.
Con el siguiente comando , se creará un nuevo almacén de claves (si aún no está presente) con la contraseña mysecret y se importará el certificado CA intermedio. También definí el proveedor BouncyCastle, donde se puede encontrar en mi sistema de archivos y el formato del almacén de claves. Ejecute este comando para cada certificado en la cadena.
keytool -importcert -v -trustcacerts -file "path_to_cert/interm_ca.cer" -alias IntermediateCA -keystore "res/raw/mykeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret
Verifique si los certificados se importaron correctamente en el almacén de claves:
keytool -list -keystore "res/raw/mykeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret
Debería dar salida a toda la cadena:
RootCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 24:77:D9:A8:91:D1:3B:FA:88:2D:C2:FF:F8:CD:33:93
IntermediateCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 98:0F:C3:F8:39:F7:D8:05:07:02:0D:E3:14:5B:29:43
Ahora puede copiar el almacén de claves como recurso sin procesar en su aplicación de Android en res/raw/
Usa el almacén de claves en tu aplicación
En primer lugar, tenemos que crear un HttpClient de Apache personalizado que use nuestro almacén de claves para conexiones HTTPS:
import org.apache.http.*
public class MyHttpClient extends DefaultHttpClient {
final Context context;
public MyHttpClient(Context context) {
this.context = context;
}
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// Register for port 443 our SSLSocketFactory with our keystore
// to the ConnectionManager
registry.register(new Scheme("https", newSslSocketFactory(), 443));
return new SingleClientConnManager(getParams(), registry);
}
private SSLSocketFactory newSslSocketFactory() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore trusted = KeyStore.getInstance("BKS");
// Get the raw resource, which contains the keystore with
// your trusted certificates (root and any intermediate certs)
InputStream in = context.getResources().openRawResource(R.raw.mykeystore);
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
trusted.load(in, "mysecret".toCharArray());
} finally {
in.close();
}
// Pass the keystore to the SSLSocketFactory. The factory is responsible
// for the verification of the server certificate.
SSLSocketFactory sf = new SSLSocketFactory(trusted);
// Hostname verification from certificate
// http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
}
Hemos creado nuestro HttpClient personalizado, ahora podemos usarlo para conexiones seguras. Por ejemplo, cuando hacemos una llamada GET a un recurso REST:
// Instantiate the custom HttpClient
DefaultHttpClient client = new MyHttpClient(getApplicationContext());
HttpGet get = new HttpGet("https://www.mydomain.ch/rest/contacts/23");
// Execute the GET call and obtain the response
HttpResponse getResponse = client.execute(get);
HttpEntity responseEntity = getResponse.getEntity();
Eso es ;)