Trust Anchor no encontrado para la conexión SSL de Android

185

Estoy tratando de conectarme a una caja IIS6 que ejecuta un certificado SSL de 256 bits de godaddy, 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()); 
Chrispix
fuente

Respuestas:

78

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

Agregue sus certificados a un administrador de confianza personalizado como se describe en esta publicación: Confiar en todos los certificados usando HttpClient sobre HTTPS

Aunque es un poco más complejo establecer una conexión segura con un certificado personalizado, ¡le brindará la seguridad de cifrado SSL deseada sin el peligro del hombre en el medio del ataque!

Matthias B
fuente
1
Esto está bien para trabajar con un certificado autogenerado, pero para uno (como los OP) que tiene una cadena válida de regreso a las CA raíz, es solo una solución para un servidor mal configurado: vea mi respuesta.
Stevie
44
@Stevie Aceptar CADA certificado es solo una opción para una prueba de prueba de concepto, donde la conexión SSL no es la parte que desea probar. De lo contrario, no tiene que usar SSL si acepta todos los certificados, ya que la conexión no es segura.
Matthias B
1
Ah, lo siento, creo que hay un malentendido: ¡estoy completamente de acuerdo en que nadie debería aceptar cada certificado! :) Mi comentario fue con respecto a su segundo párrafo, la sugerencia de utilizar un administrador de confianza personalizado, que en mi humilde opinión debería ser una solución alternativa de último recurso en lugar de una solución recomendada.
Stevie
2
Solo un aviso ... Eliminé la 'solución' que pegué como solución alternativa para no causar más problemas, ya que la gente no lo veía como una 'solución temporal'.
Chrispix
77
@Chrispix, no deberías haber eliminado la solución parcial, es buena solo para fines de prueba
Hugo Allexis Cardona
224

Contrariamente a la respuesta aceptada , no necesita un administrador de confianza personalizado, ¡debe corregir la configuración de su servidor!

Me encontré con el mismo problema al conectarme a un servidor Apache con un certificado dynadot / alphassl instalado incorrectamente. 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 indicará la solución:

"El certificado no está firmado por una autoridad de confianza (comprobando en el almacén raíz de Mozilla). Si compró el certificado de una autoridad de confianza, probablemente solo necesite instalar uno o más certificados intermedios . Póngase en contacto con su proveedor de certificados para obtener ayuda para hacerlo. plataforma de servidor ".

También puede consultar 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, anteriormente en la salida:

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 debe hacer referencia a las autoridades de firma en una cadena a una en la que Android confíe (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 generalmente son proporcionados por 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 mi emisor de certificados, ahora no tengo errores al conectarme usando HttpsUrlConnection.

Stevie
fuente
3
En caso de que el OP tenga acceso a la configuración SSL del servidor al que se está conectando, esta podría ser una solución. Pero si él no es el que aloja el servicio al que se está conectando, tiene que solucionar el problema de su lado, lo que significa implementar un administrador de confianza personalizado.
Matthias B
9
Su solución funciona, sin duda, pero ¿no está de acuerdo con que es una solución alternativa en lugar de una solución para la causa raíz? Si tengo que conectarme a un servidor desde 3 clientes (Android, iOS, Windows Mobile), entonces tengo que aplicar la solución en los 3, mientras que puedo arreglar el servidor una vez y todos "funcionarán".
Stevie
2
Gracias Stevie, tuve mi servidor mal configurado durante 3 meses, ¡y solo ahora lo detecté! Ahora mi aplicación Android está funcionando al 100%
jpros
2
@Stevie Hago muchas llamadas a diferentes API que comparten el mismo dominio, pero solo una de ellas falla con (javax.net.ssl.SSLHandshakeException) ... ¿alguna idea de por qué sucedería tal cosa? y por cierto, el Certificado SSL no es confiable. Entonces, pensé que todas las llamadas deberían fallar con la misma excepción.
un jugador justo el
1
@dvaey póngase en contacto con quien sea el propietario del servidor y dígales que su configuración está rota y que su https no funciona correctamente; bríndeles este enlace para demostrarlo digicert.com/help ... Me imagino que lo agradecerían y lo harían rápidamente. resolver. De lo contrario, tendrá que seguir uno de los pasos de solución en las otras respuestas, pero luego no deberá aceptar ninguna seguridad (ignorar los certificados) o volver a implementar sus aplicaciones cuando caduque el certificado y su almacén de confianza personalizado ya no coincida con el nuevo cert.
Stevie
17

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

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

En el ejemplo anterior, usé OkHttpClientpero SSLContextpuedo usarlo con cualquier cliente en Java.

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

klimat
fuente
¿Qué pasa con .pfx?
Choletski
2
¿No es esto inseguro ya que cualquier usuario puede acceder a la carpeta de activos de una aplicación una vez que tiene la apk?
Patrice Andala
1
@PatriceAndala, las CA raíz están disponibles públicamente, así que está bien
BekaBot
17

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

Cuando obtienes 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 autofirmado
  3. A la configuración del servidor le falta una CA intermedia

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

Otros usuarios que usan AsyncHTTPClientdesde la com.loopj.android:android-async-httpbiblioteca, verifique Configurar AsyncHttpClient para usar HTTPS .

usuario1506104
fuente
55
¿Qué pasa si uno está usando un cliente okhttp?
TheLearner el
Para okhttp, por favor verifique la respuesta de @ mklimek.
user1506104
14

Si usa la actualización, debe personalizar su OkHttpClient.

retrofit = new Retrofit.Builder()
                        .baseUrl(ApplicationData.FINAL_URL)
                        .client(getUnsafeOkHttpClient().build())
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();

El código completo es el siguiente.

    public class RestAdapter {

    private static Retrofit retrofit = null;
    private static ApiInterface apiInterface;

    public static OkHttpClient.Builder getUnsafeOkHttpClient() {
        try {
            // Create a trust manager that does not validate certificate chains
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[]{};
                        }
                    }
            };

            // Install the all-trusting trust manager
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

            // Create an ssl socket factory with our all-trusting manager
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
            return builder;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static ApiInterface getApiClient() {
        if (apiInterface == null) {

            try {
                retrofit = new Retrofit.Builder()
                        .baseUrl(ApplicationData.FINAL_URL)
                        .client(getUnsafeOkHttpClient().build())
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();

            } catch (Exception e) {

                e.printStackTrace();
            }


            apiInterface = retrofit.create(ApiInterface.class);
        }
        return apiInterface;
    }

}
Shihab Uddin
fuente
1
Intento usar el código, pero obtengo el siguiente error nuevamente ... "javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: no se encontró el ancla de confianza para la ruta de certificación". ¿Puedes ayudar en esto?
Vishwa Pratap
Esto es radicalmente inseguro. No utilice.
Marqués de Lorne el
¡Gracias! Reescribió el método getUnsafeOkHttpClient()en Kotlin: stackoverflow.com/a/60507560/2914140 .
CoolMind
11

Respondiendo a una publicación muy antigua. Pero tal vez ayude a algunos novatos y si ninguno de los anteriores funciona.

Explicación: Sé que nadie quiere una explicación basura; Más bien la solución. Pero en una línea, está intentando acceder a un servicio desde su máquina local a una máquina remota que no confía en su máquina. Debe solicitar la confianza del servidor remoto.

Solución: la siguiente solución supone que se cumplen las siguientes condiciones

  1. Intentando acceder a una API remota desde su máquina local.
  2. Estás construyendo para la aplicación de Android
  3. Su servidor remoto está bajo filtración de proxy (usa proxy en la configuración de su navegador para acceder al servicio de API remota, generalmente un servidor de preparación o de desarrollo)
  4. Estás probando en un dispositivo real

Pasos:

Necesita un archivo de extensión .keystore para registrar su aplicación. Si no sabe cómo crear un archivo .keystore; luego 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. Haga clic en el menú superior Generar> Generar APK firmado. En la siguiente ventana haga clic en el nuevo ... Crear botón. En la nueva ventana, ingrese los 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 guardar en la parte superior de la ruta del almacén de claves del campo superior . Después de ingresar todo el campo, haga clic en el botón Aceptar.

Sign Apk File

Ahora necesita crear 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. Compilación> Generar APK firmado
  3. Hacer clic Choose existing... botón
  4. Seleccione el archivo .keystore que acabamos de crear en el archivo Crear .keystore sección
  5. Ingrese la misma contraseña que creó al crear en la sección Crear archivo .keystore . Use la misma contraseña para Key store passwordyKey password campos. 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 los build.gradlearchivos, debe seleccionar Build Typesy Flavors.
  8. Para Build Typeselegir releasedel menú desplegable
  9. Para Flavorssin embargo, se depende de la configuración en el build.gradlearchivo. Elige stagingde este campo. Utilicé la siguiente configuración en build.gradle, puedes usar la misma que la mía, pero asegúrate de cambiar el applicationIdnombre de tu 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 Signature Versionscasillas inferiores y haga clic en el Finishbotón.

Casi ahí:

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

Configuración de proxy en dispositivo Android:

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

Una última parada:

Recuerde que generamos 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. Elimine cualquier archivo apk instalado anteriormente del dispositivo Android
  4. correr adb install name of the apk file
  5. Si por alguna razón el comando anterior regresa con adb command not found. Ingrese la ruta completa comoC:\Users\shah\AppData\Local\Android\sdk\platform-tools\adb.exe install name of the apk file

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

Salam!

TIENE
fuente
4

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

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

MPN
fuente
1
Si el certificado ha expirado, entonces no es válido según una serie de estándares. Está bien usar una costumbre TrustManagery usar un conjunto diferente de criterios. Pero fuera de la caja, con eso tienes que trabajar.
jww
4

Tuve el mismo problema al conectarme desde el cliente Android al servidor Kurento. El servidor Kurento usa certificados jks, así que tuve que convertir pem a é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.

V.Poddubchak
fuente
3

Use https://www.ssllabs.com/ssltest/ para probar un dominio.

La solución de Shihab Uddin en Kotlin.

import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.*
import javax.security.cert.CertificateException

companion object {

    private val gson: Gson
    private val retrofit: Retrofit

    init {

        val okHttpClient = getUnsafeOkHttpClient() // OkHttpClient().newBuilder()
            .build()

        gson = GsonBuilder().setLenient().create()

        retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build()
    }

    private fun getUnsafeOkHttpClient(): OkHttpClient.Builder =
        try {
            // Create a trust manager that does not validate certificate chains
            val trustAllCerts: Array<TrustManager> = arrayOf(
                object : X509TrustManager {
                    @Throws(CertificateException::class)
                    override fun checkClientTrusted(chain: Array<X509Certificate?>?,
                                                    authType: String?) = Unit

                    @Throws(CertificateException::class)
                    override fun checkServerTrusted(chain: Array<X509Certificate?>?,
                                                    authType: String?) = Unit

                    override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
                }
            )
            // Install the all-trusting trust manager
            val sslContext: SSLContext = SSLContext.getInstance("SSL")
            sslContext.init(null, trustAllCerts, SecureRandom())
            // Create an ssl socket factory with our all-trusting manager
            val sslSocketFactory: SSLSocketFactory = sslContext.socketFactory
            val builder = OkHttpClient.Builder()
            builder.sslSocketFactory(sslSocketFactory,
                trustAllCerts[0] as X509TrustManager)
            builder.hostnameVerifier { _, _ -> true }
            builder
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
}
CoolMind
fuente
2

Tuve el mismo problema que encontré fue que el archivo de certificado .crt que proporcioné falta un certificado intermedio. Entonces solicité todos los archivos .crt al administrador de mi servidor, luego los concateneé 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.

Sahan Maldeniya
fuente
También tuvimos el mismo problema.
Faltaba el
1

El error de anclaje de confianza puede suceder por muchas razones. Para mí era simplemente que estaba intentando acceder en https://example.com/lugar de https://www.example.com/.

Por lo tanto, es posible que desee verificar sus URL antes de comenzar a construir su propio Trust Manager (como lo hice).

Unkulunkulu
fuente
0

En los teléfonos Gingerbread, siempre aparece este error: Trust Anchor not found for Android SSL Connectionincluso 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, configuré para confiar en mi certificado personalizado. Si eso falla, entonces deshabilito la seguridad. Esta no es la mejor opción, pero es la única opción que conozco con teléfonos viejos y con errores.

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

david.perez
fuente
Solución para Android 2.3.x en caso de que alguien lo necesite, stackoverflow.com/a/46465722/7125370
Newbie009
0

En mi caso, esto sucedía después de la actualización a Android 8.0. El certificado autofirmado en el que Android estaba configurado confiaba usando el algoritmo de firma SHA1withRSA. Cambiar a un nuevo certificado, utilizando el algoritmo de firma SHA256withRSA solucionó el problema.

Zds
fuente
0

Sé que no necesita confiar en todos los certificados, pero en mi caso tuve problemas con algunos entornos de depuración donde teníamos certificados autofirmados y necesitaba una solución sucia.

Todo lo que tenía que hacer era cambiar la inicialización del sslContext

mySSLContext.init(null, trustAllCerts, null); 

donde trustAllCertsfue creado así:

private final TrustManager[] trustAllCerts= new TrustManager[] { new X509TrustManager() {
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return new java.security.cert.X509Certificate[]{};
    }

    public void checkClientTrusted(X509Certificate[] chain,
                                   String authType) throws CertificateException {
    }

    public void checkServerTrusted(X509Certificate[] chain,
                                   String authType) throws CertificateException {
    }
} };

Espero que esto sea útil.

Adrian C.
fuente
Eso es lo que quería encontrar! Gracias
oxidado
Me sale error Hostname '192.168.0.16' was not verified. Estoy probando mi webapi a través de mi depurador (IIS Express) localmente. ¿Algúna idea de cómo arreglar esto? Gracias :)
Sam
1
Esto es radicalmente inseguro. No utilice.
Marqués de Lorne el
0

He tenido un problema similar y he descartado por completo la estrategia de confiar en todas las fuentes.

Comparto aquí mi solución aplicada a una aplicación implementada en Kotlin

Primero recomendaría usar el siguiente sitio web para obtener información sobre el certificado y su validez

Si no aparece como 'Emisores aceptados' en el almacén de confianza predeterminado de Android , debemos obtener ese certificado e incorporarlo a la aplicación para crear un almacén de confianza personalizado

La solución ideal en mi caso fue crear un Trust Manager de alto nivel que combine la tienda de confianza predeterminada personalizada y la de Android

Aquí expone el código de alto nivel utilizado para configurar el OkHttpClient que utilizó con Retrofit.

override fun onBuildHttpClient(httpClientBuild: OkHttpClient.Builder) {

        val trustManagerWrapper = createX509TrustManagerWrapper(
            arrayOf(
                getCustomX509TrustManager(),
                getDefaultX509TrustManager()
            )
        )

        printX509TrustManagerAcceptedIssuers(trustManagerWrapper)

        val sslSocketFactory = createSocketFactory(trustManagerWrapper)
        httpClientBuild.sslSocketFactory(sslSocketFactory, trustManagerWrapper)

    }

De esta manera, podría comunicarme con el servidor con un certificado autofirmado y con otros servidores con un certificado emitido por una entidad de certificación de confianza.

Esto es todo, espero que pueda ayudar a alguien.

Sergio Sánchez Sánchez
fuente
0

Sé que este es un artículo muy antiguo, pero me encontré con este artículo al tratar de resolver mis problemas de anclaje de confianza. He publicado cómo lo arreglé. Si ha preinstalado su CA raíz, debe agregar una configuración al manifiesto.

https://stackoverflow.com/a/60102517/114265

Enviado GR
fuente
solo para API 24+
BekaBot
@BekaBot: probablemente esto sea cierto, pero de acuerdo con la documentación 23 y siguientes, confía en los certificados de usuario de forma predeterminada. De forma predeterminada, las conexiones seguras (que utilizan protocolos como TLS y HTTPS) de todas las aplicaciones confían en las CA del sistema preinstaladas y las aplicaciones dirigidas a Android 6.0 (Nivel de API 23) e inferior también confían en la tienda de CA agregada por el usuario de forma predeterminada
GR Envoy
-1
**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);
Dayanand Waghmare
fuente
-2

También me he enfrentado al mismo problema. Solo elimino hhtps a http, como

final public static String ROOT_URL = "https://example.com"; a final public static String ROOT_URL = "http://example.com";

Finalmente, resolví este problema.

Rasheduzzaman
fuente
Seguramente esto solo está eliminando la seguridad SSL de la ecuación, lo que probablemente sea una mala idea para un entorno de producción.
Pensamientos del dragón
Esto realmente no es una solución, eliminar la seguridad SSL.
omega1