Estoy tratando de averiguar cómo configurar la extensión trusted_ca_keys en un cliente JAVA 8 TLS. O incluso en general: ¿cómo configuro cualquier extensión TLS utilizando la biblioteca JSSE estándar proporcionada por Oracle? No quiero usar ninguna biblioteca de terceros como BouncyCastle.
Así es como configuro mi cliente SSL hasta ahora, sin ninguna extensión:
/**
* Initializes the TLS client
*
* @param host The address of the TLS server to connect to
* @param port The port of the TLS server to connect to
*/
public boolean initialize(Inet6Address host, int port) {
super.initialize();
try {
/*
* Setting the system property for the keystore and truststore via
* - System.setProperty("javax.net.ssl.keyStore", [filePath given as a String])
* - System.setProperty("javax.net.ssl.trustStore", [filePath given as a String])
* does not work in a JAR file since only getResourceAsStream works there (which on the other
* hand only returns an InputStream, not a file resource). Thus use setSSLFactories()
*/
SecurityUtils.setSSLContext(
GlobalValues.EVCC_KEYSTORE_FILEPATH.toString(),
GlobalValues.EVCC_TRUSTSTORE_FILEPATH.toString(),
GlobalValues.PASSPHRASE_FOR_CERTIFICATES_AND_KEYS.toString());
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
getLogger().debug("Creating socket to TLS server ...");
setTlsSocketToServer((SSLSocket) sslSocketFactory.createSocket(host, port));
getLogger().debug("TLS socket to server created");
setInStream(getTlsSocketToServer().getInputStream());
setOutStream(getTlsSocketToServer().getOutputStream());
/*
* The EVCC shall support at least one cipher suite as listed below according to
* the standard. An implementer may decide to choose only one of them:
* - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
* - TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
*/
String[] enabledCipherSuites = {
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256" // this cipher suite should be avoided, ECDH does not support perfect forward secrecy
};
getTlsSocketToServer().setEnabledCipherSuites(enabledCipherSuites);
// Set the supported TLS protocol
String[] enabledProtocols = {"TLSv1.2"};
getTlsSocketToServer().setEnabledProtocols(enabledProtocols);
/*
* The communication session setup timeout needs to be set here in case there is any problem with the
* TLS handshake.
* The timeout value will be overwritten with every new message being sent
*/
getTlsSocketToServer().setSoTimeout(TimeRestrictions.V2G_EVCC_COMMUNICATION_SETUP_TIMEOUT);
getLogger().debug("Starting TLS handshake ...");
getTlsSocketToServer().startHandshake();
getLogger().debug("TLS handshake finished");
getLogger().info("TLS client connection established \n\t from link-local address " +
getClientAddress() + " and port " + getClientPort() +
"\n\t to host " + host.getHostAddress() + " and port " + port);
return true;
} catch (UnknownHostException e) {
getLogger().error("TLS client connection failed (UnknownHostException)!", e);
} catch (SSLHandshakeException e) {
getLogger().error("TLS client connection failed (SSLHandshakeException)", e);
} catch (SocketTimeoutException e) {
getLogger().fatal("TLS client connection failed (SocketTimeoutException) due to session setup timeout", e);
} catch (IOException e) {
getLogger().error("TLS client connection failed (IOException)!", e);
} catch (NullPointerException e) {
getLogger().fatal("NullPointerException while trying to set keystores, resource path to keystore/truststore might be incorrect");
}
return false;
}
Y aquí, para completar, el código para setSSLContext:
/**
* Sets the SSLContext of the TLSServer and TLSClient with the given keystore and truststore locations as
* well as the password protecting the keystores/truststores.
*
* @param keyStorePath The relative path and filename for the keystore
* @param trustStorePath The relative path and filename for the truststore
* @param keyStorePassword The password protecting the keystore
*/
public static void setSSLContext(
String keyStorePath,
String trustStorePath,
String keyStorePassword) {
KeyStore keyStore = SecurityUtils.getKeyStore(keyStorePath, keyStorePassword);
KeyStore trustStore = SecurityUtils.getKeyStore(trustStorePath, keyStorePassword);
try {
// Initialize a key manager factory with the keystore
KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, keyStorePassword.toCharArray());
KeyManager[] keyManagers = keyFactory.getKeyManagers();
// Initialize a trust manager factory with the truststore
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(trustStore);
TrustManager[] trustManagers = trustFactory.getTrustManagers();
// Initialize an SSL context to use these managers and set as default
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, null);
SSLContext.setDefault(sslContext);
} catch (NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException |
KeyManagementException e) {
getLogger().error(e.getClass().getSimpleName() + " occurred while trying to initialize SSL context");
}
}
Así que ahora necesito saber en qué parte del código anterior puedo decirle a Java que use ciertas extensiones TLS. Necesito 'trusted_ca_keys' y 'staus_request_v2' (este último es para el grapado múltiple de OCSP).
También implementé el servidor y necesito admitir estas extensiones en el servidor también, pero creo que este ejemplo de código debería ser suficiente.
Cualquier ayuda es muy apreciada.