onexão @HTTPS com certificado de cliente em um aplicativo Android

Estou tentando substituir a conexão HTTP atualmente em funcionamento por uma conexão HTTPS em um aplicativo Android que estou escrevendo. A segurança adicional de uma conexão HTTPS é necessária e, portanto, não posso ignorar esta etap

Tenho o seguinte:

Um servidor configurado para estabelecer uma conexão HTTPS e requer um certificado de clienteEste servidor possui um certificado emitido por uma CA de grande escala padrão. Em resumo, se eu acessar esta conexão pelo navegador no Android, ela funcionará bem porque o armazenamento confiável de dispositivos reconhece a CA. (Portanto, não é autoassinado) Um certificado de cliente que é essencialmente autoassinado. (Emitido por uma CA interna) Um aplicativo Android que carrega esse certificado de cliente e tenta se conectar ao servidor mencionado acima, mas tem os seguintes problemas / propriedades:O cliente pode se conectar ao servidor quando o servidor estiver configurado para requer um certificado de cliente. Basicamente, se eu usarSSLSocketFactory.getSocketFactory() a conexão funciona bem, mas o certificado do cliente é uma parte necessária das especificações deste aplicativo, portanto:O cliente produz umjavax.net.ssl.SSLPeerUnverifiedException: No peer certificate exceção quando tento me conectar com meu @ personalizaSSLSocketFactory, mas não sei ao certo por quê. Essa exceção parece um pouco ambígua depois de pesquisar na Internet várias soluções para isso.

Aqui está o código relevante para o cliente:

SSLSocketFactory socketFactory = null;

public void onCreate(Bundle savedInstanceState) {
    loadCertificateData();
}

private void loadCertificateData() {
    try {
        File[] pfxFiles = Environment.getExternalStorageDirectory().listFiles(new FileFilter() {
            public boolean accept(File file) {
                if (file.getName().toLowerCase().endsWith("pfx")) {
                    return true;
                }
                return false;
            }
        });

        InputStream certificateStream = null;
        if (pfxFiles.length==1) {
            certificateStream = new FileInputStream(pfxFiles[0]);
        }

        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        char[] password = "somePassword".toCharArray();
        keyStore.load(certificateStream, password);

        System.out.println("I have loaded [" + keyStore.size() + "] certificates");

        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, password);

        socketFactory = new SSLSocketFactory(keyStore);
    } catch (Exceptions e) {
        // Actually a bunch of catch blocks here, but shortened!
    }
}

private void someMethodInvokedToEstablishAHttpsConnection() {
    try {
        HttpParams standardParams = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(standardParams, 5000);
        HttpConnectionParams.setSoTimeout(standardParams, 30000);

        SchemeRegistry schRegistry = new SchemeRegistry();
        schRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        schRegistry.register(new Scheme("https", socketFactory, 443));
        ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(standardParams, schRegistry);

        HttpClient client = new DefaultHttpClient(connectionManager, standardParams);
        HttpPost request = new HttpPost();
        request.setURI(new URI("https://TheUrlOfTheServerIWantToConnectTo));
        request.setEntity("Some set of data used by the server serialized into string format");
        HttpResponse response = client.execute(request);
        resultData = EntityUtils.toString(response.getEntity());
    } catch (Exception e) {
        // Catch some exceptions (Actually multiple catch blocks, shortened)
    }
}

Verifiquei que sim, a keyStore carrega um certificado e está feliz com iss

Tenho duas teorias sobre o que sinto falta de ler sobre conexões HTTPS / SSL, mas como essa é realmente minha primeira incursão, estou um pouco intrigado com o que realmente preciso para resolver esse problem

A primeira possibilidade, até onde sei, é que eu preciso configurar este SSLSocketFactory com o armazenamento confiável dos dispositivos, que inclui todas as Autoridades de Certificação intermediárias e de terminais padrão. Ou seja, o padrão deSSLSocketFactory.getSocketFactory() carrega um conjunto de CAs no armazenamento confiável da fábrica que é usado para confiar no servidor quando ele envia seu certificado, e é isso que está falhando no meu código, porque não tenho o armazenamento confiável carregado corretamente. Se isso for verdade, qual seria a melhor maneira de carregar esses dados?

A segunda possibilidade se deve ao fato de o certificado do cliente ser autoassinado (ou emitido por uma autoridade de certificação interna - me corrija se eu estiver errado, mas isso realmente equivale à mesma coisa, para todos os efeitos e propósitos aqui) ) É de fatoest armazenamento confiável que falta, e basicamente preciso fornecer uma maneira para o servidor validar o certificado com a CA interna e também validar se essa CA interna é de fato"confiável". Se isso for verdade, exatamente que tipo de coisa estou procurando? Vi algumas referências a isso que me fazem acreditar que esse pode ser o meu problema, como emaqu, mas não tenho certeza. Se esse for realmente o meu problema, o que pediria à pessoa que mantém a autoridade de certificação interna e como adicionaria isso ao meu código para que minha conexão HTTPS funcionasse?

A terceira solução, e espero que menos possível, é que estou completamente enganado sobre algum ponto aqui e perdi uma etapa crucial ou estou negligenciando completamente uma parte do HTTPS / SSL da qual atualmente não tenho conhecimento. Se for esse o caso, você poderia me fornecer um pouco de orientação para que eu possa aprender o que preciso aprender?

Obrigado pela leitura!

questionAnswers(5)

yourAnswerToTheQuestion