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.