Anchor de confiança não encontrado para a conexão SSL do Android


185

Estou tentando conectar-me a uma caixa do IIS6 executando um certificado SSL de 256 bits godaddy e estou recebendo o erro:

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

Estive tentando determinar o que poderia estar causando isso, mas desenhando espaços em branco agora.

Aqui está como estou me 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()); 

Respostas:


78

A solução do @Chrispix é perigosa! Confiar em todos os certificados permite que alguém faça um homem no meio do ataque!Basta enviar QUALQUER certificado para o cliente e ele aceitará!

Adicione seu (s) certificado (s) a um gerenciador de confiança personalizado, como descrito nesta postagem: Confiando em todos os certificados usando HttpClient sobre HTTPS

Embora seja um pouco mais complexo estabelecer uma conexão segura com um certificado personalizado, ele oferecerá a segurança de criptografia SSL desejada, sem o perigo do homem no ataque do meio!


1
Isso é bom para trabalhar com um certificado auto-gerado, mas para um (como os OPs) que possui uma cadeia válida de volta às autoridades de certificação raiz, é apenas uma solução alternativa para um servidor mal configurado - veja minha resposta.
30513 Stevie

4
@Stevie Aceitar TODOS os certificados é apenas uma opção para um teste de prova de conceito, em que a conexão SSL não é a parte que você deseja testar. Caso contrário, você não precisará usar SSL, se aceitar todos os certificados, pois a conexão não é segura!
Matthias B

1
Ah, desculpe, acho que há um mal-entendido - concordo plenamente que ninguém deve aceitar todos os certificados! :) Meu comentário foi em relação ao seu segundo parágrafo - a sugestão de usar um gerenciador de confiança personalizado - que IMHO deveria ser uma solução alternativa de último recurso em vez de uma solução recomendada.
30513 Stevie

2
Apenas um aviso. Eu removi a 'solução' que colei como solução alternativa para não causar mais problemas, pois as pessoas não a viam como uma 'solução temporária'.
chrispix

7
@Chrispix, você não deve ter removido a correção parcial, bom é para fins apenas testando
Hugo Allexis Cardona

224

Ao contrário da resposta aceita, você não precisa de um gerenciador de confiança personalizado, precisa corrigir a configuração do servidor!

Ocorreu o mesmo problema ao conectar-me a um servidor Apache com um certificado dynadot / alphassl incorretamente instalado. Estou me conectando usando HttpsUrlConnection (Java / Android), que estava lançando -

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

O problema real é uma configuração incorreta do servidor - teste-o com http://www.digicert.com/help/ ou similar, e ele fornecerá a solução:

"O certificado não é assinado por uma autoridade confiável (checando no repositório raiz do Mozilla). Se você comprou o certificado de uma autoridade confiável, provavelmente precisará instalar um ou mais certificados intermediários . Entre em contato com o seu provedor de certificados para obter ajuda sobre isso. plataforma de servidor ".

Você também pode verificar o certificado com o openssl:

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

Você provavelmente verá:

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

e, anteriormente na saída:

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`

A cadeia de certificados conterá apenas 1 elemento (seu certificado):

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

... mas deve referir as autoridades de assinatura em uma cadeia de volta a uma confiável do 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

As instruções (e os certificados intermediários) para configurar seu servidor geralmente são fornecidas pela autoridade que emitiu seu certificado, por exemplo: http://www.alphassl.com/support/install-root-certificate.html

Depois de instalar os certificados intermediários fornecidos pelo meu emissor de certificado, agora não tenho erros ao conectar usando HttpsUrlConnection.


3
Caso o OP tenha acesso à configuração SSL do servidor à qual ele está se conectando, isso pode ser uma solução. Mas se ele não é o único que hospeda o serviço ao qual está se conectando, ele precisa corrigir o problema do seu lado, o que significa implementar um gerenciador de confiança personalizado.
Matthias B

9
Sua solução funciona, sem dúvida, mas você não concorda que é uma solução alternativa e não uma correção para a causa raiz? Se eu tiver que me conectar a um servidor de 3 clientes (Android, iOS, Windows Mobile), aplico a solução alternativa nos 3, enquanto posso consertar o servidor uma vez e todos "funcionarão".
30513 Stevie

2
Obrigado Stevie, meu servidor foi configurado incorretamente por 3 meses e só agora eu detectei isso! Agora meu aplicativo android está funcionando 100%
jpros

2
@ Stevie Faço muitas chamadas para diferentes APIs que compartilham o mesmo domínio, mas apenas uma delas falha com (javax.net.ssl.SSLHandshakeException) ... alguma idéia de por que isso aconteceria? e, a propósito, o certificado SSL não é confiável. Então, pensei que todas as chamadas deveriam falhar com a mesma exceção.
um jogador justo

1
@dvaey entre em contato com quem é o dono do servidor e diga a eles que a configuração está quebrada e o https não está funcionando corretamente - forneça esse link para provar isso digicert.com/help ... Eu imagino que eles seriam agradecidos e rápidos em resolver. Caso contrário, você precisará executar uma das etapas da solução alternativa nas outras respostas, mas precisará aceitar nenhuma segurança (ignorar certs) ou reimplementar seus aplicativos quando o certificado expirar e seu armazenamento confiável personalizado não corresponder mais ao novo cert.
Stevie

17

Você pode confiar em um certificado específico em tempo de execução.
Basta fazer o download no servidor, colocar ativos e carregar assim usando ssl-utils-android :

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

No exemplo acima, usei, OkHttpClientmas SSLContextpode ser usado com qualquer cliente em Java.

Se você tiver alguma dúvida não hesite em perguntar. Eu sou o autor desta pequena biblioteca.


e o .pfx?
Choletski

2
Isso não é seguro, pois qualquer usuário pode acessar a pasta de ativos de um aplicativo depois de ter o apk?
Patrice Andala

1
@PatriceAndala, CAs raiz estão disponíveis ao público, então está tudo bem
BekaBot 15/06

17

Atualização com base na documentação mais recente do Android (março de 2017):

Quando você receber esse tipo de erro:

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)

o problema pode ser um dos seguintes:

  1. A CA que emitiu o certificado do servidor era desconhecida
  2. O certificado do servidor não foi assinado por uma CA, mas foi autoassinado
  3. Falta à configuração do servidor uma CA intermediária

A solução é ensinar HttpsURLConnectiona confiar em um conjunto específico de CAs. Quão? Verifique https://developer.android.com/training/articles/security-ssl.html#CommonProblems

Para outras pessoas que estão usando AsyncHTTPClientda com.loopj.android:android-async-httpbiblioteca, verifique o Setup AsyncHttpClient para usar HTTPS .


5
E se alguém estiver usando um cliente okhttp?
TheLearner

Para okhttp, pls verifique a resposta de @ mklimek.
user1506104

14

Se você usar o retrofit, precisará personalizar seu OkHttpClient.

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

O código completo é como abaixo.

    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;
    }

}

1
Estou tentando usar o código, mas estou recebendo o seguinte erro novamente .. "javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Confia na âncora para o caminho da certificação não encontrado." você pode ajudar nisso
Vishwa Pratap

Isso é radicalmente inseguro. Não use.
Marquês de Lorne

Obrigado! Reescreva o método getUnsafeOkHttpClient()no Kotlin: stackoverflow.com/a/60507560/2914140 .
CoolMind 03/03

11

Respondendo a uma postagem muito antiga. Mas talvez isso ajude alguns novatos e, se não funcionar, acima.

Explicação: Eu sei que ninguém quer porcaria de explicação; sim a solução. Mas em um liner, você está tentando acessar um serviço da sua máquina local para uma máquina remota que não confia na sua máquina. Você solicita a necessidade de obter a confiança do servidor remoto.

Solução: A solução a seguir pressupõe que você tenha as seguintes condições atendidas

  1. Tentando acessar uma API remota da sua máquina local.
  2. Você está construindo para o aplicativo Android
  3. Seu servidor remoto está sob filtragem de proxy (você usa proxy na configuração do navegador para acessar o serviço de API remota, geralmente um servidor de teste ou de desenvolvimento)
  4. Você está testando no dispositivo real

Passos:

Você precisa de um arquivo de extensão .keystore para inscrever seu aplicativo. Se você não sabe como criar o arquivo .keystore; em seguida, siga com a seção a seguir Criar arquivo .keystore ou pule para a próxima seção Assinar arquivo Apk

Criar arquivo .keystore

Abra o Android Studio. Clique no menu superior Compilar> Gerar APK assinado. Na janela seguinte, clique no novo ... Criar botão. Na nova janela, insira dados em todos os campos. Lembre-se dos dois campos de senha que eu recomendo devem ter a mesma senha; não use senha diferente; e também lembrar o caminho para salvar a top mais campo caminho de armazenamento de chaves . Depois de inserir todo o campo, clique no botão OK.

Assinar arquivo Apk

Agora você precisa criar um aplicativo assinado com o arquivo .keystore que você acabou de criar. Siga esses passos

  1. Build> Clean Project, espere até terminar a limpeza
  2. Compilar> Gerar APK assinado
  3. Clique no Choose existing...botão
  4. Selecione o arquivo .keystore que acabamos de criar no Criar .keystore arquivo de seção
  5. Digite a mesma senha que você criou ao criar na seção Criar arquivo .keystore . Use a mesma senha para Key store passworde Key passwordcampos. Digite também o alias
  6. Clique no botão Avançar
  7. Na próxima tela; que pode ser diferente com base nas suas configurações nos build.gradlearquivos, você precisa selecionar Build Typese Flavors.
  8. Para a Build Typesescolha releaseno menu suspenso
  9. Pois, Flavorsno entanto, isso depende das suas configurações no build.gradlearquivo. Escolha stagingneste campo. Usei as seguintes configurações no build.gradle, você pode usar o mesmo que o meu, mas certifique-se de alterar o applicationIdnome do seu pacote

    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. Clique nas duas Signature Versionscaixas de seleção inferiores e clique no Finishbotão.

Quase lá:

Todo o trabalho é feito, agora o movimento da verdade. Para acessar o servidor de armazenamento temporário em backup por proxy, é necessário fazer algumas configurações em seus dispositivos Android de teste reais.

Configuração de proxy no dispositivo Android:

  1. Clique na configuração dentro do telefone Android e depois em wi-fi
  2. Mantenha pressionado o wifi conectado e selecione Modify network
  3. Clique no botão Advanced optionsse não conseguir ver oProxy Hostname campo
  4. No campo, Proxy Hostnamedigite o IP do host ou o nome que você deseja conectar. Um servidor de temporariedade típico será nomeado comostg.api.mygoodcompany.com
  5. Para a porta, digite o número da porta de quatro dígitos, por exemplo 9502
  6. Aperte o Savebotão

Uma última parada:

Lembre-se de que geramos o arquivo apk assinado na seção Sign APK File . Agora é a hora de instalar esse arquivo APK.

  1. Abra um terminal e mude para a pasta do arquivo apk assinado
  2. Conecte seu dispositivo Android à sua máquina
  3. Remova qualquer arquivo apk instalado anterior do dispositivo Android
  4. Corre adb install name of the apk file
  5. Se, por algum motivo, o comando acima retornar com adb command not found. Digite o caminho completo comoC:\Users\shah\AppData\Local\Android\sdk\platform-tools\adb.exe install name of the apk file

Espero que o problema possa ser resolvido. Caso contrário, deixe-me um comentário.

Salam!


4

A mensagem de erro que eu recebia era semelhante, mas o motivo era que o certificado autoassinado havia expirado. Quando o cliente openssl foi tentado, ele me deu o motivo que foi esquecido quando eu estava verificando a caixa de diálogo de certificado do firefox.

Portanto, em geral, se o certificado estiver no keystore e seu "VÁLIDO", esse erro será disparado.


1
Se o certificado expirar, não será válido de acordo com vários padrões. Não há problema em usar um costume TrustManagere usar um conjunto diferente de critérios. Mas pronto para usar, é com isso que você precisa trabalhar.
jww 27/07

4

Eu tive o mesmo problema ao conectar do cliente Android ao servidor Kurento. O servidor Kurento usa certificados jks, então tive que converter o pem nele. Como entrada para a conversão, usei o arquivo cert.pem e isso levou a esses erros. Mas se usar fullchain.pem em vez de cert.pem - tudo está bem.


3

Use https://www.ssllabs.com/ssltest/ para testar um domínio.

A solução de Shihab Uddin em 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)
        }
}

2

Eu tive o mesmo problema que descobri foi que o arquivo .crt do certificado que forneci estava ausente de um certificado intermediário. Então, perguntei a todos os arquivos .crt do administrador do servidor e os concatinei em ordem inversa.

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

no windows eu executei a cópia Inter.crt + Root.crt newCertificate.crt

(Aqui eu ignorei myCrt.crt)

Então eu forneci o arquivo newCertificate.crt no código via inputstream. Trabalho feito.


Também tivemos o mesmo problema. Certificado intermediário estava faltando
Nidhin Chandran

1

O erro da âncora de confiança pode ocorrer por vários motivos. Para mim, era simplesmente o que eu estava tentando acessar em https://example.com/vez de https://www.example.com/.

Portanto, convém verificar suas URLs antes de começar a criar seu próprio Trust Manager (como eu fiz).


0

Nos telefones Gingerbread, eu sempre recebo este erro: Trust Anchor not found for Android SSL Connectionmesmo que eu configure para confiar no meu certificado.

Aqui está o código que eu uso (no idioma 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 _ 
        }
    }
}

e aqui está o código de conexão:

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)
}

Basicamente, eu configuro para confiar no meu certificado personalizado. Se isso falhar, desabilito a segurança. Essa não é a melhor opção, mas a única opção que conheço com telefones antigos e com bugs.

Esse código de amostra pode ser facilmente traduzido para Java.


Solução para o Android 2.3.x no caso de alguém precisar, stackoverflow.com/a/46465722/7125370
Newbie009 28/17

0

No meu caso, isso estava acontecendo após a atualização para o Android 8.0. O certificado autoassinado em que o Android foi configurado para confiar estava usando o algoritmo de assinatura SHA1withRSA. A mudança para um novo certificado, usando o algoritmo de assinatura SHA256withRSA, corrigiu o problema.


0

Eu sei que você não precisa confiar em todos os certificados, mas, no meu caso, tive problemas com alguns ambientes de depuração em que tínhamos certificados autoassinados e que precisava de uma solução suja.

Tudo o que eu precisava fazer era mudar a inicialização do sslContext

mySSLContext.init(null, trustAllCerts, null); 

onde trustAllCertsfoi criado assim:

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 isso seja útil.


Era isso que eu queria encontrar! Obrigado
oxied

Eu recebo erro Hostname '192.168.0.16' was not verified. Estou testando meu webapi por meio do meu depurador (IIS Express) localmente. Alguma idéia de como consertar isso? Obrigado :)
Sam

1
Isso é radicalmente inseguro. Não use.
Marquês de Lorne # /

0

Eu tive um problema semelhante e descartei completamente a estratégia de confiar em todas as fontes.

Compartilho aqui minha solução aplicada a um aplicativo implementado no Kotlin

Eu recomendaria primeiro usar o site a seguir para obter informações sobre o certificado e sua validade

Se ele não aparecer como "Emissores aceitos" no repositório de confiança padrão do Android , precisamos obter esse certificado e incorporá-lo ao aplicativo para criar um armazenamento confiável personalizado

A solução ideal no meu caso foi criar um Trust Manager de alto nível que combine o armazenamento confiável personalizado e o padrão do Android

Aqui, ele expõe o código de alto nível usado para configurar o OkHttpClient que ele usou com o Retrofit.

override fun onBuildHttpClient(httpClientBuild: OkHttpClient.Builder) {

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

        printX509TrustManagerAcceptedIssuers(trustManagerWrapper)

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

    }

Dessa maneira, eu poderia me comunicar com o servidor com um certificado autoassinado e com outros servidores com um certificado emitido por uma entidade de certificação confiável

É isso, espero que possa ajudar alguém.


0

Sei que este é um artigo muito antigo, mas me deparei com este artigo ao tentar resolver meus problemas de âncora de confiança. Eu postei como corrigi-lo. Se você pré-instalou sua CA raiz, precisará adicionar uma configuração ao manifesto.

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


somente para API 24+
BekaBot

@BekaBot - isso provavelmente é verdade, mas, de acordo com a documentação 23 e abaixo, confie nos certificados do usuário por padrão Por padrão, as conexões seguras (usando protocolos como TLS e HTTPS) de todos os aplicativos confiam nas CAs do sistema pré-instalado e nos aplicativos direcionados ao Android 6.0 (Nível de API 23) e inferior também confiam no armazenamento de CA adicionado pelo usuário por padrão
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);

-2

Eu também enfrentei o mesmo problema. Acabei de remover hhtps para http, como

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

Finalmente, eu resolvi esse problema.


Certamente, isso está apenas removendo a segurança SSL da equação, o que provavelmente é uma má idéia para um ambiente de produção.
Dragonthoughts

Isso realmente não é uma solução, removendo a segurança SSL.
omega1 11/04
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.