L'autenticazione del client ha avuto successo quando si utilizza un pfx con Java, non riesce a utilizzare OpenSSL. Perché?

1

Ho cercato di risolvere i problemi con l'autenticazione del client e sto riscontrando un comportamento diverso durante la connessione da un'applicazione Java a OpenSSL.

Una terza parte mi ha fornito un pfx, ho estratto il certificato e la chiave (che corrispondono tra loro) e ho tentato di iniziare una connessione usando openssl. Ottengo il seguente errore di handshake:

CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
depth=2 C = US, O = "VeriSign, Inc.", OU = VeriSign Trust Network, OU = "(c) 2006 VeriSign, Inc. - For authorized use only", CN = VeriSign Class 3 Public Primary Certification Authority - G5
verify return:1
depth=1 C = US, O = "VeriSign, Inc.", OU = VeriSign Trust Network, OU = Terms of use at https://www.verisign.com/rpa (c)10, CN = VeriSign Class 3 International Server CA - G3
verify return:1
depth=0 C = US, ST = Somewhere, L = Somewhere, O = The Third Party, OU = TTP, CN = thethirdparty.com
verify return:1
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server certificate request A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client certificate A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write certificate verify A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL3 alert read:fatal:handshake failure
SSL_connect:failed in SSLv3 read finished A
140735253803088:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:s3_pkt.c:1472:SSL alert number 40
140735253803088:error:140790E5:SSL routines:ssl23_write:ssl handshake failure:s23_lib.c:177:

Anche la terza parte mi ha inviato un'applicazione Java, che utilizza lo stesso pfx e autentica correttamente. Il codice è il seguente:

    private void postHTTPSUsingClientAuth()
    {
        log.info("starting test");
        final String url="https://thethirdpartyendpoint.com";
        final String GUID = "(A guid)";
        final String KEY = "(A key)";
        final String DATA = "Any Data";
        final String clientCert="/testdata/theClientCert.pfx";
        final String password = "password here";

        log.info("using URL: "+url);
        log.info("using guid | key: "+GUID+" | "+KEY);
        log.info("using certificate: "+clientCert);

        try
        {
            KeyStore keyStore = getKeyStore(clientCert,password);
            CloseableHttpClient client=getHttpClientWithClientCert(keyStore,password);
            HttpPost request = new HttpPost(url);
            request.addHeader("clientId", GUID);
            request.addHeader("key", KEY);
            request.setEntity(new StringEntity(DATA));

            // add request header
            HttpResponse response = client.execute(request);
            log.info("got response: "+response.getStatusLine().getStatusCode());

            BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            StringBuffer result = new StringBuffer();
            String line = "";
            log.info("writing response");
            while ((line = rd.readLine()) != null)
            {
                result.append(line);
            }
            log.info("result=\n"+result);
        }
        catch (Exception e)
        {
            log.error("error occurred: "+e.toString());
        }
        log.info("test complete");
    }



private KeyStore getKeyStore(String certFile, String password) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException
    {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        //log.info("testing resource location");
        //log.info("available="+getClass().getResourceAsStream(certFile).available());
        keyStore.load(getClass().getResourceAsStream(certFile), password.toCharArray());
        return keyStore;
    }

    private CloseableHttpClient getHttpClientWithClientCert(KeyStore keyStore, String password) throws Exception
    {
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
        keyManagerFactory.init(keyStore, password.toCharArray());
        final SSLContext context = SSLContext.getInstance("TLS");
        context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
        return HttpClientBuilder.create()
                .setSSLSocketFactory(new SSLConnectionSocketFactory(context)).build();      
    }   

Qualcuno può spiegare perché, quando si utilizza lo stesso certificato, l'handshake non riesce per OpenSSL?

Il certificato client contiene una catena:

Bag Attributes
    localKeyID: 01 00 00 00 
subject=/O=Something/OU=Something/CN=Something.Something.com
issuer=/DC=net/DC=Something/DC=Something/CN=Something
-----BEGIN CERTIFICATE-----
(cert data)
-----END CERTIFICATE-----
Bag Attributes: <Empty Attributes>
subject=/O=Something/CN=Something
issuer=/O=Something/CN=Something
-----BEGIN CERTIFICATE-----
(cert data)
-----END CERTIFICATE-----
Bag Attributes: <Empty Attributes>
subject=/DC=Something/DC=Something/DC=Something/CN=Something
issuer=/O=Something/CN=Something
-----BEGIN CERTIFICATE-----
(cert data)
-----END CERTIFICATE-----

C'è una possibilità che OpenSSL ometta questa catena e manda solo il certificato superiore?

    
posta Mark Kelly 12.11.2015 - 01:29
fonte

1 risposta

1

La mia ipotesi è che tu abbia semplicemente aggiunto certificato foglia e certificato catena allo stesso file e poi usato openssl s_client -cert file.pem su di esso. Ma la documentazione per gli stati s_client:

-CAfile file
    A file containing trusted certificates to use during server authentication
    and to use when attempting to build the client certificate chain.

Ciò significa che devi fornire il certificato foglia con l'opzione -cert ma aggiungere i certificati di catena con l'opzione -CAfile . Vedi anche link

    
risposta data 12.11.2015 - 06:33
fonte

Leggi altre domande sui tag