cacerts java ssl https certificate keystore

java keytool import certificate cacerts



¿Cómo especificar el alias de certificado de salida para las llamadas HTTPS? (4)

Estoy llamando a un servicio web que requiere autenticación de certificado de cliente.

Si especifico un almacén de claves Java que contiene un solo certificado (el certificado de cliente que el servicio espera), entonces todo funciona bien. Sin embargo, si uso un almacén de claves que contiene varios certificados, parece que no puedo especificar qué certificado debe recoger el cliente, el cliente parece recoger el primer certificado disponible (en orden alfabético).

He intentado la siguiente propiedad pero sin resultado esperado:

System.setProperty("com.sun.enterprise.security.httpsOutboundKeyAlias", "my-client-certificate alias");

¿Cómo puedo especificar qué alias de certificado de cliente se debe usar?


Heres un código completo cortado que funciona.

Lo uso para crear una conexión SSL en Android con un almacén de claves de una tarjeta inteligente que contiene varios certificados que coinciden con los criterios de filtrado estándar.

Los créditos van a zarniwoop.

/** * filters the SSLCertificate we want to use for SSL * <code> * KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509"); * kmf.init(keyStore, null); * String SSLCertificateKeyStoreAlias = keyStore.getCertificateAlias(sslCertificate); * KeyManager[] keyManagers = new KeyManager[] { new FilteredKeyManager((X509KeyManager)kmf.getKeyManagers()[0], sslCertificate, SSLCertificateKeyStoreAlias) }; * </code> */ private class FilteredKeyManager implements X509KeyManager { private final X509KeyManager originatingKeyManager; private final X509Certificate sslCertificate; private final String SSLCertificateKeyStoreAlias; /** * @param originatingKeyManager, original X509KeyManager * @param sslCertificate, X509Certificate to use * @param SSLCertificateKeyStoreAlias, Alias of the certificate in the provided keystore */ public FilteredKeyManager(X509KeyManager originatingKeyManager, X509Certificate sslCertificate, String SSLCertificateKeyStoreAlias) { this.originatingKeyManager = originatingKeyManager; this.sslCertificate = sslCertificate; this.SSLCertificateKeyStoreAlias = SSLCertificateKeyStoreAlias; } @Override public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { return SSLCertificateKeyStoreAlias; } @Override public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { return originatingKeyManager.chooseServerAlias(keyType, issuers, socket); } @Override public X509Certificate[] getCertificateChain(String alias) { return new X509Certificate[]{ sslCertificate }; } @Override public String[] getClientAliases(String keyType, Principal[] issuers) { return originatingKeyManager.getClientAliases(keyType, issuers); } @Override public String[] getServerAliases(String keyType, Principal[] issuers) { return originatingKeyManager.getServerAliases(keyType, issuers); } @Override public PrivateKey getPrivateKey(String alias) { return originatingKeyManager.getPrivateKey(alias); } }


Los enlaces que proporciona en su respuesta lo llevan a la respuesta, pero quería publicar una respuesta más simple aquí, ya que luchamos con este problema durante bastante tiempo antes de finalmente obtener algo que funcionara.

Tenemos el caso donde hay varios certificados disponibles para usar, y necesitamos usar el que tiene un alias específico para realizar nuestra conexión. Hicimos esto creando nuestra propia implementación de KeyManager que pasa a través de la mayor parte de su funcionalidad al X509KeyManager predeterminado, pero tiene la funcionalidad de seleccionar exactamente el alias correcto para usar cuando se realiza la conexión.

Primero el gestor de claves que creamos:

public class FilteredKeyManager implements X509KeyManager { private final X509KeyManager originatingKeyManager; private final X509Certificate[] x509Certificates; public FilteredKeyManager(X509KeyManager originatingKeyManager, X509Certificate[] x509Certificates) { this.originatingKeyManager = originatingKeyManager; this.x509Certificates = x509Certificates; } public X509Certificate[] getCertificateChain(String alias) { return x509Certificates; } public String[] getClientAliases(String keyType, Principal[] issuers) { return new String[] {"DesiredClientCertAlias"}; }

Todos los demás métodos requeridos para la implementación son pasajes a originatingKeyManager .

Entonces, cuando realmente configuramos el contexto:

SSLContext context = SSLContext.getInstance("TLSv1"); context.init(new KeyManager[] { new FilteredKeyManager((X509KeyManager)originalKeyManagers[0], desiredCertsForConnection) }, trustManagerFactory.getTrustManagers(), new SecureRandom());

Espero que eso quede claro, y que funcione para cualquiera que intente resolver este problema.


Mi impresión del KeyManager es que una vez que se inicializa con el almacén de claves, utiliza el alias de la entrada de clave privada para encontrar el certificado asociado y la cadena de certificados.
De lo contrario, creo que elige una cadena basada en los tipos de clave y las autoridades de certificación reconocidas por el host.
Entonces, en su caso, su descripción no menciona una entrada privada en el almacén de claves, por lo que supongo que el administrador de claves elige el certificado más adecuado.
No conozco en absoluto la propiedad del sistema que mencionas.
-Trate de cambiar el almacén de claves para tener una clave privada y la cadena asociada
-O (no estoy seguro de si esto funcionará) cambie el alias del certificado que desea enviar al servidor para que coincida con el nombre del sujeto del certificado


Respuesta corta: no se puede hacer con la implementación predeterminada de Java SSL.

Respuesta larga: sun.security.ssl.ClientHandshaker cómo se implementa el sun.security.ssl.ClientHandshaker enlace SSL en sun.security.ssl.ClientHandshaker . En su método, serverHelloDone se llama X509ExtendedKeyManager.chooseClientAlias . Sus implementaciones se realizan realmente de tal manera que devuelven el primer alias, cuya entrada coincide con el algoritmo de clave dado y algunas otras cosas. De ninguna manera cómo ajustar la selección de alias.

Para aquellos que pueden cambiar el código, esto parece una solución prometedora: http://www.44342.com/java-f392-t785-p1.htm