br.gov.frameworkdemoiselle.certificate.signer.util.ValidadorUtil.java Source code

Java tutorial

Introduction

Here is the source code for br.gov.frameworkdemoiselle.certificate.signer.util.ValidadorUtil.java

Source

/*
 * Demoiselle Framework
 * Copyright (C) 2010 SERPRO
 * ----------------------------------------------------------------------------
 * This file is part of Demoiselle Framework.
 *
 * Demoiselle Framework is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License version 3
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License version 3
 * along with this program; if not,  see <http://www.gnu.org/licenses/>
 * or write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA  02110-1301, USA.
 * ----------------------------------------------------------------------------
 * Este arquivo  parte do Framework Demoiselle.
 *
 * O Framework Demoiselle  um software livre; voc pode redistribu-lo e/ou
 * modific-lo dentro dos termos da GNU LGPL verso 3 como publicada pela Fundao
 * do Software Livre (FSF).
 *
 * Este programa  distribudo na esperana que possa ser til, mas SEM NENHUMA
 * GARANTIA; sem uma garantia implcita de ADEQUAO a qualquer MERCADO ou
 * APLICAO EM PARTICULAR. Veja a Licena Pblica Geral GNU/LGPL em portugus
 * para maiores detalhes.
 *
 * Voc deve ter recebido uma cpia da GNU LGPL verso 3, sob o ttulo
 * "LICENCA.txt", junto com esse programa. Se no, acesse <http://www.gnu.org/licenses/>
 * ou escreva para a Fundao do Software Livre (FSF) Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA.
 */
package br.gov.frameworkdemoiselle.certificate.signer.util;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.Security;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.CertPathValidatorResult;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXCertPathValidatorResult;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.DERObject;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import br.gov.frameworkdemoiselle.certificate.ca.manager.CAManager;
import br.gov.frameworkdemoiselle.certificate.signer.SignerException;

public class ValidadorUtil {

    public enum CertPathEncoding {

        PKCS7, PkiPath
    }

    /**
     * Valida uma assinatura digital ou um certificado digital tomando por base
     * o certificado raiz da ICP-Brasil
     *
     * @param contentSigned
     * @param trustedCa
     * @param encoding
     * @throws SignerException
     */
    public static void validate(byte[] contentSigned, String policyOID, CertPathEncoding encoding)
            throws SignerException {
        X509Certificate userCertificate = null;
        Collection<X509Certificate> trustedCas = CAManager.getInstance().getSignaturePolicyRootCAs(policyOID);
        try {

            CertificateFactory factory = CertificateFactory.getInstance("X.509", "BC");
            InputStream in = new ByteArrayInputStream(new byte[512]);

            Security.addProvider(new BouncyCastleProvider());
            in = new ByteArrayInputStream(contentSigned);
            CertPath certPath = null;

            switch (encoding) {
            case PKCS7:
                certPath = factory.generateCertPath(in, "PKCS7");
                break;

            case PkiPath:
                certPath = factory.generateCertPath(in, "PkiPath");
                break;
            }

            userCertificate = (X509Certificate) certPath.getCertificates().iterator().next();

            // Carrega os certificados confiaveis
            List<TrustAnchor> trustAnchors = new ArrayList<TrustAnchor>();
            for (X509Certificate x : trustedCas) {
                trustAnchors.add(new TrustAnchor(x, null));
            }

            Set trust = new HashSet();
            Collections.addAll(trust, trustAnchors.toArray());

            // Create the parameters for the validator
            PKIXParameters params = new PKIXParameters(trust);

            params.setSigProvider("BC");
            params.setRevocationEnabled(false);
            CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX");
            CertPathValidatorResult result = certPathValidator.validate(certPath, params);

            // Get the CA used to validate this path
            PKIXCertPathValidatorResult pkixResult = (PKIXCertPathValidatorResult) result;
            TrustAnchor trustAnchor = pkixResult.getTrustAnchor();
            X509Certificate cert = trustAnchor.getTrustedCert();

        } catch (Throwable error) {
            error.printStackTrace();
            //            if (error.getCause() instanceof CertificateExpiredException) {
            //                throw new SignerException("O certificado de uma das cadeias est expirado", error);
            //            }

            try {
                CAManager.getInstance().validateRootCAs(trustedCas, userCertificate);
            } catch (Throwable managerError) {
                managerError.printStackTrace();
                throw new SignerException("Este certificado nao esta associado a uma cadeia confiavel de ACs",
                        error);
            }
        }
    }

    public static void validate(X509Certificate certificate) {
        /*
         * Assinaturas digitais geradas segundo esta Poltica de Assinatura
         * devero ser criadas com chave privada associada ao certificado
         * ICP-Brasil * tipo A1 (do OID 2.16.76.1.2.1.1 ao OID
         * 2.16.76.1.2.1.100), tipo A2 (do OID 2.16.76.1.2.2.1 ao OID
         * 2.16.76.1.2.2.100), do tipo A3 (do OID 2.16.76.1.2.3.1 ao OID
         * 2.16.76.1.2.3.100) e do tipo A4 (do OID 2.16.76.1.2.4.1 ao OID
         * 2.16.76.1.2.4.100), conforme definido em DOC-ICP-04.
         */

        try {
            byte[] val1 = certificate.getExtensionValue("2.5.29.32");
            ASN1InputStream ans1InputStream = new ASN1InputStream(new ByteArrayInputStream(val1));
            DERObject derObject = ans1InputStream.readObject();
            ans1InputStream.close();
            DEROctetString derOctetString = (DEROctetString) derObject;
            byte[] val2 = derOctetString.getOctets();
            ASN1InputStream asn1InputStream2 = new ASN1InputStream(new ByteArrayInputStream(val2));
            DERObject derObject2 = asn1InputStream2.readObject();
            asn1InputStream2.close();
            DERSequence derSequence = (DERSequence) derObject2;
            DERSequence derObject3 = (DERSequence) derSequence.getObjectAt(0).getDERObject();
            DERObjectIdentifier objectIdentifier = (DERObjectIdentifier) derObject3.getObjectAt(0);
            String identificador = objectIdentifier.toString();

            if (!(identificador.startsWith("2.16.76.1.2.1.") || identificador.startsWith("2.16.76.1.2.2.")
                    || identificador.startsWith("2.16.76.1.2.3.") || identificador.startsWith("2.16.76.1.2.4."))) {
                throw new SignerException("O OID no corresponde a uma Poltica de Certificado.");
            }

            int sufixo = Integer.parseInt(identificador.substring(identificador.lastIndexOf(".") + 1));
            if (sufixo < 1 || sufixo > 100) {
                throw new SignerException("O certificado deve ser do tipo A1, A2, A3 ou A4.");
            }

        } catch (Throwable error) {
            throw new SignerException(
                    "A assinaturas digital deve ser criada com chave privada associada ao certificado ICP-Brasil tipo A1, A2, A3 ou A4",
                    error);
        }
    }
}