2011-03-29 23 views
8

Necesito construir una cadena de certificados en Windows, desde un certificado de tarjeta inteligente X.509 a través de una o más CA intermedias hasta una CA raíz. Eso es fácil cuando los certificados de CA están en un almacén de claves JKS, pero también necesito usar los almacenes de claves de Windows.¿Acceso Java a CA intermedias desde almacenes de claves de Windows?

Puedo obtener el certificado de CA raíz de "Windows-ROOT", pero no puedo acceder al almacén de claves de "Autoridades de certificación intermedias".

¿Alguien ha hecho esto?

Gracias!

Respuesta

8

El proveedor criptográfico SunMSCAPI solo admite dos almacenes de claves: Windows-MY (almacén de certificados personales) y Windows-ROOT (almacén de certificados de autoridades confiables), por lo que no creo que sea posible acceder directamente a otros almacenes de certificados de Windows. Sin embargo, puede no ser necesario ya que parece que el almacén de claves Windows-MY puede construir cadenas de certificados con los certificados de otras tiendas.

Aquí es un fragmento de código que utilizo para probarlo:

KeyStore ks = KeyStore.getInstance("Windows-MY"); 
ks.load(null, null) ; 
Enumeration en = ks.aliases() ; 
while (en.hasMoreElements()) { 
    String aliasKey = (String)en.nextElement() ; 
    Certificate c = ks.getCertificate(aliasKey) ; 
    System.out.println("---> alias : " + aliasKey) ; 
    if (ks.isKeyEntry(aliasKey)) { 
     Certificate[] chain = ks.getCertificateChain(aliasKey); 
     System.out.println("---> chain length: " + chain.length); 
     for (Certificate cert: chain) { 
      System.out.println(cert); 
    } 
} 

Si añado un único certificado con la clave privada en el almacén de certificados personales de la longitud de la cadena es 1. Después de la adición de la CA de la CA intermedia almacén de certificados de inicio el programa una segunda vez y la longitud de la cadena ahora es 2.

ACTUALIZACIÓN (abril de segundo) es posible agregar mediante programación los certificados en el almacén de claves Windows-MY y Windows-ROOT con algunas limitaciones:

  • al agregar un certificado en el Windows-ROOT se solicita al usuario para su confirmación
  • todo certificado añadió en el almacén de claves Windows-MY es A (desde el punto de vista de almacén de claves, no el punto de vista Windows) TrustedCertificateEntry. El almacén de claves parece construir la cadena más larga posible con todos los certificados disponibles.
  • las certificaciones sin clave privada asociada no están visibles en el navegador del almacén de certificados de Windows, pero es posible eliminarlas mediante programación.

Adición de un certificado en un almacén de claves es sencillo:

Certificate c = CertificateFactory.getInstance("X.509").generateCertificate(new FileInputStream("C:/Users/me/Downloads/myca.crt")); 
KeyStore.TrustedCertificateEntry entry = new KeyStore.TrustedCertificateEntry(c); 
ks.setEntry("CA1", entry , null); 
+0

Sí, no hay ningún problema si el certificado del usuario está en la tienda personal. Me pregunto si puedo agregarlo programáticamente. – Mermeister

+0

Sí, es posible. Actualizo mi respuesta con más detalles. – Jcs

+0

¡Eso funciona! Recupero el certificado de usuario de la tarjeta inteligente, lo agrego programáticamente a la tienda Windows-MY y luego construyo la cadena usando el almacén de claves de Windows. – Mermeister

1

Jcs tenía la respuesta, pero quiero mostrar algo de pseudocódigo así:

// load the Windows keystore 
KeyStore winKeystore = KeyStore.getInstance("Windows-MY", "SunMSCAPI"); 
winKeystore.load(null, null); 

// add the user's smart card cert to the keystore 
winKeystore.setCertificateEntry(myAlias, userCertificate); 

// build the cert chain! this will include intermediate CAs 
Certificate[] chain = winKeystore.getCertificateChain(myAlias); 

cadenas cert de Windows no están validados a medida que se construyen, pero ahora puede hacer lo habitual de crear un CertPath y PKIXParameters y usarlos para validar la cadena.

CertPathValidator certPathValidator = CertPathValidator.getInstance(CertPathValidator.getDefaultType()); 
certPathValidator.validate(certPath, params); 
Cuestiones relacionadas