ec.rubrica.pdf.VerificadorFirmaPdf.java Source code

Java tutorial

Introduction

Here is the source code for ec.rubrica.pdf.VerificadorFirmaPdf.java

Source

/*
 * Copyright (c) 2009-2013 Rubrica.ec
 * 
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 */

package ec.rubrica.pdf;

import java.io.IOException;
import java.security.AccessController;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PrivilegedAction;
import java.security.Security;
import java.security.SignatureException;
import java.security.cert.CRL;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.logging.Logger;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.tsp.TimeStampToken;

import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.security.CertificateInfo;
import com.itextpdf.text.pdf.security.CertificateUtil;
import com.itextpdf.text.pdf.security.CertificateVerification;
import com.itextpdf.text.pdf.security.KeyStoreUtil;
import com.itextpdf.text.pdf.security.PdfPKCS7;

import ec.rubrica.cert.bce.BceSubCert;
import ec.rubrica.cert.bce.BceSubTestCert;
import ec.rubrica.cert.bce.CertificadoBancoCentralFactory;
import ec.rubrica.cert.securitydata.CertificadoSecurityDataFactory;
import ec.rubrica.cert.securitydata.SecurityDataSubCaCert;
import ec.rubrica.cert.securitydata.old.CertificadoSecurityDataOldFactory;
import ec.rubrica.ocsp.OcspTimeoutException;
import ec.rubrica.ocsp.OcspValidationException;
import ec.rubrica.ocsp.ValidadorOCSP;

/**
 * Verifica una firma digital sobre un documento PDF utilizando iText.
 * 
 * @author Ricardo Arguello (ricardo.arguello@soportelibre.com)
 */
public class VerificadorFirmaPdf {

    /** Campos de un PDF */
    private AcroFields af;

    /** Certificados de CAs del JVM */
    private KeyStore cacerts;

    private static final Logger log = Logger.getLogger(VerificadorFirmaPdf.class.getName());

    static {
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                Security.addProvider(new BouncyCastleProvider());
                return null;
            }
        });
    }

    public VerificadorFirmaPdf(byte[] pdf) throws IOException {
        PdfReader pdfReader = new PdfReader(pdf);
        this.af = pdfReader.getAcroFields();
        this.cacerts = KeyStoreUtil.loadCacertsKeyStore();
    }

    public Verificacion verificar() throws OcspValidationException, SignatureException {
        int totalRevisiones = af.getTotalRevisions();
        Verificacion verificacion = new Verificacion(totalRevisiones);

        ArrayList<String> nombres = af.getSignatureNames();
        System.out.println("Cuantos nombres=" + nombres.size());

        for (String nombre1 : nombres) {
            System.out.println("nombre=" + nombre1);
            PdfPKCS7 pk = af.verifySignature(nombre1);
            X509Certificate certificadoFirmante = pk.getSigningCertificate();
            log.info("Subject: " + CertificateInfo.getSubjectFields(pk.getSigningCertificate()));
            Certificate[] chain = pk.getSignCertificateChain();

            // Verificar OCSP:
            try {
                verificarOscp(certificadoFirmante);
            } catch (OcspTimeoutException e) {
                throw new SignatureException(e);
            }
        }

        for (String nombre : nombres) {
            PdfPKCS7 pk = af.verifySignature(nombre);

            boolean firmaCubreTodoDocumento = af.signatureCoversWholeDocument(nombre);

            int revision = af.getRevision(nombre);

            X509Certificate certificadoFirmante = pk.getSigningCertificate();
            log.info("Subject: " + CertificateInfo.getSubjectFields(pk.getSigningCertificate()));

            Calendar fechaFirma = pk.getSignDate();
            TimeStampToken tst = pk.getTimeStampToken();

            if (tst != null) {
                log.fine("La firma Tiene Time Stamp");
                fechaFirma = pk.getTimeStampDate();
            }

            boolean selladoTiempoCorrecto = false;

            if (!pk.isTsp() && tst != null) {
                try {
                    selladoTiempoCorrecto = pk.verifyTimestampImprint();
                } catch (NoSuchAlgorithmException e) {
                    throw new SignatureException(e);
                }
            }

            Certificate[] certificados = pk.getCertificates();

            // TODO: DEBUG
            Certificate[] chain = pk.getSignCertificateChain();
            for (int i = 0; i < chain.length; i++) {
                X509Certificate cert = (X509Certificate) chain[i];
                System.out.println(String.format("[%s] %s", i, cert.getSubjectDN()));
                System.out.println(CertificateUtil.getOCSPURL(cert));
            }
            // TODO: DEBUG

            boolean documentoModificado = !pk.verify();

            Firma firma = new Firma(nombre, firmaCubreTodoDocumento, revision, certificadoFirmante, fechaFirma,
                    selladoTiempoCorrecto, certificados, documentoModificado);

            // TODO: Implementar CRLs
            Collection<CRL> crls = null;

            Object error[] = CertificateVerification.verifyCertificates(certificados, cacerts, crls, fechaFirma);

            // TODO: Quitar el mensaje y usar una Enum
            if (error != null) {
                Object objetoConFalla = error[0];
                String mensaje = (String) error[1];

                Falla falla;

                if (objetoConFalla != null) {
                    Certificate certConFalla = (Certificate) objetoConFalla;
                    falla = new Falla(certConFalla, mensaje);
                } else {
                    falla = new Falla(mensaje);
                }

                firma.setFalla(falla);
            }

            verificacion.addFirma(firma);
        }

        return verificacion;
    }

    private void verificarSiTieneOCSP(Certificate[] chain) {
        for (int i = 0; i < chain.length; i++) {
            X509Certificate cert = (X509Certificate) chain[i];
            System.out.println(String.format("[%s] %s", i, cert.getSubjectDN()));
            System.out.println(CertificateUtil.getOCSPURL(cert));
        }
    }

    private void verificarOscp(X509Certificate certificado) throws OcspTimeoutException, OcspValidationException {

        X509Certificate subCert = null;

        if (CertificadoSecurityDataFactory.esCertificadoDeSecurityData(certificado)
                || CertificadoSecurityDataOldFactory.esCertificadoDeSecurityDataOld(certificado)) {
            subCert = new SecurityDataSubCaCert();
        } else if (CertificadoBancoCentralFactory.esCertificadoDelBancoCentral(certificado)) {
            if (CertificadoBancoCentralFactory.estTestCa(certificado)) {
                subCert = new BceSubTestCert();
            } else {
                subCert = new BceSubCert();
            }
        }

        // Validar
        ValidadorOCSP.check(subCert, certificado);
    }

    // iText 5.4.0:
    /*
     * public void checkRevocation(PdfPKCS7 pkcs7, X509Certificate signCert,
     * X509Certificate issuerCert, Date date) throws GeneralSecurityException,
     * IOException { List<BasicOCSPResp> ocsps = new ArrayList<BasicOCSPResp>();
     * if (pkcs7.getOcsp() != null) ocsps.add(pkcs7.getOcsp()); OCSPVerifier
     * ocspVerifier = new OCSPVerifier(null, ocsps); List<VerificationOK>
     * verification = ocspVerifier.verify(signCert, issuerCert, date); if
     * (verification.size() == 0) { List<X509CRL> crls = new
     * ArrayList<X509CRL>(); if (pkcs7.getCRLs() != null) { for (CRL crl :
     * pkcs7.getCRLs()) crls.add((X509CRL) crl); } CRLVerifier crlVerifier = new
     * CRLVerifier(null, crls); verification.addAll(crlVerifier.verify(signCert,
     * issuerCert, date)); } if (verification.size() == 0) {
     * System.out.println("The signing certificate couldn't be verified"); }
     * else { for (VerificationOK v : verification) System.out.println(v); } }
     */
}