La instalación del certificado autofirmado afirma tener éxito, pero Android actúa como si el certificado no estuviera allí

Estoy intentando instalar el certificado autofirmado para mi servidor web en Android 4.3. Tengo el archivo .crt en la raíz de la tarjeta SD (que en realidad se emula porque no tengo una tarjeta SD en la ranura).

Para instalar el certificado, voy a Configuración -> General -> Seguridad -> Almacenamiento de credenciales -> Instalar desde el almacenamiento del dispositivo.

Aparece un cuadro de diálogo que muestra el nombre del certificado (el nombre de archivo menos la extensión .crt) que puedo modificar (pero no lo hago), un menú desplegable "usado para" con "VPN y aplicaciones" seleccionado y texto en la parte inferior del cuadro de diálogo que informa "El paquete contiene: un certificado de usuario". Todo se ve bien, así que hago clic en "Aceptar". El cuadro de diálogo desaparece y aparece un mensaje emergente con "[nombre] instalado".

Sin embargo, si voy inmediatamente a "Credenciales de confianza y selecciono "Usuario", ¡no hay nada allí! El nuevo certificado tampoco está en "Sistema", pero no lo esperaría allí. Si voy a un navegador después de esto e intento ir a mi sitio web, sigo recibiendo la advertencia de que el certificado del sitio no es de confianza. También he intentado reiniciar, pero no hace ninguna diferencia.

¿Qué estoy haciendo mal? La falta total de mensajes de error no es útil. ¿Es posible que mi certificado esté en un formato incorrecto? He intentado usar el archivo .crt en el directorio ssl del servidor y he intentado convertirlo al formato DER.

Actualización: leí en alguna parte que Android requiere que los certificados estén en formato p12, así que convertí el certificado Apache2 a p12 usando el siguiente comando:

openssl pkcs12 -export -inkey server.key -in server.crt -out ~/server.p12

Luego repetí los pasos anteriores, obtuve el mismo mensaje de éxito y luego procedí a no ver el certificado en las credenciales de usuario y sigo recibiendo el error de certificado no confiable del navegador móvil.

Respuestas (1)

Tuve el mismo problema para que Android realmente instalara el certificado, hasta que encontré este sitio que describe un método que funcionó para mí. Se reduce a los siguientes pasos:

  1. Cree una clave privada y un certificado x509 público con extensiones v3_req y habilitado como CA:

    sudo openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout /etc/ssl/private/my_site.key -out /etc/ssl/certs/my_site.crt -reqexts v3_req -extensions v3_ca

  2. Convierta el certificado al formato DER, que es entendido por Android:

    sudo openssl x509 -in /etc/ssl/certs/my_site.crt -outform der -out my_site.der.crt

  3. Use cualquier método para obtener el my_site.der.crtarchivo en su dispositivo Android: me resultó fácil tener el archivo alojado en mi servidor web y descargarlo a través del navegador de Android, que luego le permite instalarlo automáticamente.

Aunque me hubiera gustado dividir el paso 1 en dos (1a. generación de clave privada y 1b. generación de certificado público), no invertí mucho tiempo investigando cómo hacerlo. Por favor, hágamelo saber en un comentario si encontró una manera que funcione, gracias.

(En lugar de agregar un comentario, siento que esto realmente pertenece como parte de la respuesta para referencia futura, así que lo estoy editando. --Michael)

En lugar de crear un certificado habilitado como CA, creé una CA autofirmada y luego volví a firmar mi clave/csr existente con la nueva CA. Luego agregué la CA autofirmada a Android y ¡listo! ¡Funcionó!

Generación de la CA autofirmada:

openssl genrsa -out rootCA.key 4096
openssl req -x509 -new -nodes -key rootCA.key -days 3650 -out rootCA.pem

Volver a firmar un CSR existente que tenía desde la creación de la clave desde el

openssl x509 -req -in existing.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out existing.crt -days 3649

Ahora, usando una forma modificada de su segundo comando, convertí el certificado CA en forma DER:

openssl x509 -in /etc/apache2/ssl/rootCA.pem -outform der -out ~/rootCA.der.crt

Lo mejor de esto es que cualquier certificado adicional que no sea de confianza que ahora se vuelva a firmar con la nueva CA autofirmada ahora será confiable en cualquier dispositivo que tenga instalada la nueva CA sin necesidad de instalar nada más. Esto no resuelve exactamente el problema de confiar en sitios sobre los que no tiene control, pero podría facilitarlo si tiene alguna influencia sobre (digamos) su departamento de TI para un servidor interno o algo así.

Ya tengo el certificado que necesito instalar, así que probé el paso 2 y aún no aparece en Credenciales de confianza del usuario después de que afirma que la instalación se realizó correctamente, y Chrome aún muestra el error "sitio no confiable" después de reiniciar.
¿Podría haber algo sobre la extensión v3_req y habilitada como CA que se requiere que el certificado tenga para que Android lo use? Si es así, ¿hay algún comando que pueda usar para tomar un certificado existente y agregarle esa información, ya que no tengo control sobre todos los certificados que quiero instalar?
Para responder a la primera mitad de mi pregunta anterior, leí la página que había vinculado y parece que el problema es que Android se niega a instalar certificados autofirmados (pero no CA autofirmadas). Esto parece no estar documentado, y el hecho de que Android pretenda instalarlo lo empeora aún más. Pero la pregunta sigue siendo, si tengo un certificado autofirmado sobre el que no tengo control, ¿hay alguna forma de "CA"-ificarlo para poder instalarlo?
@Michael, es por eso que dije en mi respuesta que me gustaría dividir el paso 1 para que pueda usarse para certificados ya existentes. Como solo lo necesitaba para mi propio servidor, tuve la suerte de poder seguir los pasos tal como están. Pero estoy totalmente de acuerdo contigo, este es uno de los problemas realmente desagradables de Android, especialmente porque no parece haber ninguna documentación clara al respecto... Pasé muchas horas buscando y probando hasta que encontré que Enlace.
@Espero que no le importe, voy a editar su respuesta para incluir mi solución, en lugar de incluirla en los comentarios, ya que realmente pertenece como parte de la respuesta.
+1 No me importa en absoluto, porque permitirá a los futuros lectores volver a firmar certificados adicionales. ¡Gracias por investigar y encontrar esta mejora significativa! Podría editar la respuesta ligeramente para mayor claridad más adelante.
No entiendo cómo se genera la solicitud de firma existente.csr. Creo que este es el último punto que falta para un tutorial completo paso a paso.
Ya no funciona en Android 4.4. Una vez más, reclamando éxito incluso diciendo que el certificado está instalado en intentos repetidos, pero no se encuentra en ninguna parte.
@wie5Ooma: estoy usando el certificado que creé a través del primer método (pasos etiquetados 1,2,3 arriba) en mi Android 4.4.4 (Cyanogenmod). Se queja al inicio de que "su dispositivo está siendo monitoreado", pero aparte de eso, funciona bien.
@FriendFX Mi Android 4.4.2 (no rooteado) pretende importar el certificado como dije antes, pero no lo almacena. CADroid se niega a importar el certificado y se queja de la identidad en el campo CN. Estoy usando la dirección IP en el campo CN que podría contribuir a esto.
@wie5Ooma Mi 4.4.4 tampoco está rooteado. Sugeriría investigar el problema del campo CN y, si eso no ayuda, eche un vistazo a este sitio (que es de donde obtuve la información para esta respuesta), tal vez haya algún caso de esquina que me haya perdido. ¡Haganos saber como va!
Veo que no respondí a esto. Resolví el problema. CAdroid es simplemente estúpido e intenta importar el certificado del servidor, no el certificado de CA, así que lo importé manualmente.
Después de probar MIL cosas... Lo que faltaba eran las extensiones. Entonces, crear el certificado y la clave usando -reqexts v3_req -extensions v3_cafinalmente funcionó. Al menos 6 horas. Lo juro. ¡¡Gracias!!
El comentario anterior @cguenther, pero "Volver a firmar un CSR existente que tenía desde la creación de la clave de" es confuso ya que no se mencionan las instrucciones para crear un csr existente. Sin embargo, puede crearlo a partir de archivos existentes.crt y existentes.key usando "openssl x509 -x509toreq -in my_site.crt -outexistent.csr -signkey my_site.key"