Java tutorial
/* * File: CRLValidationHandler.java * * Created on Nov 7, 2007 * * * Copyright 2006-2007 Felix Garcia Borrego (borrego at gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.viafirma.nucleo.validacion; import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.cert.CRL; import java.security.cert.CRLException; import java.security.cert.CertPath; import java.security.cert.CertPathValidator; import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorResult; import java.security.cert.CertStore; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.CollectionCertStoreParameters; import java.security.cert.PKIXParameters; import java.security.cert.PolicyNode; import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.viafirma.excepciones.CodigoError; import org.viafirma.excepciones.ExcepcionErrorInterno; /** * Manejador de las validaciones basadas en CRLs y certpath * * @author Felix Garcia Borrego (borrego@gmail.com) */ public class CRLValidationHandler { /** * Crea un nuevo validador, recuperando los certificados de confianza. * * @param certificadosConfianza */ public CRLValidationHandler(boolean validacionOnline, Set<TrustAnchor> certificadosConfianza) { this.certificadosConfianza = certificadosConfianza; this.validacionOnline = validacionOnline; } /** * Metodo encargado de la verificacin de los certificados * * @param certificadoX509 * @throws ExcepcionErrorInterno */ public CodigoError validarCRL(X509Certificate certificadoX509) { try { // 1.- Inicia la factoria de certificados CertificateFactory factoriaCertificados = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME); log.debug("Validando certificado perteneciente a: " + certificadoX509.getIssuerDN()); CertPathValidator validador = CertPathValidator.getInstance("PKIX", BouncyCastleProvider.PROVIDER_NAME); // 2.- Configuracin de los parametros del validador // 2.1.- Para comprobar que el camino de confianza no esta roto, // tengo en cuenta todos los certificados PKIXParameters parametros = new PKIXParameters(certificadosConfianza); // Fecha para la comprobacin de validez. parametros.setDate(new Date()); if (validacionOnline) { // Para la validacin online de del estado de revocacin de los // certificados // ************ // creo un almacen( cache ) de certificados y CRLs para no tener // que conectarme a las crls // en cada validacin // Genero un listado de las CRLS que vamos a utilizar para la // validacin del certificado. List<CRL> listaCRLsCertificadosAlmacenados = new LinkedList<CRL>(); // Aade las crls de los certificados de confianza reconocidos // por Viafirma. // estos certificados son los marcados con el prefijo viafirma_ for (TrustAnchor trustAnchor : certificadosConfianza) { // TODO establecer un sistema de cache eficiente // TODO recuperar solo las crls del certificado en uso. listaCRLsCertificadosAlmacenados .addAll(CRLUtil.getCurrentInstance().getCRLs(trustAnchor.getTrustedCert())); // para cada certificado. } // aado al listado todas las crls del certificado actual. EJ // para el caso de // un certificado de FNMT el certificado personal contiene CN = // CRL1827,OU = FNMT Clase 2 CA,O = FNMT,C = ES listaCRLsCertificadosAlmacenados.addAll(CRLUtil.getCurrentInstance().getCRLs(certificadoX509)); // parametros para la creacin del almacen(cache CRLs) CollectionCertStoreParameters params = new CollectionCertStoreParameters( listaCRLsCertificadosAlmacenados); CertStore almacen = CertStore.getInstance("Collection", params, BouncyCastleProvider.PROVIDER_NAME); parametros.addCertStore(almacen); } else { // No se utilizan las CRLs para la comprobacin de la // revocacin. parametros.setRevocationEnabled(false); } // certificados a validar ( solo 1) List<X509Certificate> certificadosValidar = new ArrayList<X509Certificate>(1); certificadosValidar.add(certificadoX509); // genero el listado de certificados a validar CertPath certPath = factoriaCertificados.generateCertPath(certificadosValidar); // validacin CertPathValidatorResult resultado = validador.validate(certPath, parametros); if (log.isDebugEnabled()) { if (resultado instanceof java.security.cert.PKIXCertPathValidatorResult) { // pintamos el arbol de politicas PolicyNode node = ((java.security.cert.PKIXCertPathValidatorResult) resultado).getPolicyTree(); StringBuffer ruta = new StringBuffer( "Certificado vlido: " + certificadoX509.getSubjectDN().getName()); while (node != null) { ruta.append("-->"); ruta.append(node.getValidPolicy()); if (node.getChildren().hasNext()) { node = node.getChildren().next(); } else { node = null; } } log.info("ruta de validacin: " + ruta); } } return CodigoError.OK_CERTIFICADO_VALIDADO; } catch (CertificateException e) { log.fatal(CodigoError.ERROR_INTERNO, e); return CodigoError.ERROR_INTERNO; } catch (NoSuchProviderException e) { log.fatal(CodigoError.ERROR_INTERNO, e); return CodigoError.ERROR_INTERNO; } catch (NoSuchAlgorithmException e) { log.fatal(CodigoError.ERROR_INTERNO, e); return CodigoError.ERROR_INTERNO; } catch (InvalidAlgorithmParameterException e) { log.fatal(CodigoError.ERROR_VALIDACION_CONFIGURACION_PARAMETRO, e); return CodigoError.ERROR_VALIDACION_CONFIGURACION_PARAMETRO; } catch (CRLException e) { log.fatal(CodigoError.ERROR_VALIDACION_CRL, e); return CodigoError.ERROR_VALIDACION_CRL; } catch (CertPathValidatorException e) { // detectamos el tipo de problema if (e.getMessage().contains(java.security.cert.CertificateExpiredException.class.getName()) || e.getMessage().contains("Certificate revocation after") || e.getMessage().contains("NotAfter") || e.getMessage().contains("certificate expired on")) { log.warn("El certificado esta caducado." + e.getMessage() + " " + certificadoX509.getSubjectDN()); return CodigoError.ERROR_VALIDACION_CERTIFICADO_CADUCADO; } else if (e.getMessage().contains(java.security.SignatureException.class.getName())) { log.warn( "Algunos de los certificados en el camino de certificacin no tiene crl. Algunos de los certificados no se puede validar." + e.getMessage() + " " + certificadoX509.getSubjectDN()); return CodigoError.ERROR_VALIDACION_CRL; } else if (e.getMessage().contains("no valid CRL found")) { log.warn("No se ha podido comprobar la validez del certificado. " + e.getMessage() + " " + certificadoX509.getSubjectDN()); return CodigoError.ERROR_VALIDACION_CRL; } else if (e.getMessage().contains("CertPath not found")) { log.warn("Autoridad de certificacin no reconicida." + e.getMessage() + " " + certificadoX509.getIssuerDN()); return CodigoError.ERROR_VALIDACION_AUTORIDAD_NO_RECONOCIDA; } else { log.warn("Autoridad de certificacin no reconicida." + e.getMessage() + " " + certificadoX509.getIssuerDN()); return CodigoError.ERROR_VALIDACION_AUTORIDAD_NO_RECONOCIDA; } // TODO java.security.cert.CertPathValidatorException: couldn't // validate certificate: // java.security.cert.CertificateNotYetValidException: NotBefore: // Thu Apr 19 19:22:17 CEST 2007 // at // org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(PKIXCertPathValidatorSpi.java:819) } } private Log log = LogFactory.getLog(CRLValidationHandler.class); /** * Conjunto de certificados de confianza reconocidos por el sistema. Se * inicializan al arrancar la aplicacin. */ private Set<TrustAnchor> certificadosConfianza; /** * Indica si se conectara remotamente para realizar la validacin. */ private boolean validacionOnline; }