solucion - ¿Por qué java no envía el certificado del cliente durante el protocolo de enlace SSL?
error ssl solucion (2)
Estoy intentando conectarme a un servicio web seguro.
Recibí un error de saludo aunque mi keystore y truststore se configuraron correctamente.
Después de varios días de frustración, de buscar en Google sin parar y de preguntar a todos los alrededores, descubrí que el único problema era que Java decidió no enviar el certificado del cliente al servidor durante el intercambio de información.
Específicamente:
- El servidor solicitó un certificado de cliente (CN = RootCA), es decir, "dame un certificado firmado por la CA raíz".
- Java miró en el almacén de claves y solo encontró el certificado de mi cliente que está firmado por el "SubCA", que a su vez es emitido por el "RootCA". No se molestó en mirar en el almacén de confianza ... duh OK, supongo
- Lamentablemente, cuando traté de agregar el certificado "SubCA" al almacén de claves, eso no ayudó en absoluto. Verifiqué si los certificados se cargan en el almacén de claves. Sí lo hacen, pero el KeyManager ignora todos los certificados excepto el del cliente.
- Todo lo anterior lleva al hecho de que Java decide que no tiene ningún certificado que satisfaga la solicitud del servidor y no envía nada ... tadaaa falla de handshake :-(
Mis preguntas:
- ¿Es posible que agregue el certificado "SubCA" al almacén de claves de una manera que "rompió la cadena de certificados" o algo así para que KeyManager solo cargue el certificado del cliente e ignore el resto? (Chrome y openssl logran resolver eso, ¿por qué no puede Java? - tenga en cuenta que el certificado "SubCA" siempre se presenta por separado como la autoridad de confianza, por lo que aparentemente Chrome lo empaqueta junto con el certificado del cliente durante el saludo)
- ¿Es esto un "problema de configuración" formal en el lado del servidor? El servidor es un tercero. Esperaría que el servidor solicite un certificado firmado por la autoridad "SubCA" ya que eso es lo que nos proporcionaron. Sospecho que el hecho de que esto funcione en Chrome y en openssl es porque son "menos restrictivos" y java simplemente va "por el libro" y falla.
Me las arreglé para armar una solución sucia para esto, pero no estoy muy feliz por eso, así que me alegrará si alguien puede aclararme esta.
Como un agregado aquí, puede usar %> openssl s_client -connect host.example.com:443 y ver el volcado y verificar que todo el certificado principal sea válido contra el cliente. Usted está buscando esto en la parte inferior de la salida. Verificar código de retorno: 0 (ok)
Si agrega -showcerts arrojará toda la información del llavero que se envió junto con el certificado del host, que es lo que cargó en su llavero.
Es posible que haya importado el certificado CA intermedio en el almacén de claves sin asociarlo con la entrada donde tiene su certificado de cliente y su clave privada. Debería poder ver esto usando keytool -v -list -keystore store.jks
. Si solo obtiene un certificado por entrada de alias, no están juntos.
Debería importar su certificado y su cadena en el alias de almacén de claves que tiene su clave privada.
Para saber qué alias de almacén de claves tiene la clave privada, use keytool -list -keystore store.jks
(supongo que aquí está el tipo de tienda JKS). Esto te dirá algo como esto:
Your keystore contains 1 entry
myalias, Feb 15, 2012, PrivateKeyEntry,
Certificate fingerprint (MD5): xxxxxxxx
Aquí, el alias es myalias
. Si usa -v
además de esto, debería ver el Alias Name: myalias
.
Si aún no lo tiene por separado, exporte su certificado de cliente desde el almacén de claves:
keytool -exportcert -rfc -file clientcert.pem -keystore store.jks -alias myalias
Esto debería darle un archivo PEM.
Usando un editor de texto (o cat
), prepare el archivo (llamémoslo bundle.pem
) con ese certificado de cliente y el certificado de CA intermedio (y posiblemente el certificado de CA raíz si lo desea), para que el certificado de cliente esté en el comenzando y su certificado de emisor está justo debajo.
Esto debería verse así:
-----BEGIN CERTIFICATE-----
MIICajCCAdOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVSzEa
....
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICkjCCAfugAwIBAgIJAKm5bDEMxZd7MA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV
....
-----END CERTIFICATE-----
Ahora, importe este paquete nuevamente en el alias donde está su clave privada:
keytool -importcert -keystore store.jks -alias myalias -file bundle.pem