Hay algún código en nuestro sistema para generar automáticamente certificados autofirmados en un almacén de claves que luego Jetty utiliza. Si una clave para un equipo dado que ya existe, entonces no pasa nada, pero si no existe, se genera una nueva clave, como esto:Si hay más de un certificado en el almacén de claves de Jetty, ¿cómo elige?
public void generateKey(String commonName) {
X500Name x500Name = new X500Name("CN=" + commonName);
CertAndKeyGen keyPair = new CertAndKeyGen("DSA", "SHA1withDSA");
keyPair.generate(1024);
PrivateKey privateKey = keyPair.getPrivateKey();
X509Certificate certificate = keyPair.getSelfCertificate(x500Name, 20*365*24*60*60);
Certificate[] chain = { certificate };
keyStore.setEntry(commonName, privateKey, "secret".toCharArray(), chain);
}
Todo esto funciona bien siempre y cuando sólo hay una clave y el certificado en la tienda de llaves Una vez que tenga varias claves, ocurren cosas extrañas cuando intenta conectarse:
java.io.IOException: HTTPS hostname wrong: should be <127.0.0.1>
Esto fue un error bastante desconcertante pero finalmente lograron localizarlo escribiendo una prueba de unidad que se conecta al servidor y afirma que el CN en el certificado coincide con el nombre de host. Lo que encontré fue bastante interesante: Jetty parece elegir arbitrariamente qué certificado presentar al cliente, pero de manera consistente.
Por ejemplo:
- Si "CN = localhost" y "CN = cheese.mydomain" están en el almacén de claves, siempre eligieron "CN = cheese.mydomain".
- Si "CN = 127.0.0.1" y "CN = cheese.mydomain" están en el almacén de claves, siempre eligió "CN = cheese.mydomain".
- Si "CN = 192.168.222.100" (cheese.mydomain) y "CN = cheese.mydomain" están en el almacén de claves, siempre eligió "CN = 192.168.222.100".
Escribí un código que recorre los certificados en la tienda para imprimirlos y descubrí que no siempre está eligiendo el primer certificado o algo trivial como ese.
¿Qué criterios exactamente utiliza? Inicialmente pensé que localhost era especial, pero luego el tercer ejemplo me desconcertó por completo.
Supongo que de alguna manera esto es decidido por KeyManagerFactory, que es SunX509 en mi caso.
Sí, también descubrimos lo mismo con las direcciones IP, lo que resultó en la escritura de nuestro propio HostnameVerifier para verificar si eso coincide y devuelve verdadero. Originalmente teníamos un HostnameVerifier que siempre devolvía verdadero, que simplemente tenía que descartarse por razones obvias. Muchos usuarios existentes configuraron una dirección IP como su "nombre de host" y no queremos atacar agresivamente eso por el momento. – Trejkaz