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?