Ancla de confianza no encontrada para la conexión SSL de Android

Estoy tratando de conectarme a un cuadro de IIS6 que ejecuta un certificado godaddy de 256 bits SSL y recibo el error:

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 

He estado tratando de determinar qué podría estar causando eso, pero dibujando espacios en blanco en este momento.

Así es como me estoy conectando:

 HttpsURLConnection conn; conn = (HttpsURLConnection) (new URL(mURL)).openConnection(); conn.setConnectTimeout(20000); conn.setDoInput(true); conn.setDoOutput(true); conn.connect(); String tempString = toString(conn.getInputStream()); 

¡La solución de @Chrispix es peligrosa! ¡Confiar en todos los certificados permite a cualquier persona atacar a un hombre en el medio! ¡Simplemente envíe CUALQUIER certificado al cliente y lo aceptará!

Agregue su (s) certificado (s) a un administrador de confianza personalizado como se describe en esta publicación: Confiar en todos los certificados que usan HttpClient a través de HTTPS

Aunque es un poco más complejo establecer una conexión segura con un certificado personalizado, le brindará la seguridad de encriptación ssl deseada sin el peligro de un hombre en el ataque medio.

Contrariamente a la respuesta aceptada , no necesitas un administrador de confianza personalizado, ¡necesitas arreglar la configuración de tu servidor!

Me topo con el mismo problema al conectarme a un servidor Apache con un certificado dynadot / alphassl incorrectamente instalado. Me estoy conectando usando HttpsUrlConnection (Java / Android), que estaba lanzando –

 javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 

El problema real es una configuración incorrecta del servidor, pruébelo con http://www.digicert.com/help/ o similar, e incluso le dirá la solución:

“El certificado no está firmado por una autoridad de confianza (verificando con el almacén raíz de Mozilla). Si compró el certificado a una autoridad confiable, probablemente solo necesite instalar uno o más certificados Intermedios . Póngase en contacto con su proveedor de certificados para que lo haga. plataforma de servidor “.

También puede verificar el certificado con openssl:

openssl s_client -debug -connect www.thedomaintocheck.com:443

Probablemente verás:

Verify return code: 21 (unable to verify the first certificate)

y, antes en el resultado:

 depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com verify error:num=20:unable to get local issuer certificate verify return:1 depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com verify error:num=27:certificate not trusted verify return:1 depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com verify error:num=21:unable to verify the first certificate` 

La cadena de certificados solo contendrá 1 elemento (su certificado):

 Certificate chain 0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com i:/O=AlphaSSL/CN=AlphaSSL CA - G2 

… pero debería hacer referencia a las autoridades de firma en una cadena que vuelva a ser una en la que confíe Android (Verisign, GlobalSign, etc.):

 Certificate chain 0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com i:/O=AlphaSSL/CN=AlphaSSL CA - G2 1 s:/O=AlphaSSL/CN=AlphaSSL CA - G2 i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA 2 s:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA 

Las instrucciones (y los certificados intermedios) para configurar su servidor las proporciona generalmente la autoridad que emitió su certificado, por ejemplo: http://www.alphassl.com/support/install-root-certificate.html

Después de instalar los certificados intermedios proporcionados por el emisor de mi certificado, ahora no tengo errores al conectarme usando HttpsUrlConnection.

Puede confiar en un certificado particular en tiempo de ejecución.
Simplemente descárguelo del servidor, coloque los activos y cargue de esta manera con ssl-utils-android :

 OkHttpClient client = new OkHttpClient(); SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer"); client.setSslSocketFactory(sslContext.getSocketFactory()); 

En el ejemplo anterior utilicé OkHttpClient pero SSLContext se puede usar con cualquier cliente en Java.

Si usted tiene alguna pregunta no dude en preguntar. Soy el autor de esta pequeña biblioteca.

Actualización basada en la última documentación de Android (marzo de 2017):

Cuando obtiene este tipo de error:

 javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:374) at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209) at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478) at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433) at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290) at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240) at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282) at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177) at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271) 

el problema podría ser uno de los siguientes:

  1. La CA que emitió el certificado del servidor era desconocida
  2. El certificado del servidor no fue firmado por una CA, pero fue auto-firmado
  3. A la configuración del servidor le falta una CA intermedia

La solución es enseñar a HttpsURLConnection a confiar en un conjunto específico de CA. ¿Cómo? Por favor, consulte https://developer.android.com/training/articles/security-ssl.html#CommonProblems

Otros que utilizan AsyncHTTPClient de la biblioteca com.loopj.android:android-async-http , compruebe la configuración AsyncHttpClient para usar HTTPS .

En respuesta a una publicación muy antigua. Pero tal vez ayudará a un novato y si no funciona lo anterior.

Explicación: Sé que nadie quiere una mierda de explicación; más bien la solución. Pero en un trazador de líneas, estás intentando acceder a un servicio desde tu máquina local a una máquina remota que no confía en tu máquina. Usted solicita obtener la confianza del servidor remoto.

Solución: la siguiente solución asume que usted tiene las siguientes condiciones cumplidas

  1. Intentando acceder a una API remota desde su máquina local.
  2. Estás comstackndo para la aplicación de Android
  3. Su servidor remoto está bajo filtrado de proxy (usted usa el proxy en la configuración de su navegador para acceder al servicio de API remota, por lo general un servidor de transición o de desarrollo)
  4. Estás probando en un dispositivo real

Pasos:

Necesitas un archivo de extensión .keystore para registrar tu aplicación. Si no sabe cómo crear el archivo .keystore; a continuación, siga junto con la siguiente sección Crear archivo .keystore o salte a la siguiente sección Firmar archivo apk

Crear archivo .keystore

Abra Android Studio. Haz clic en el menú superior Crear> Generar APK firmado. En la siguiente ventana, haga clic en el botón Crear nuevo … En la nueva ventana, ingrese datos en todos los campos. Recuerde que los dos campos de Contraseña que recomiendo deben tener la misma contraseña; no use una contraseña diferente; y también recuerde la ruta de guardado en la parte superior del campo Ruta del almacén de claves:. Después de ingresar todo el campo, haga clic en el botón Aceptar.

Firma del archivo apk

Ahora debe comstackr una aplicación firmada con el archivo .keystore que acaba de crear. Sigue estos pasos

  1. Build> Clean Project, espere hasta que termine de limpiar
  2. Crear> Generar APK firmado
  3. Haga clic en el botón Choose existing...
  4. Seleccione el archivo .keystore que acabamos de crear en la sección Crear archivo .keystore
  5. Ingrese la misma contraseña que creó al crear en la sección Crear archivo .keystore . Use la misma contraseña para los campos Key store password y Key password . También ingrese el alias
  6. Haga clic en el botón Siguiente
  7. En la siguiente pantalla; que puede ser diferente en función de su configuración en archivos build.gradle , debe seleccionar Build Types and Flavors .
  8. Para los Build Types elija la release del menú desplegable
  9. Para Flavors sin embargo, dependerá de su configuración en el archivo build.gradle . Elija la staging en staging desde este campo. Utilicé la siguiente configuración en build.gradle , puede usar la misma que la mía, pero asegúrese de cambiar la applicationId por el nombre de su paquete

    productFlavors { staging { applicationId "com.yourapplication.package" manifestPlaceholders = [icon: "@drawable/ic_launcher"] buildConfigField "boolean", "CATALYST_DEBUG", "true" buildConfigField "boolean", "ALLOW_INVALID_CERTIFICATE", "true" } production { buildConfigField "boolean", "CATALYST_DEBUG", "false" buildConfigField "boolean", "ALLOW_INVALID_CERTIFICATE", "false" } }

  10. Haga clic en las dos casillas de verificación de Signature Versions y haga clic en el botón Finish .

Casi allí:

Todo el trabajo duro está hecho, ahora es el movimiento de la verdad. Para acceder al servidor de transición respaldado por el proxy, debe realizar algunas configuraciones en sus dispositivos Android de prueba reales.

Configuración Proxy en dispositivo Android:

  1. Haga clic en Configuración en el teléfono Android y luego en wi-fi
  2. Mantenga presionado el wifi conectado y seleccione Modify network
  3. Haga clic en Advanced options si no puede ver el campo Proxy Hostname
  4. En el Proxy Hostname ingrese la IP del host o el nombre que desea conectar. Un servidor de stg.api.mygoodcompany.com típico se llamará stg.api.mygoodcompany.com
  5. Para el puerto ingrese el número de puerto de cuatro dígitos, por ejemplo 9502
  6. Presiona el botón Save

Una última parada:

Recuerde que hemos generado el archivo apk firmado en la sección Firmar Archivo APK . Ahora es el momento de instalar ese archivo APK.

  1. Abra una terminal y cambie a la carpeta de archivos apk firmada
  2. Conecte su dispositivo Android a su máquina
  3. Elimina cualquier archivo apk instalado previamente del dispositivo Android
  4. Ejecute adb install name of the apk file
  5. Si por algún motivo el comando anterior vuelve con el adb command not found . Ingrese la ruta completa como C:\Users\shah\AppData\Local\Android\sdk\platform-tools\adb.exe name of the apk file install name of the apk file

Espero que el problema pueda ser resuelto. Si no, por favor déjame un comentario.

Salam!

El mensaje de error que estaba recibiendo era similar, pero la razón era que el certificado autofirmado había expirado. Cuando se intentó el cliente de openssl, me dio la razón que se pasó por alto cuando estaba revisando el diálogo de certificado de Firefox.

Entonces, en general, si el certificado está allí en el almacén de claves y es “VÁLIDO”, este error se activará.

Tuve el mismo problema al conectarme desde el cliente de Android al servidor de Kurento. El servidor Kurento usa certificados jks, así que tuve que convertir el pem en él. Como entrada para la conversión, utilicé el archivo cert.pem y condujo a tales errores. Pero si usa fullchain.pem en lugar de cert.pem , todo está bien.

Tuve el mismo problema. Lo que encontré fue que el archivo .crt del certificado proporcioné falta un certificado intermedio. Así que le pregunté a todos los archivos .crt de mi administrador de servidor, luego los concaténelos en orden inverso.

Ex. 1. Root.crt 2. Inter.crt 3. myCrt.crt

en Windows ejecuté copia Inter.crt + Root.crt newCertificate.crt

(Aquí ignoré myCrt.crt)

Luego proporcioné el archivo newCertificate.crt en el código a través de inputstream. Trabajo hecho.

En los teléfonos Gingerbread, siempre obtengo este error: Trust Anchor not found for Android SSL Connection , incluso si configuro para confiar en mi certificado.

Aquí está el código que uso (en lenguaje Scala):

 object Security { private def createCtxSsl(ctx: Context) = { val cer = { val is = ctx.getAssets.open("mycertificate.crt") try CertificateFactory.getInstance("X.509").generateCertificate(is) finally is.close() } val key = KeyStore.getInstance(KeyStore.getDefaultType) key.load(null, null) key.setCertificateEntry("ca", cer) val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm) tmf.init(key) val c = SSLContext.getInstance("TLS") c.init(null, tmf.getTrustManagers, null) c } def prepare(url: HttpURLConnection)(implicit ctx: Context) { url match { case https: HttpsURLConnection ⇒ val cSsl = ctxSsl match { case None ⇒ val res = createCtxSsl(ctx) ctxSsl = Some(res) res case Some(c) ⇒ c } https.setSSLSocketFactory(cSsl.getSocketFactory) case _ ⇒ } } def noSecurity(url: HttpURLConnection) { url match { case https: HttpsURLConnection ⇒ https.setHostnameVerifier(new HostnameVerifier { override def verify(hostname: String, session: SSLSession) = true }) case _ ⇒ } } } 

y aquí está el código de conexión:

 def connect(securize: HttpURLConnection ⇒ Unit) { val conn = url.openConnection().asInstanceOf[HttpURLConnection] securize(conn) conn.connect(); .... } try { connect(Security.prepare) } catch { case ex: SSLHandshakeException /*if ex.getMessage != null && ex.getMessage.contains("Trust anchor for certification path not found")*/ ⇒ connect(Security.noSecurity) } 

Básicamente, me configuro para confiar en mi certificado personalizado. Si eso falla, deshabilito la seguridad. Esta no es la mejor opción, pero la única opción que conozco es con teléfonos viejos y defectuosos.

Este código de muestra, se puede traducir fácilmente a Java.

En mi caso, esto estaba sucediendo después de la actualización a Android 8.0. El certificado autofirmado en el que se estableció que confiaba Android utilizaba el algoritmo de firma SHA1withRSA. El cambio a un nuevo certificado, utilizando el algoritmo de firma SHA256withRSA solucionó el problema.

El error de anclaje de Confianza puede ocurrir por muchas razones. Para mí fue simplemente que estaba tratando de acceder a https://example.com/ lugar de https://www.example.com/ .

Así que es posible que desee verificar sus URL antes de comenzar a construir su propio Administrador de confianza (como yo hice).

 **Set proper alias name** CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509","BC"); X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(derInputStream); String alias = cert.getSubjectX500Principal().getName(); KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null); trustStore.setCertificateEntry(alias, cert);