Pregunta ¿Cómo se elige el certificado de cliente SSL cuando hay varios certificados coincidentes?


No es algo que debería suceder por diseño, pero por cuestiones de seguridad, me pregunto cómo se enviará el certificado "correcto" al servidor, suponiendo que hay más de un certificado que coincida con el requisito de estar firmado por una determinada CA.

Estoy usando un simple cliente de ejemplo SSL JAVA, conectándome a un Apache HTTPD.

Intenté realizar pruebas con 4 certificados, cada vez eliminando el elegido y anotando quién fue el siguiente. No pude encontrar una lógica razonable (es decir, fecha, nombre de alias, etc.) que no sea una orden lexicográfica del "sha256" de los certificados. eso me parece poco probable ...

El cliente de ejemplo hace algo así como

System.setProperty("javax.net.ssl.keyStore","device.p12");  
System.setProperty("javax.net.ssl.keyStorePassword","password");  
System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");  
System.setProperty("javax.net.ssl.trustStore","truststore.jks");  
System.setProperty("javax.net.ssl.trustStorePassword","password");  
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();  
SSLSocket sslSock = (SSLSocket) factory.createSocket("87.69.60.100",443);  
BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(sslSock.getOutputStream(), "UTF8"));  
wr.write("GET /lather HTTP/1.1\r\nhost: 87.69.60.100\r\n\r\n");  
wr.flush();  

Y el Apache está configurado con

SSLCACertificateFile rootCA.crt  
SSLVerifyClient require  

No pude encontrar la documentación relevante para responder a la pregunta. También me estoy preguntando: ¿hay alguna posibilidad de que Apache envíe de alguna manera más de una cadena de certificados? (digamos con un cliente que se comporta mal enviando algo raro).

¡Gracias!


5
2018-05-07 20:10


origen


Respuestas:


Un servidor que requiera autenticación del cliente enviará una lista de tipos de certificados aceptables, posiblemente junto con una lista de CA aceptables. Por defecto, su cliente Java aplica el siguiente algoritmo:

  1. Para cada tipo de certificado (RSA, DSA, EC) aceptado por el servidor, busque los pares de claves públicas / privadas en el almacén de claves que se hayan generado con el algoritmo especificado
  2. Si el servidor envió una lista de CA aceptables, elimine cualquier par de claves que no contenga ninguna de las CA en la lista en su cadena de certificados
  3. Si queda al menos un par de claves, seleccione la clave privada correspondiente a la primera; De lo contrario, vuelva al paso 1 para el siguiente tipo de clave.

El algoritmo de elección de certificado de cliente no se especifica en RFC 5246, pero la implementación predeterminada simple de Java parece razonable, si está sujeta a cambios en el futuro, como lo señala EJP. En particular, el 'primero' es bastante aleatorio: las credenciales se almacenan actualmente en un Map, por lo que dependerá del orden de iteración del conjunto de entradas. También el KeyManager las implementaciones son conectables, y hay una implementación 'NewSun' disponible con OpenJDK que se activa al pasar la propiedad de seguridad ssl.KeyManagerFactory.algorithm=NewSunX509. Este segundo también tendrá en cuenta los atributos keyUsage y extendedKeyUsage de sus certificados de cliente, así como las fechas de caducidad.

Si necesita garantizar el certificado enviado desde una lista de posibilidades y encuentra que los comportamientos predeterminados no lo están haciendo por usted, su mejor opción es crear manualmente un almacén de claves de una sola entrada y usarlo para inicializar un SSLContext, o escribe tu propia implementación de X509KeyManager hacer lo que quieras en chooseClientAlias, como en las respuestas a esta pregunta o esta pregunta.


8
2018-06-01 21:19