/** * LICENCIA LGPL: * * Esta librería es Software Libre; Usted puede redistribuirla y/o modificarla * bajo los términos de la GNU Lesser General Public License (LGPL) tal y como * ha sido publicada por la Free Software Foundation; o bien la versión 2.1 de * la Licencia, o (a su elección) cualquier versión posterior. * * Esta librería se distribuye con la esperanza de que sea útil, pero SIN * NINGUNA GARANTÍA; tampoco las implícitas garantías de MERCANTILIDAD o * ADECUACIÓN A UN PROPÓSITO PARTICULAR. Consulte la GNU Lesser General Public * License (LGPL) para más detalles * * Usted debe recibir una copia de la GNU Lesser General Public License (LGPL) * junto con esta librería; si no es así, escriba a la Free Software Foundation * Inc. 51 Franklin Street, 5º Piso, Boston, MA 02110-1301, USA o consulte * . * * Copyright 2011 Agencia de Tecnología y Certificación Electrónica */ package es.accv.arangi.base.device; import java.io.IOException; import java.lang.reflect.Field; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.KeyStoreSpi; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Collection; import org.apache.log4j.Logger; import es.accv.arangi.base.exception.device.OpeningDeviceException; import es.accv.arangi.base.exception.device.WindowsNotFoundException; /** * SOLO FUNCIONA CON VERSIONES DE JAVA A PARTIR DE LA 1.6.

* * Clase para tratar el almacén de claves personal de Windows, es decir * el que contiene los certificados que no son de autoridades de certificación.

* * Ejemplo de uso:

* * * IDocument document = new FileDocument(new File ("/documento.txt"));
* PersonalWindowsKeyStoreManager manager = new PersonalWindowsKeyStoreManager ();
* String aliases = manager.getAliasNamesList();
* for (int i=0;i *   System.out.println ("Certificate: " + manager.getCertificate(aliases[i]));
*   System.out.println ("Firma: " + manager.signDocument(document, aliases[i])); // Firma con la clave privada del alias
* }
*
* * @author José M Gutiérrez */ public class PersonalWindowsKeyStoreManager extends AbstractBrowserKeyStoreManager { /* * Logger de la clase */ Logger logger = Logger.getLogger(PersonalWindowsKeyStoreManager.class); //-- Constructores /** * Constructor: inicializa el keystore personal de Windows. * * @throws OpeningDeviceException Error abriendo el keystore personal de Windows * @throws WindowsNotFoundException No existe el almacén de claves de Windows debido * a que la ejecución se produce en un sistema operativo diferente */ public PersonalWindowsKeyStoreManager () throws OpeningDeviceException, WindowsNotFoundException { if (!System.getProperty("os.name").contains("indows")) { logger.info("[PersonalWindowsKeyStoreManager]:: El sistema operativo no es Windows sino " + System.getProperty("os.name")); throw new WindowsNotFoundException("El sistema operativo no es Windows sino " + System.getProperty("os.name")); } this.pin = ""; this.ksType = STORE_TYPE_PERSONAL_WINDOWS; try { this.ks = KeyStore.getInstance("Windows-MY"); ks.load(null); } catch (KeyStoreException e) { logger.info("[PersonalWindowsKeyStoreManager]::No se puede obtener una instancia del keystore personal de Windows", e); throw new OpeningDeviceException ("No se puede obtener una instancia del keystore personal de Windows", e); } catch (NoSuchAlgorithmException e) { logger.info("[PersonalWindowsKeyStoreManager]::No existe el algoritmo que comprueba la integridad del keystore personal de Windows", e); throw new OpeningDeviceException ("No existe el algoritmo que comprueba la integridad del keystore personal de Windows", e); } catch (CertificateException e1) { logger.info("[PersonalWindowsKeyStoreManager]::Alguno de los certificados del dispositivo no puede ser cargado", e1); throw new OpeningDeviceException ("Alguno de los certificados del dispositivo no puede ser cargado", e1); } catch (IOException e1) { logger.info("[PersonalWindowsKeyStoreManager]::Error de entrada/salida cargando el keystore personal de Windows", e1); throw new OpeningDeviceException ("Error de entrada/salida cargando el keystore personal de Windows", e1); } //-- Renombrar los alias (en IExplorer pueden estar repetidos) try { cleanCAPIDuplicateAliases(ks); } catch (Throwable e) { logger.info("[PersonalWindowsKeyStoreManager]::No se han podido renombrar los alias duplicados en el repositorio de Windows", e); } } //-- Métodos públicos /** * Cerrar el keystore y eliminar el provider de SUN de la lista de proveedores */ public void close() { logger.debug ("Cerrando Keystore..."); ks = null; logger.debug("Cerrado Keystore...OK"); } @Override public void initialize() { try { this.ks = KeyStore.getInstance("Windows-MY"); ks.load(null); cleanCAPIDuplicateAliases(ks); } catch (Throwable e) { logger.error("[PersonalWindowsKeyStoreManager.initialize]:: Error al reinicializar el KeyStore", e); } } /* (non-Javadoc) * @see es.accv.arangi.base.device.DeviceManager#isAliasFree(java.lang.String) */ public boolean isAliasFree(String alias){ logger.debug ("[PersonalWindowsKeyStoreManager.isAliasFree]::Entrada::" + alias); boolean isFree = false; try { isFree = !ks.containsAlias(alias); } catch (KeyStoreException e) { logger.info("[PersonalWindowsKeyStoreManager.isAliasFree]::Error comprobando si existe el alias '" + alias + "'", e); } return isFree; } //-- Métodos privados static void cleanCAPIDuplicateAliases(KeyStore keyStore) throws Throwable { Field field; KeyStoreSpi keyStoreVeritable; field = keyStore.getClass().getDeclaredField("keyStoreSpi"); field.setAccessible(true); keyStoreVeritable = (KeyStoreSpi)field.get(keyStore); if("sun.security.mscapi.KeyStore$MY".equals(keyStoreVeritable.getClass().getName())) { Collection entries; String alias, hashCode; X509Certificate[] certificates; field = keyStoreVeritable.getClass().getEnclosingClass().getDeclaredField("entries"); field.setAccessible(true); entries = (Collection)field.get(keyStoreVeritable); for(Object entry : entries) { field = entry.getClass().getDeclaredField("certChain"); field.setAccessible(true); certificates = (X509Certificate[])field.get(entry); hashCode = Integer.toString(certificates[0].hashCode()); field = entry.getClass().getDeclaredField("alias"); field.setAccessible(true); alias = (String)field.get(entry); if(!alias.equals(hashCode)) { field.set(entry, alias.concat(" - ").concat(hashCode)); } } } } }