package gov.pr.celepar.tabeliao.core;
/*
Este programa � licenciado de acordo com a
LPG-AP (LICEN�A P�BLICA GERAL PARA PROGRAMAS DE COMPUTADOR DA ADMINISTRA��O P�BLICA),
vers�o 1.1 ou qualquer vers�o posterior.
A LPG-AP deve acompanhar todas PUBLICA��ES, DISTRIBUI��ES e REPRODU��ES deste Programa.
Caso uma c�pia da LPG-AP n�o esteja dispon�vel junto com este Programa, voc� pode contatar o LICENCIANTE ou ent�o acessar diretamente:
http://www.celepar.pr.gov.br/licenca/LPG-AP.pdf
Para poder USAR, PUBLICAR, DISTRIBUIR, REPRODUZIR ou ALTERAR este Programa
� preciso estar de acordo com os termos da LPG-AP
*/
import gov.pr.celepar.framework.exception.ApplicationException;
import gov.pr.celepar.framework.util.Data;
import gov.pr.celepar.tabeliao.core.validacao.TabeliaoResultadoValidacao;
import gov.pr.celepar.tabeliao.dao.CertificadoAcDAO;
import gov.pr.celepar.tabeliao.dao.CertificadoRevogadoDAO;
import gov.pr.celepar.tabeliao.dao.factory.DAOFactory;
import gov.pr.celepar.tabeliao.database.HibernateUtil;
import gov.pr.celepar.tabeliao.pojo.CertificadoAc;
import gov.pr.celepar.tabeliao.pojo.CertificadoPublico;
import gov.pr.celepar.tabeliao.pojo.CertificadoRevogado;
import gov.pr.celepar.tabeliao.util.Download;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import org.apache.log4j.Logger;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.DERObject;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.x509.CRLDistPoint;
import org.bouncycastle.asn1.x509.DistributionPoint;
import org.bouncycastle.asn1.x509.PolicyInformation;
import org.bouncycastle.asn1.x509.X509Extensions;
/**
* Classe TabeliaoCertificate<br>
* <br>
* Essa classe encapsula um objeto do tipo X509Certificate e gera interfaces<br>
* para leitura das informacoes contidas no certificado.
*
* @author Thiago Meneghello <thiagomeneghello@ecelepar.pr.gov.br>
*
*/
public class TabeliaoCertificate {
private static Logger logger = Logger.getLogger(TabeliaoCertificate.class);
public static final String OID_CERTIFICADO_A1 = "2.16.76.1.2.1";
public static final String OID_CERTIFICADO_A2 = "2.16.76.1.2.2";
public static final String OID_CERTIFICADO_A3 = "2.16.76.1.2.3";
public static final String OID_CERTIFICADO_A4 = "2.16.76.1.2.4";
public static final String OID_CERTIFICADO_S1 = "2.16.76.1.2.101";
public static final String OID_CERTIFICADO_S2 = "2.16.76.1.2.102";
public static final String OID_CERTIFICADO_S3 = "2.16.76.1.2.103";
public static final String OID_CERTIFICADO_S4 = "2.16.76.1.2.104";
private X509Certificate certificate = null;
private TabeliaoCertificate certificadoGerador = null;
private TabeliaoSubjectAlternativeNames subjectAlternativeNames = null;
private TabeliaoKeyUsage keyUsage = null;
private TabeliaoDN certificadoDe = null;
private TabeliaoDN certificadoPara = null;
private TabeliaoLCR tabeliaoLCR = null;
private TabeliaoResultadoValidacao tabeliaoValidacao = null;
/**********************************************************************************************
* Mehtodos Privados
*********************************************************************************************/
/**
*
* @param data -> array de bytes
* @return String
*/
private String toString(byte[] data){
if(data == null) {
return null;
}
return toString(new BigInteger(1, data));
}
/**
*
* @param bi -> Inteiro longo
* @return String
*/
private String toString(BigInteger bi) {
if(bi == null) {
return null;
}
String ret = bi.toString(16);
if(ret.length() % 2 == 1) {
ret = "0" + ret;
}
return ret.toUpperCase();
}
/**
*
* @param certificadoAc
* @see gov.pr.celepar.tabeliao.pojo.CertificadoAc
* @return X509Certificate
* @throws ApplicationException
* @throws Exception
* @throws IOException
*/
private X509Certificate getCertificate(CertificadoAc certificadoAc)
throws ApplicationException, IOException, Exception {
X509Certificate cert = null;
cert = getCertificate(certificadoAc.getArquivo());
return cert;
}
/**
*
* @param data -> Array de byte
* @return X509Certificate
* @throws Exception
*/
private X509Certificate getCertificate(byte[] data)
throws Exception {
X509Certificate cert = null;
ByteArrayInputStream bis = new ByteArrayInputStream(data);
cert = getCertificate(bis);
bis.close();
bis = null;
return cert;
}
/**
*
* @param is -> InputStream
* @return X509Certificate
* @throws CertificateException
* @throws IOException
* @throws Exception
*/
private X509Certificate getCertificate(InputStream is)
throws CertificateException, IOException, Exception {
X509Certificate cert = null;
CertificateFactory cf = CertificateFactory.getInstance("X509");
cert = (X509Certificate)cf.generateCertificate(is);
return cert;
}
/**********************************************************************************************
* Construtores da Classe
*********************************************************************************************/
/**
*
* @param certificate -> tipo X509Certificate
* @see java.security.cert.X509Certificate
*/
public TabeliaoCertificate(X509Certificate certificate) {
this.certificate = certificate;
}
/**
*
* @param certificadoAc
* @throws ApplicationException
* @throws Exception
*/
public TabeliaoCertificate(CertificadoAc certificadoAc) throws ApplicationException, Exception {
this.certificate = getCertificate(certificadoAc);
}
/**
*
* @param data
* @throws Exception
*/
public TabeliaoCertificate(byte[] data) throws Exception {
this.certificate = getCertificate(data);
}
/**
*
* @param is
* @throws Exception
* @throws IOException
*/
public TabeliaoCertificate(InputStream is) throws IOException, Exception {
this.certificate = getCertificate(is);
}
/**
*
* @param certificadoPublico
* @throws Exception
* @see gov.pr.celepar.tabeliao.pojo.CertificadoPublico
*/
public TabeliaoCertificate(CertificadoPublico certificadoPublico) throws Exception{
this.certificate = getCertificate(certificadoPublico.getArquivo());
}
/**********************************************************************************************
* Metodos que estao revisados
*********************************************************************************************/
/**
* Retorna o certificado no formato original X509Certificate<br>
*
* @return X509Certificate
*/
public X509Certificate getX509Certificate(){
return certificate;
}
/**
* Retorna o IssuerDn do certificado no formato TabeliaoDN que funciona<br>
* como um Properties.<br>
* O metodo toString dessa classe retorna o IssuerDn.getName()<br>
*
* @return TabeliaoDN
* @see TabeliaoDN
* @throws IOException
*/
public TabeliaoDN getCertificadoDe() throws IOException{
if(certificadoDe == null) {
certificadoDe = new TabeliaoDN(certificate.getIssuerDN().getName());
}
return certificadoDe;
}
/**
* Retorna o SerialNumber do certificado no formato de String<br>
*
* @return String
*/
public String getSerialNumber(){
return toString(certificate.getSerialNumber());
}
/**
* Retorna o SubjectDN do certificado no formato TabeliaoDN que funciona<br>
* como um Properties.<br>
* O Metodo toString dessa classe retorna o SubjectDN.getName()<br>
*
* @return TabeliaoDN
* @see TabeliaoDN
* @throws IOException
*/
public TabeliaoDN getCertificadoPara() throws IOException{
if(certificadoPara == null) {
certificadoPara = new TabeliaoDN(certificate.getSubjectDN().getName());
}
return certificadoPara;
}
/**
* Retorna o nome que esta definido no CN do CertificadoPara.<br>
* Equivalente a chamada getCertificadoPara().getProperty("CN") ignorando<br>
* a informacao que aparece depois dos dois pontos.<br>
*
* @return String
*/
public String getNome(){
try {
String nome = this.getCertificadoPara().getProperty("CN");
int pos;
pos = nome.indexOf(":");
if(pos > 0) {
return nome.substring(0, pos);
}
return nome;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
*
* @return Date -> Inicio da Validade
*/
public Date getValidadeDe(){
return certificate.getNotBefore();
}
/**
*
* @return Date -> Fim da validade
*/
public Date getValidadeAte(){
return certificate.getNotAfter();
}
/**
* Retorna um Objeto TabeliaoKeyUsage com as informacoes sobre o Uso<br>
* do certificado.<br>
*
* @return TabeliaoKeyUsage
* @see TabeliaoKeyUsage
*/
public TabeliaoKeyUsage getTabeliaoKeyUsage(){
if(keyUsage == null) {
keyUsage = new TabeliaoKeyUsage(certificate);
}
return keyUsage;
}
/**
* Retorna o SubjectAlternativeNames do certificado no formato<br>
* TabeliaoSubjectAlternativeNames.<br>
* Caso nao exista essa informacao retorna o valor <b>null</b>.<br>
*
* @return TabeliaoSubjectAlternativeNames
* @see TabeliaoSubjectAlternativeNames
*/
public TabeliaoSubjectAlternativeNames getTabeliaoSubjectAlternativeNames(){
if(this.subjectAlternativeNames == null) {
this.subjectAlternativeNames = new TabeliaoSubjectAlternativeNames(this.certificate);
}
return this.subjectAlternativeNames;
}
/**
* Retorna o email que esta definido no SubjectAlternativeNames do certificado.<br>
* Equivalente a chamada getTabeliaoSubjectAlternativeNames().getEmail()<br>
* Caso nao exista essa informacao retorna o valor <b>null</b>.<br>
*
* @return String
*/
public String getEmail(){
if(getTabeliaoSubjectAlternativeNames() == null) {
return null;
}
return getTabeliaoSubjectAlternativeNames().getEmail();
}
/**
* Verifica se o certificado possui dados de Pessoa Fisica.<br>
* Equivalente a chamada getTabeliaoSubjectAlternativeNames().isDadosPF()<br>
*
* @return boolean
*/
public boolean hasDadosPF(){
if(getTabeliaoSubjectAlternativeNames() == null) {
return false;
}
return getTabeliaoSubjectAlternativeNames().isDadosPF();
}
/**
* Retorna os dados de Pessoa Fisica do certificado no formato<br>
* TabeliaoDadosPF.<br>
* Equivalente a chamada getTabeliaoSubjectAlternativeNames().getTabeliaoDadosPF()<br>
* Retorna o valor <b>null</b> caso o certificado nao possua os dados de Pessoa<br>
* Fisica.<br>
*
* @return TabeliaoDadosPF
* @see TabeliaoDadosPF
*/
public TabeliaoDadosPF getTabeliaoDadosPF(){
if(getTabeliaoSubjectAlternativeNames() == null) {
return null;
}
return getTabeliaoSubjectAlternativeNames().getTabeliaoDadosPF();
}
/**
* Verifica se o certificado possui dados de Pessoa Juridica.<br>
* Equivalente a chamada getTabeliaoSubjectAlternativeNames().isDadosPJ()<br>
*
* @return boolean
*/
public boolean hasDadosPJ(){
if(getTabeliaoSubjectAlternativeNames() == null) {
return false;
}
return getTabeliaoSubjectAlternativeNames().isDadosPJ();
}
/**
* Retorna os dados de Pessoa Juridica do certificado no formato<br>
* TabeliaoDadosPJ.<br>
* Equivalente a chamada getTabeliaoSubjectAlternativeNames().getTabeliaoDadosPJ()<br>
* Retorna o valor <b>null</b> caso o certificado nao possua os dados de Pessoa<br>
* Juridica.<br>
*
* @return TabeliaoDadosPJ
* @see TabeliaoDadosPJ
*/
public TabeliaoDadosPJ getTabeliaoDadosPJ(){
if(getTabeliaoSubjectAlternativeNames() == null) {
return null;
}
return getTabeliaoSubjectAlternativeNames().getTabeliaoDadosPJ();
}
/**
* Verifica se o certificado possui dados de Equipamento.<br>
* Equivalente a chamada getTabeliaoSubjectAlternativeNames().isDadosEquipamento()<br>
*
* @return boolean
*/
public boolean hasDadosEquipamento(){
if(getTabeliaoSubjectAlternativeNames() == null) {
return false;
}
return getTabeliaoSubjectAlternativeNames().isDadosEquipamento();
}
/**
* Retorna os dados de Equipamento do certificado no formato<br>
* TabeliaoDadosEquipamento.<br>
* Equivalente a chamada getTabeliaoSubjectAlternativeNames().getTabeliaoDadosEquipamento()<br>
* Retorna o valor <b>null</b> caso o certificado nao possua os dados de Equipamento.<br>
*
* @return TabeliaoDadosEquipamento
* @see TabeliaoDadosEquipamento
*/
public TabeliaoDadosEquipamento geTabeliaoDadosEquipamento(){
if(getTabeliaoSubjectAlternativeNames() == null) {
return null;
}
return getTabeliaoSubjectAlternativeNames().getTabeliaoDadosEquipamento();
}
/**
* Retorna o valor PathLength do BasicConstraint do certificado.<br>
* * <b>0</b> - Caso seja de uma AC.<br>
* * <b>1</b> - Caso seja de Usuario Final.<br>
*
* @return int
*/
public int getPathLength(){
return certificate.getBasicConstraints();
}
/**
* Verifica se o certificado eh de uma Autoridade Certificadora (AC).<br>
* * <b>true</b> - Caso seja de uma AC.<br>
* * <b>false</b> - Caso seja de Usuario Final.<br>
*
* @return boolean
*/
public boolean isCertificadoAc(){
return certificate.getBasicConstraints() >= 0;
}
/**
* Verifica qual o tipo do certificado (A1, A2, A3, A4, S1, S2, S3, S4).<br>
* Retorna o valor <b>null</b> caso nao possua a extensao CertificatePolicies.
*
* @return String
*/
public String getTipoCertificado() {
try {
DERSequence seq = (DERSequence)getExtensionValue(X509Extensions.CertificatePolicies.getId());
if(seq == null) {
return null;
}
for(int pos = 0 ; pos < seq.size() ; pos++) {
PolicyInformation pol = new PolicyInformation((DERSequence) seq.getObjectAt(pos));
String id = pol.getPolicyIdentifier().getId();
if(id == null) {
continue;
}
if(id.startsWith(OID_CERTIFICADO_A1)) {
return "A1";
}
if(id.startsWith(OID_CERTIFICADO_A2)) {
return "A2";
}
if(id.startsWith(OID_CERTIFICADO_A3)) {
return "A3";
}
if(id.startsWith(OID_CERTIFICADO_A4)) {
return "A4";
}
if(id.startsWith(OID_CERTIFICADO_S1)) {
return "S1";
}
if(id.startsWith(OID_CERTIFICADO_S2)) {
return "S2";
}
if(id.startsWith(OID_CERTIFICADO_S3)) {
return "S3";
}
if(id.startsWith(OID_CERTIFICADO_S4)) {
return "S4";
}
}
return null;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Retorna o valor da extensao AuthorityKeyIdentifier no formato String.<br>
* Caso essa informacao nao esteja no certificado, retorna <b>null</b>.<br>
*
* @return String
* @throws IOException
*/
public String getAuthorityKeyIdentifier() throws IOException {
//TODO - Precisa validar este metodo com a RFC
DERSequence seq = (DERSequence) getExtensionValue(X509Extensions.AuthorityKeyIdentifier.getId());
if(seq == null || seq.size() == 0) {
return null;
}
DERTaggedObject tag = (DERTaggedObject)seq.getObjectAt(0);
DEROctetString oct = (DEROctetString)DEROctetString.getInstance(tag);
return toString(oct.getOctets());
}
/**
* Retorna o valor da extensao SubjectKeyIdentifier no formato String.<br>
* Caso essa informacao nao esteja no certificado, retorna <b>null</b>.<br>
*
* @return String
*/
public String getSubjectKeyIdentifier() throws IOException {
//TODO - Precisa validar este metodo com a RFC
DEROctetString oct = (DEROctetString)getExtensionValue(X509Extensions.SubjectKeyIdentifier.getId());
if(oct == null) {
return null;
}
return toString(oct.getOctets());
}
/**
* Retorna URL da Lista de Certificados Revogados (CRL). Pode haver mais de uma dependendo do
* emissor do certificado<br>
* Mesmo que a CRL possua mais que uma fonte, retorna apenas a URL.<br>
* Caso essa informacao nao esteja no certificado, retorna <b>null</b>.<br>
*
* @return String
* @throws IOException
*/
public List<String> getCRLDistributionPoint() throws IOException{
//TODO - Precisa validar este metodo com a RFC
List<String> lcrS = new ArrayList<String>();
DERObject derObj = getExtensionValue(X509Extensions.CRLDistributionPoints.getId());
if(derObj == null) {
return null;
}
CRLDistPoint crlDistPoint = CRLDistPoint.getInstance(derObj);
DistributionPoint[] dp = crlDistPoint.getDistributionPoints();
for(int i=0 ; i<dp.length ; i++) {
DERSequence seq = (DERSequence)new ASN1InputStream(dp[i].getDistributionPoint().getName().getDEREncoded()).readObject();
DERTaggedObject tag = (DERTaggedObject) seq.getObjectAt(0);
try{
ASN1OctetString oct = (DEROctetString)DEROctetString.getInstance(tag);
lcrS.add( new String(oct.getOctets()));
}catch (Exception e){
// N�o � um objeto com informa��o de DistributionPoint
}
// codifica��o antiga feita pelo Thiago, pegava apenas a primeira URL.
//URL da WEB
//if(tag.getTagNo() == 6) {
// DEROctetString oct = (DEROctetString)DEROctetString.getInstance(tag);
// return new String(oct.getOctets());
//}
}
return lcrS;
}
/**
* Retorna um Objeto do tipo DERObject contendo o valor da extensao passado<br>
* atraves do OID.<br>
*
* @param oid
* @return DERObject
* @see DERObject
*/
public DERObject getExtensionValue(String oid){
byte[] extvalue = certificate.getExtensionValue(oid);
if (extvalue == null) {
return null;
}
try {
DEROctetString oct = (DEROctetString) (new ASN1InputStream(extvalue).readObject());
return (new ASN1InputStream(oct.getOctets()).readObject());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**********************************************************************************************
* Metodos Publicos Complementares sobre os certificados
*********************************************************************************************/
/**
* Retorna o certificado da AC que assinou
* @return TabeliaoCertificate
* @see TabeliaoCertificate
* @throws Exception
*/
public TabeliaoCertificate getCertificadoGerador() throws Exception {
if(certificadoGerador == null) {
//Se eh um certificado auto-assinado retorna ele mesmo
if(certificate.getSubjectDN().getName().equals(certificate.getIssuerDN().getName())) {
certificadoGerador = this;
} else {
try {
HibernateUtil.currentSession();
CertificadoAcDAO certificadoAcDAO = DAOFactory.getDAOFactory(DAOFactory.HIBERNATE).getCertificadoAcDAO();
CertificadoAc certificadoAc = certificadoAcDAO.buscarPorKeyId(getAuthorityKeyIdentifier());
if(certificadoAc == null) {
throw new Exception("N�o foi poss�vel localizar o certificado da Autoridade Certificadora: " + getX509Certificate().getIssuerDN().getName());
}
certificadoGerador = new TabeliaoCertificate(certificadoAc);
}catch (Exception e) {
throw new Exception("Problemas ao tentar localizar o certificado da Autoridade Certificadora: " + getX509Certificate().getIssuerDN().getName());
}finally {
HibernateUtil.closeSession();
}
}
}
return certificadoGerador;
}
/**
* Carrega uma List com a cadeia de certificados, onde o primeiro certificado <br>
* e o certificado Raiz, e o ultimo certificado eh este.<br>
*
* @return List<TabeliaoCertificate>
* @throws Exception
* @see TabeliaoCertificate
*/
public List<TabeliaoCertificate> getCadeiaCertificados() throws Exception {
List<TabeliaoCertificate> list = null;
if(certificate.getSubjectDN().getName()
.equals(certificate.getIssuerDN().getName())) {
list = new LinkedList<TabeliaoCertificate>();
list.add(this);
return list;
}
try {
list = getCertificadoGerador().getCadeiaCertificados();
} catch (Exception e) {
//list = new LinkedList<TabeliaoCertificate>();
throw new Exception("Problemas na gera��o da Cadeia"+e.getMessage());
}
list.add(this);
return list;
}
/**
* Carrega uma List com a cadeia de certificados na ordem inversa, ou seja, <br>
* o primeiro certificado eh este e o ultimo certificado eh o Raiz.<br>
*
* @return List<TabeliaoCertificate>
* @throws Exception
* @see TabeliaoCertificate
*/
public List<TabeliaoCertificate> getCadeiaCertificadosInversa() throws Exception {
List<TabeliaoCertificate> list = null;
if(certificate.getSubjectDN().getName()
.equals(certificate.getIssuerDN().getName())) {
list = new LinkedList<TabeliaoCertificate>();
list.add(this);
return list;
}
try {
list = getCertificadoGerador().getCadeiaCertificadosInversa();
} catch (Exception e) {
//list = new LinkedList<TabeliaoCertificate>();
throw new Exception("Problemas na gera��o da Cadeia"+e.getMessage());
}
list.add(0, this);
return list;
}
/**
* Recupera a Lista de Certificados Revogados (LCR), primeiramente com uma pesquisa na base de
* dados do Tabeliao, caso nao seja encontrada a mesma sera recuperada atraves do atributo
* CRLDistributionPoint armazenado no Certificado, neste caso sera necessario o acesso a internet.
* A nova lista sera atualizada na Base.
*
* @return TabeliaoLCR
* @see TabeliaoLCR
* @throws Exception
*/
public TabeliaoLCR getTabeliaoLCR() throws Exception {
if(tabeliaoLCR == null) {
// Primeiro tenta encontrar a LCR na base de dados do Tabeli�o
try {
HibernateUtil.currentSession();
CertificadoRevogadoDAO certRevogadoDAO = DAOFactory.getDAOFactory(DAOFactory.HIBERNATE).getCertificadoRevogadoDAO();
CertificadoRevogado certRevogado = certRevogadoDAO.buscarPorKeyId(getAuthorityKeyIdentifier());
// Caso n�o encontre a LCR ser� baixada uma do Ponto de Distribui��o
if(certRevogado == null) {
List<String> pontosLCR = getCRLDistributionPoint();
if(pontosLCR.size() == 0) {
return null;
}
// Iniciando a busca nos pontos
for (int i=0; i < pontosLCR.size(); i++ ){
boolean baixou = false;
String urlNova = null;
try {
urlNova = pontosLCR.get(i);
logger.info("\n Tentando Baixar Lista, ..."+urlNova+"\n");
byte[] buffer = Download.downloadByteArray(urlNova);
TabeliaoLCR lcr = new TabeliaoLCR(buffer);
logger.info("\n Baixou a lista, ... Busca gerador e valida LCR \n");
TabeliaoCertificate cert = getCertificadoGerador();
lcr.getCRL().verify(cert.getX509Certificate().getPublicKey());
logger.info("\n Busca Autoridade!\n");
CertificadoAcDAO certificadoAcDAO = DAOFactory.getDAOFactory(DAOFactory.HIBERNATE).getCertificadoAcDAO();
CertificadoAc certificadoAc = certificadoAcDAO.buscarPorKeyId(getCertificadoGerador().getSubjectKeyIdentifier());
logger.info("\n Gravando nova lista: "+urlNova+"\n");
certRevogado = new CertificadoRevogado();
certRevogado.setArquivo(buffer);
certRevogado.setAutoAtualizacao(true);
certRevogado.setCertificadoAc(certificadoAc);
certRevogado.setDtInclusao(new Date());
certRevogado.setDtProximaAtualizacao(lcr.getCRL().getNextUpdate());
certRevogado.setDtUltimaAtualizacao(lcr.getCRL().getThisUpdate());
certRevogado.setEnderecoWeb(urlNova);
certRevogado.setVersao(1);
baixou = true;
try {
HibernateUtil.currentTransaction();
certRevogadoDAO.salvar(certRevogado);
HibernateUtil.commitTransaction();
} catch (Exception e) {
HibernateUtil.rollbackTransaction();
logger.error("Erro ao salvar a lista de certificados revogados no banco de dados.");
}
}catch (Exception e) {
logger.warn("Lista n�o encontrada, ou problemas."+urlNova);
}
// se j� encontrou a LCR n�o percorrer� todos os pontos
if (baixou){
break;
}
}
tabeliaoLCR = new TabeliaoLCR(certRevogado.getArquivo());
}
// A LCR foi encontrada no Banco
else{
TabeliaoLCR lcr = new TabeliaoLCR(certRevogado.getArquivo());
// Verifica a validade da lista encontrada no Banco
// Se estiver vencida ser� baixada uma nova.
if(lcr.getCRL().getNextUpdate().before(new Date())) {
List<String> pontosLCR = getCRLDistributionPoint();
for (int i=0; i < pontosLCR.size(); i++ ){
String urlVencida = null;
boolean baixou = false;
try {
urlVencida = pontosLCR.get(i);
logger.warn("Lista vencida, recuperando nova: " + urlVencida);
byte[] buffer = Download.downloadByteArray(urlVencida);
TabeliaoLCR lcrN = new TabeliaoLCR(buffer);
TabeliaoCertificate cert = new TabeliaoCertificate(certRevogado.getCertificadoAc());
lcrN.getCRL().verify(cert.getX509Certificate().getPublicKey());
// verifica se a lista baixada e mais atual que a da Base e atualiza
if(lcrN.getCRL().getThisUpdate().compareTo(certRevogado.getDtUltimaAtualizacao()) > 0) {
certRevogado.setVersao(certRevogado.getVersao() + 1);
certRevogado.setDtUltimaAtualizacao(lcrN.getCRL().getThisUpdate());
certRevogado.setDtProximaAtualizacao(lcrN.getCRL().getNextUpdate());
certRevogado.setArquivo(buffer);
baixou = true;
try {
HibernateUtil.currentTransaction();
certRevogadoDAO.salvar(certRevogado);
HibernateUtil.commitTransaction();
} catch (Exception e) {
HibernateUtil.rollbackTransaction();
System.err.println("Erro ao salvar a lista de certificados revogados no banco de dados."+e.getMessage());
}
tabeliaoLCR = new TabeliaoLCR(certRevogado.getArquivo());
}
}catch (Exception e) {
logger.error("Lista n�o encontrada, ou problemas."+urlVencida);
}
// Se foi baixada a nova lista, n�o � necess�rio percorrer os demais pontos.
if (baixou){
break;
}
}
}
// Lista encontrada na Base est� vigente.
else{
tabeliaoLCR = new TabeliaoLCR(certRevogado.getArquivo());
}
}
}catch (Exception e) {
logger.info("\n Exce��o na busca de LCR: !"+e.getMessage());
HibernateUtil.closeSession();
throw new Exception("Erro na busca da LCR: Lista Indispon�vel ou Atributo de URL Incorreto.\n"+ getCRLDistributionPoint()+"\nAutoridade:"+getAuthorityKeyIdentifier());
}
finally {
HibernateUtil.closeSession();
}
}
return tabeliaoLCR;
}
/**
* Efetua a validacao completa (data de validade, cadeia e LCR) do certificado
* @return TabeliaoResultadoValidacao
* @throws Exception
* @see TabeliaoResultadoValidacao
* @throws Exception
*/
public TabeliaoResultadoValidacao valida() throws Exception{
if(tabeliaoValidacao == null) {
tabeliaoValidacao = new TabeliaoResultadoValidacao();
validaValidadeCertificado(tabeliaoValidacao);
validaCadeiaCertificado(tabeliaoValidacao);
validaCertificadoRevogado(tabeliaoValidacao);
}
return tabeliaoValidacao;
}
/**
* Recupera o resultado da validacao completa (data de validade, cadeia e LCR) do certificado
* @return TabeliaoResultadoValidacao
* @throws Exception
* @see TabeliaoResultadoValidacao
*/
public TabeliaoResultadoValidacao getResultadoValidacao() throws Exception{
return valida();
}
/**
* Efetua a verificacao da data de vigencia do Certificado comparando com a data Atual
* do sistema.
* @return TabeliaoResultadoValidacao
* @throws Exception
* @see TabeliaoResultadoValidacao
*/
public TabeliaoResultadoValidacao validaDataVigencia() throws Exception{
if(tabeliaoValidacao == null) {
tabeliaoValidacao = new TabeliaoResultadoValidacao();
validaValidadeCertificado(tabeliaoValidacao);
}
return tabeliaoValidacao;
}
/**
* Recupera o resultado da validacao da data de validade do certificado
* @return TabeliaoResultadoValidacao
* @throws Exception
* @see TabeliaoResultadoValidacao
*/
public TabeliaoResultadoValidacao getResultadoDataVigencia() throws Exception{
return validaDataVigencia();
}
/**
* Efetua a validacao da cadeia de certificacao
* @return TabeliaoResultadoValidacao
* @throws Exception
* @see TabeliaoResultadoValidacao
* @throws Exception
*/
public TabeliaoResultadoValidacao validaCadeia() throws Exception{
if(tabeliaoValidacao == null) {
tabeliaoValidacao = new TabeliaoResultadoValidacao();
validaCadeiaCertificado(tabeliaoValidacao);
}
return tabeliaoValidacao;
}
/**
* Recupera o resultado da validacao da cadeia de certificacao
* @return TabeliaoResultadoValidacao
* @throws Exception
* @see TabeliaoResultadoValidacao
*/
public TabeliaoResultadoValidacao getResultadoCadeia() throws Exception{
return validaCadeia();
}
/**
* Efetua a validacao da LCR (Lista de Certificados Revogados)
* @return TabeliaoResultadoValidacao
* @throws Exception
* @see TabeliaoResultadoValidacao
* @throws Exception
*/
public TabeliaoResultadoValidacao validaLCR() throws Exception{
if(tabeliaoValidacao == null) {
tabeliaoValidacao = new TabeliaoResultadoValidacao();
validaCertificadoRevogado(tabeliaoValidacao);
}
return tabeliaoValidacao;
}
/**
* Recupera o resultado da validacao da LCR (Lista de Certificados Revogados)
* @return TabeliaoResultadoValidacao
* @throws Exception
* @see TabeliaoResultadoValidacao
*/
public TabeliaoResultadoValidacao getResultadoLCR() throws Exception{
return validaLCR();
}
/**
* Efetua uma verificacao da validade do certificado, compara com a data atual
* @param trv -> TabeliaoResultadoValidacao
* @throws Exception
* @see TabeliaoResultadoValidacao
* @throws Exception
*/
private void validaValidadeCertificado(TabeliaoResultadoValidacao trv) throws Exception{
validaValidadeCertificado(trv, new Date());
}
/**
* Efetua uma verificacao da validade do certificado, compara com a data informada no parametro
* e informa a validade com relacao a esta data.
* Gera um AVISO quando o prazo de validade se aproxima.
* @param trv -> TabeliaoResultadoValidacao
* @param date -> Data com a qual sera comparada a validade do certificado.
* @throws Exception
* @throws Exception
* @throws Exception
* @see TabeliaoResultadoValidacao
* @throws Exception
*/
private void validaValidadeCertificado(TabeliaoResultadoValidacao trv, Date date) throws Exception{
try {
certificate.checkValidity(date);
Date date30 = new Date(date.getTime() + (30 * 86400000l)); // 86400000l == 1 dia em milisegundos
try {
certificate.checkValidity(date30);
trv.addOk(TabeliaoResultadoValidacao.VAL_VALIDADE);
} catch (CertificateExpiredException e1) {
trv.addAviso(TabeliaoResultadoValidacao.VAL_VALIDADE, "Este certificado est� para vencer em " + Data.formataData(certificate.getNotAfter()));
return;
}
} catch (CertificateExpiredException e1) {
trv.addErro(TabeliaoResultadoValidacao.VAL_VALIDADE, "Este certificado est� vencido! \n"+e1.getMessage());
return;
} catch (CertificateNotYetValidException e1) {
trv.addErro(TabeliaoResultadoValidacao.VAL_VALIDADE, "Este certificado ainda n�o est� habilitado! \n"+e1.getMessage());
return;
} catch (Exception e) {
trv.addExcecao(TabeliaoResultadoValidacao.VAL_VALIDADE, e.getMessage());
return;
}
}
/**
* Efetua a validacao completa da cadeia do certificado ate a raiz
* @param trv -> TabeliaoResultadoValidacao
* @throws Exception
* @throws Exception
* @see TabeliaoResultadoValidacao
*/
private void validaCadeiaCertificado(TabeliaoResultadoValidacao trv) throws Exception {
if (certificate.getSubjectDN().getName()
.equals(certificate.getIssuerDN().getName())) {
// Eh um certificado de uma AC Raiz
//logger.debug("*** Verificando Certificado Raiz: " + certificate.getSubjectDN().getName());
try {
certificate.verify(certificate.getPublicKey());
} catch (InvalidKeyException e) {
trv.addErro(TabeliaoResultadoValidacao.VAL_CADEIA, "Chave Inv�lida:"+e.getMessage());
return;
} catch (CertificateException e) {
trv.addErro(TabeliaoResultadoValidacao.VAL_CADEIA, "Certificado com Problema: "+e.getMessage());
return;
} catch (NoSuchAlgorithmException e) {
trv.addErro(TabeliaoResultadoValidacao.VAL_CADEIA, "Sem Algoritimo: "+e.getMessage());
return;
} catch (NoSuchProviderException e) {
trv.addErro(TabeliaoResultadoValidacao.VAL_CADEIA, "Sem provider:"+e.getMessage());
return;
} catch (SignatureException e) {
trv.addErro(TabeliaoResultadoValidacao.VAL_CADEIA, "Erro de Assinatura:"+e.getMessage());
return;
}catch (Exception e) {
trv.addExcecao(TabeliaoResultadoValidacao.VAL_CADEIA, e.getMessage());
return;
}
} else {
// Eh um certificado normal
//logger.debug("*** Verificando Certificado de n�vel: " + certificate.getSubjectDN().getName());
//logger.debug("*** Assinado por: " + certificate.getIssuerDN().getName());
TabeliaoCertificate certGer = null;
try {
certGer = getCertificadoGerador();
} catch (Exception e) {
trv.addExcecao(TabeliaoResultadoValidacao.VAL_CADEIA, e.getMessage());
return;
}
X509Certificate cert = certGer.getX509Certificate();
try {
certificate.verify(cert.getPublicKey());
} catch (InvalidKeyException e) {
trv.addErro(TabeliaoResultadoValidacao.VAL_CADEIA, "Chave Inv�lida:"+e.getMessage());
return;
} catch (CertificateException e) {
trv.addErro(TabeliaoResultadoValidacao.VAL_CADEIA, "Certificado com Problema: "+e.getMessage());
return;
} catch (NoSuchAlgorithmException e) {
trv.addErro(TabeliaoResultadoValidacao.VAL_CADEIA, "Sem Algoritimo: "+e.getMessage());
return;
} catch (NoSuchProviderException e) {
trv.addErro(TabeliaoResultadoValidacao.VAL_CADEIA, "Sem provider:"+e.getMessage());
return;
} catch (SignatureException e) {
trv.addErro(TabeliaoResultadoValidacao.VAL_CADEIA, "Erro de Assinatura:"+e.getMessage());
return;
} catch (Exception e) {
trv.addExcecao(TabeliaoResultadoValidacao.VAL_CADEIA, e.getMessage());
return;
}
}
trv.addOk(TabeliaoResultadoValidacao.VAL_CADEIA);
}
/**
* Verifica se o certificado nao foi revogado, de acordo com a LCR.
* Gera um Aviso em TabeliaoResultadoValidacao nos seguintes casos:
* - A lista nao foi localizada no Banco ou nem na URL
* - A lista da base esta desatualizada.
* @param trv -> TabeliaoResultadoValidacao
* @throws Exception
* @throws Exception
* @see TabeliaoResultadoValidacao
*/
private void validaCertificadoRevogado(TabeliaoResultadoValidacao trv) throws Exception {
if (certificate.getSubjectDN().getName()
.equals(certificate.getIssuerDN().getName())) {
// Eh um certificado de uma AC Raiz, portanto n�o h� valida��o de Revoga��o.
//logger.debug("*** Verificando Certificado Raiz: " + certificate.getSubjectDN().getName());
} else {
// Eh um certificado normal
//logger.debug("*** Verificando Certificado de n�vel: " + certificate.getSubjectDN().getName());
//logger.debug("*** Assinado por: " + certificate.getIssuerDN().getName());
TabeliaoLCR lcr;
try {
lcr = getTabeliaoLCR();
} catch (Exception e) {
trv.addExcecao(TabeliaoResultadoValidacao.VAL_LCR, e.getMessage());
return;
}
if(lcr == null) {
trv.addExcecao(TabeliaoResultadoValidacao.VAL_LCR, "N�o foi poss�vel localizar a lista de certificados revogados.\n "+ getCRLDistributionPoint());
return;
}
if(lcr.getCRL().isRevoked(certificate)) {
trv.addErro(TabeliaoResultadoValidacao.VAL_LCR, "Este certificado est� revogado.");
return;
}
if(lcr.getCRL().getNextUpdate().before(new Date())) {
trv.addAviso(TabeliaoResultadoValidacao.VAL_LCR, "A Lista de Certificados Revogados est� vencida.\n" + getCRLDistributionPoint());
return;
}
}
trv.addOk(TabeliaoResultadoValidacao.VAL_LCR);
}
public String toString(){
StringBuffer sBuffer = new StringBuffer();
try {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
sBuffer.append("*********************************\n");
sBuffer.append("Certificado DE : " + this.getCertificadoDe() + "\n");
sBuffer.append("Serial Number . : " + this.getSerialNumber() + "\n");
sBuffer.append("Certificado PARA: " + this.getCertificadoPara() + "\n");
sBuffer.append("Nome do Certif : " + this.getNome() + "\n");
sBuffer.append("Validade . . . : de " + sdf.format(this.getValidadeDe()) + " ate " + sdf.format(this.getValidadeAte()) + "\n");
sBuffer.append("*********************************\n");
sBuffer.append("Email . . . . . : " + this.getEmail() + "\n");
sBuffer.append("*********************************\n");
sBuffer.append("Tem dados PF . : " + this.hasDadosPF() + "\n");
if(this.hasDadosPF()) {
TabeliaoDadosPF tdPF = this.getTabeliaoDadosPF();
sBuffer.append("CPF . . . . . . : " + tdPF.getCPF() + "\n");
sBuffer.append("Data Nascimento : " + sdf.format(tdPF.getDataNascimento()) + "\n");
sBuffer.append("PIS . . . . . . : " + tdPF.getNis() + "\n");
sBuffer.append("Rg . . . . . . : " + tdPF.getRg() + " " + tdPF.getOrgaoUfExpedidorRg() + "\n");
sBuffer.append("Inss . . . . . : " + tdPF.getInss() + "\n");
sBuffer.append("Titulo . . . . : " + tdPF.getTituloEleitor() + "\n");
sBuffer.append("Se��o . . . . . : " + tdPF.getSecaoTituloEleitor() + "\n");
sBuffer.append("Zona . . . . . : " + tdPF.getZonaTituloEleitor() + "\n");
sBuffer.append("Municipio UF. . : " + tdPF.getMunicipioUfTituloEleitor() + "\n");
}
sBuffer.append("*********************************\n");
sBuffer.append("Tem dados PJ . : " + this.hasDadosPJ() + "\n");
if(this.hasDadosPJ()) {
TabeliaoDadosPJ tdPJ = this.getTabeliaoDadosPJ();
sBuffer.append("CNPJ. . . . . . : " +tdPJ.getCNPJ()+ "\n");
sBuffer.append("INSS. . . . . . : " +tdPJ.getINSS()+ "\n");
sBuffer.append("NIS . . . . . . : " +tdPJ.getNis()+ "\n");
sBuffer.append("Respons�vel . . : " +tdPJ.getNomeResponsavel()+ "\n");
}
sBuffer.append("*********************************\n");
sBuffer.append("Tem dados Equip : " + this.hasDadosEquipamento() + "\n");
if(this.hasDadosEquipamento()) {
TabeliaoDadosEquipamento tdEq = this.geTabeliaoDadosEquipamento();
sBuffer.append("CNPJ. . . . . . : " +tdEq.getCNPJ()+ "\n");
sBuffer.append("NIS . . . . . . : " +tdEq.getNis()+ "\n");
sBuffer.append("Nome Empresa. . : " +tdEq.getNomeEmpresarial()+ "\n");
sBuffer.append("Respons�vel . . : " +tdEq.getNomeResponsavel()+ "\n");
}
sBuffer.append("*********************************\n");
sBuffer.append("Eh CertificadoAC: " + this.isCertificadoAc() + "\n");
sBuffer.append("PathLength . . : " + this.getPathLength() + "\n");
sBuffer.append("Tipo Certificado: " + this.getTipoCertificado() + "\n");
sBuffer.append("Tipo de Uso . . : " + this.getTabeliaoKeyUsage() + "\n");
sBuffer.append("*********************************\n");
sBuffer.append("Authority KeyID : " + this.getAuthorityKeyIdentifier() + "\n");
sBuffer.append("Subject KeyID . : " + this.getSubjectKeyIdentifier() + "\n");
sBuffer.append("CRL DistPoint . : " + this.getCRLDistributionPoint() + "\n");
} catch (IOException e) {
e.printStackTrace();
}
return sBuffer.toString();
}
}