¿Cómo instalar un certificado CA de confianza en un dispositivo Android?

134

He creado mi propio certificado de CA y ahora quiero instalarlo en mi dispositivo Android Froyo (HTC Desire Z), para que el dispositivo confíe en mi certificado.

Android almacena certificados de CA en su almacén de claves Java en /system/etc/security/cacerts.bks. Copié el archivo a mi computadora, agregué mi certificado usando portecle 1.5 y lo devolví al dispositivo.

Ahora, Android no parece recargar el archivo automáticamente. He leído en varias publicaciones de blog que necesito reiniciar el dispositivo. Al hacerlo, el archivo se sobrescribirá con el original nuevamente.

Mi siguiente intento fue instalar el certificado de la tarjeta SD copiándolo y usando la opción correspondiente del menú de configuración. El dispositivo me dice que el certificado se ha instalado, pero aparentemente no confía en el certificado. Además, cuando intento copiar el almacén de claves en mi computadora, todavía encuentro el stock originalcacerts.bks .

Entonces, ¿cuál es la forma correcta de instalar mi propio certificado de CA raíz en un dispositivo Android 2.2 como un certificado de confianza? ¿Hay alguna manera de hacerlo mediante programación?

Björn Marschollek
fuente
Puede asumir un teléfono rooteado aquí. :)
Björn Marschollek

Respuestas:

116

Antes de Android KitKat, debe rootear su dispositivo para instalar nuevos certificados.

Desde Android KitKat (4.0) hasta Nougat (7.0) es posible y fácil. Pude instalar el certificado Charles Web Debbuging Proxy en mi dispositivo no rooteado y detectar con éxito el tráfico SSL.

Extracto de http://wiki.cacert.org/FAQ/ImportRootCert

Antes de la versión de Android 4.0, con la versión de Android Gingerbread & Froyo, había un único archivo de solo lectura (/system/etc/security/cacerts.bks) que contenía el almacén de confianza con todos los certificados de CA ('sistema') confiables por defecto en Androide. Tanto las aplicaciones del sistema como todas las aplicaciones desarrolladas con el SDK de Android usan esto. Use estas instrucciones para instalar certificados CAcert en Android Gingerbread, Froyo, ...

A partir de Android 4.0 (Android ICS / 'Ice Cream Sandwich', Android 4.3 'Jelly Bean' y Android 4.4 'KitKat'), los certificados confiables del sistema están en la partición del sistema (solo lectura) en la carpeta '/ system / etc / seguridad / 'como archivos individuales. Sin embargo, los usuarios ahora pueden agregar fácilmente sus propios certificados de 'usuario' que se almacenarán en '/ data / misc / keychain / certs-Added'.

Los certificados instalados en el sistema se pueden administrar en el dispositivo Android en la sección Configuración -> Seguridad -> Certificados -> 'Sistema', mientras que los certificados de confianza del usuario se gestionan en la sección 'Usuario' allí. Cuando se utilizan certificados de confianza del usuario, Android obligará al usuario del dispositivo Android a implementar medidas de seguridad adicionales: el uso de un código PIN, un patrón de bloqueo o una contraseña para desbloquear el dispositivo son obligatorios cuando se utilizan certificados proporcionados por el usuario.

Instalar certificados de CAcert como certificados de "confianza del usuario" es muy fácil. La instalación de nuevos certificados como certificados de 'sistema confiable' requiere más trabajo (y requiere acceso de root), pero tiene la ventaja de evitar el requisito de bloqueo de pantalla de Android.

Desde Android N en adelante se vuelve un poco más difícil, vea este extracto del sitio web de proxy de Charles :

A partir de Android N, debe agregar la configuración a su aplicación para que confíe en los certificados SSL generados por Charles SSL Proxying. Esto significa que solo puedes usar SSL Proxying con aplicaciones que controlas.

Para configurar su aplicación para que confíe en Charles, debe agregar un archivo de configuración de seguridad de red a su aplicación. Este archivo puede anular el valor predeterminado del sistema, lo que permite que su aplicación confíe en los certificados de CA instalados por el usuario (por ejemplo, el Certificado Charles Root). Puede especificar que esto solo se aplique a las compilaciones de depuración de su aplicación, de modo que las compilaciones de producción usen el perfil de confianza predeterminado.

Agregue un archivo res / xml / network_security_config.xml a su aplicación:

<network-security-config>    
    <debug-overrides> 
        <trust-anchors> 
            <!-- Trust user added CAs while debuggable only -->
            <certificates src="user" /> 
        </trust-anchors>    
    </debug-overrides>  
</network-security-config>

Luego agregue una referencia a este archivo en el manifiesto de su aplicación, de la siguiente manera:

<?xml version="1.0" encoding="utf-8"?> 
<manifest>
    <application android:networkSecurityConfig="@xml/network_security_config">
    </application> 
</manifest>
Dean Wild
fuente
1
Mis archivos de certificado personalizados ( /system/etc/security/cacerts/*.0) no se retienen después de reiniciar / reiniciar AVD, por lo que esta solución no tuvo éxito.
fikr4n
@BornToCode interesante - Raramente uso AVD's, así que no estaba al tanto de esta limitación
Dean Wild
Veo la configuración debug-overrides, ¿eso significa que network_security_configsolo se trata de una variante de depuración? Si tengo otra variante como la variante UAT, ¿entonces esto no funcionará?
Isaac
1
@Isaac esto significa que se aplicará a cualquier variante donde debuggable = true
Dean Wild
1
@DeanWild: ¡muchas gracias! Traté de que esto funcionara para siempre y seguí obteniendo un "certificado SSL inválido" al depurar mi aplicación. Esta solución funcionó de maravilla para mi aplicación de Android que se ejecuta en Android 9 en un Samsung Note 8.
Dave Black,
43

Pasé mucho tiempo tratando de encontrar una respuesta a esto (necesito Android para ver los certificados StartSSL). Conclusión: Android 2.1 y 2.2 le permiten importar certificados, pero solo para usar con WiFi y VPN. No hay una interfaz de usuario para actualizar la lista de certificados raíz confiables, pero se está discutiendo sobre cómo agregar esa característica. No está claro si existe una solución confiable para actualizar y reemplazar manualmente el archivo cacerts.bks.

Detalles y enlaces: http://www.mcbsys.com/techblog/2010/12/android-certificates/ . En esa publicación, vea el enlace al error 11231 de Android: es posible que desee agregar su voto y consulta a ese error.

Mark Berry
fuente
3
Un desarrollador de Android respondió mi consulta re. actualizar cacerts.bks: "en todas las versiones, aunque sea la 2.3, se requiere una OTA para actualizar cacerts.bks en un teléfono no rooteado". code.google.com/p/android/issues/detail?id=11231#c25 . OTA = por aire, ¿verdad? ¿Podría ser esta la razón por la cual su teléfono sigue volviendo a los cacerts.bks de fábrica? Sin embargo, si TIENES acceso de root, parece que deberías poder descargar el código fuente, agregar tu certificado y luego construir cacerts.bks usando el script certimport.sh. android.git.kernel.org/?p=platform/libcore.git;a=tree;f=luni/… .
Mark Berry
Gracias. Obviamente, esta no era la respuesta que quería escuchar, pero parece ser la correcta. Esperaba que hubiera una manera de instalar un certificado sin actualizar todo el sistema. Por supuesto, puedo construir el nuevo cacerts.bks, con acceso de root, incluso puedo reemplazar el antiguo, pero vuelve a la versión original con cada reinicio. Sin reiniciar, Android parece negarse a volver a cargar el archivo de certificados de confianza.
Björn Marschollek
27
¿Qué pasa con la instalación de certificados de CA en plataformas 3.X y 4.X?
Alok Kulkarni
1
4.X en adelante: stackoverflow.com/questions/4461360/…
Dean Wild
16

Si necesita su certificado para conexiones HTTPS, puede agregar el archivo .bks como recurso sin procesar a su aplicación y extender DefaultHttpConnection para que sus certificados se usen para conexiones HTTPS.

public class MyHttpClient extends DefaultHttpClient {

    private Resources _resources;

    public MyHttpClient(Resources resources) {
        _resources = resources;
    }

    @Override
    protected ClientConnectionManager createClientConnectionManager() {
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory
            .getSocketFactory(), 80));
        if (_resources != null) {
            registry.register(new Scheme("https", newSslSocketFactory(), 443));
        } else {
            registry.register(new Scheme("https", SSLSocketFactory
                .getSocketFactory(), 443));
        }
        return new SingleClientConnManager(getParams(), registry);
    }

    private SSLSocketFactory newSslSocketFactory() {
        try {
            KeyStore trusted = KeyStore.getInstance("BKS");
            InputStream in = _resources.openRawResource(R.raw.mystore);
            try {
                trusted.load(in, "pwd".toCharArray());
            } finally {
                in.close();
            }
            return new SSLSocketFactory(trusted);
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}
Alexander Egger
fuente
Gracias por su respuesta. En realidad, necesito instalar el certificado de manera tal que cada aplicación en el dispositivo confíe en el certificado. El mismo problema también debería existir para algunas CA más pequeñas como CAcert, cuyos certificados no son confiables de manera predeterminada. ¿Cómo se instalan sus certificados?
Björn Marschollek
Intentó: Configuración -> Seguridad -> Instalar desde la tarjeta SD
Alexander Egger
También esto puede ser interesante: android.git.kernel.org/?p=platform/packages/apps/…
Alexander Egger
2
Tengo el mismo problema, tengo que cargar un certificado .PDX X509 usando la aplicación Adroid 2.3.3 y luego crear una conexión SSL. ¿Alguien puede ayudarme con el código comentado?
AndroidLearner
9

La guía vinculada aquí probablemente responderá la pregunta original sin la necesidad de programar un conector SSL personalizado.

Encontré una guía de instrucciones muy detallada sobre la importación de certificados raíz que realmente lo guía a través de la instalación de certificados de CA confiables en diferentes versiones de dispositivos Android (entre otros dispositivos).

Básicamente necesitarás:

  1. Descargue: el archivo cacerts.bks de su teléfono.

    adb pull /system/etc/security/cacerts.bks cacerts.bks

  2. Descargue el archivo .crt de la autoridad de certificación que desea permitir.

  3. Modifique el archivo cacerts.bks en su computadora usando el proveedor BouncyCastle

  4. Vuelva a cargar el archivo cacerts.bks en su teléfono y reinicie.

Aquí hay un paso a paso más detallado para actualizar los teléfonos Android anteriores: Cómo actualizar el almacén de claves de la autoridad del certificado de seguridad HTTPS en un dispositivo anterior a Android-4.0

RightHandedMonkey
fuente
5

Hay una solución MUCHO más fácil para esto que la publicada aquí, o en hilos relacionados. Si está utilizando una vista web (como yo), puede lograr esto ejecutando una función JAVASCRIPT dentro de ella. Si no está utilizando una vista web, es posible que desee crear una oculta para este propósito. Aquí hay una función que funciona en casi cualquier navegador (o webview) para iniciar la instalación de ca (generalmente a través del repositorio compartido de certificados de os, incluso en un Droid). Utiliza un buen truco con iFrames. Simplemente pase la url a un archivo .crt a esta función:

function installTrustedRootCert( rootCertUrl ){
    id = "rootCertInstaller";
    iframe = document.getElementById( id );
    if( iframe != null ) document.body.removeChild( iframe );
    iframe = document.createElement( "iframe" );
    iframe.id = id;
    iframe.style.display = "none";
    document.body.appendChild( iframe );
    iframe.src = rootCertUrl;
}

ACTUALIZAR:

El truco del iframe funciona en Droids con API 19 y versiones posteriores, pero las versiones anteriores de la vista web no funcionarán así. Sin embargo, la idea general todavía funciona: solo descargue / abra el archivo con una vista web y luego deje que el sistema operativo se haga cargo. Esta puede ser una solución más fácil y más universal (en el Java real ahora):

 public static void installTrustedRootCert( final String certAddress ){
     WebView certWebView = new WebView( instance_ );
     certWebView.loadUrl( certAddress );
 }

Tenga en cuenta que instancia_ es una referencia a la Actividad. Esto funciona perfectamente si conoce la URL del certificado. En mi caso, sin embargo, lo resuelvo dinámicamente con el software del lado del servidor. Tuve que agregar una buena cantidad de código adicional para interceptar una URL de redireccionamiento y llamar a esto de una manera que no causó un bloqueo basado en una complicación de enhebrado, pero no agregaré toda esa confusión aquí ...

BuvinJ
fuente
3

Lo que hice para poder usar los certificados startssl fue bastante fácil. (en mi teléfono rooteado)

Copié /system/etc/security/cacerts.bks en mi tarjeta sd

Http://www.startssl.com/certs/ca.crt y http://www.startssl.com/certs/sub.class1.server.ca.crt descargados

Fui a portecle.sourceforge.net y ejecuté portecle directamente desde la página web.

Abrí mi archivo cacerts.bks desde mi tarjeta sd (no ingresé nada cuando se me solicitó una contraseña)

Elija importar en portacle y abrir sub.class1.server.ca.crt, en mi caso, ya tenía el ca.crt, pero tal vez también necesite instalarlo.

Guarde el almacén de claves y lo copie baxck a /system/etc/security/cacerts.bks (hice una copia de seguridad de ese archivo primero por si acaso)

Reinicié mi teléfono y ahora puedo visitar mi sitio usando un certificado startssl sin errores.

Hans
fuente
¿Alguna idea de cómo volver a colocar el cacert.bks en un dispositivo NO rooteado?
Bob
1

Estos pasos me funcionaron:

  1. Instale la aplicación de Android Dory Certificate en su dispositivo móvil: https://play.google.com/store/apps/details?id=io.tempage.dorycert&hl=en_US
  2. Conecte el dispositivo móvil a la computadora portátil con un cable USB.
  3. Cree la carpeta raíz en la memoria interna del teléfono, copie el archivo del certificado en esa carpeta y desconecte el cable.
  4. Abra la aplicación de Android Dory Certificate, haga clic en el botón redondo [+] y seleccione la opción correcta Importar certificado de archivo.
  5. Seleccione el formato, proporcione un nombre (escribí lo mismo que el nombre del archivo), explore el archivo del certificado y haga clic en [Aceptar].
  6. Se enumerarán tres cartas. Ignoré la tarjeta que solo tenía el botón [SIGN CSR] y procedí a hacer clic en el botón [INSTALAR] en las otras dos tarjetas.
  7. Actualicé la aplicación web de PWA, no había abierto mi Chrome móvil (está alojado en un servidor web IIS local) y ¡listo! No hay mensaje de advertencia de cromo. La cerradura verde estaba allí. Estaba funcionando.

Alternativamente, encontré estas opciones que no tenía necesidad de probar yo mismo, pero parecía fácil de seguir:

Finalmente, puede no ser relevante pero, si está buscando crear y configurar un certificado autofirmado (con mkcert) para su aplicación PWA (sitio web) alojado en un servidor web IIS local, seguí esta página:

https://medium.com/@aweber01/locally-trusted-development-certificates-with-mkcert-and-iis-e09410d92031

Gracias y espero que ayude !! :)

Manuel Hernández
fuente
0

Aquí hay una solución alternativa que realmente agrega su certificado a la lista integrada de certificados predeterminados: Confiar en todos los certificados usando HttpClient sobre HTTPS

Sin embargo, solo funcionará para su aplicación. No hay forma de hacerlo programáticamente para todas las aplicaciones en el dispositivo de un usuario, ya que eso sería un riesgo de seguridad.

emmby
fuente