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.tabeliao.core.validacao.TabeliaoResultadoValidacao;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Date;
import org.bouncycastle.asn1.cms.Attribute;
import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.cms.CMSAttributes;
import org.bouncycastle.asn1.cms.Time;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
/**
* Classe de tratamento/validacao de Assinaturas em formato PKCS7/CADES
* De acordo com as propriedades CADES reconhecipas pela ICP-BRASIL
*
* @author Thiago Meneghello - GIC/CELEPAR
* @author Emerson Sachio Saito - GIC/CELEPAR
*
*/
public class TabeliaoAssinaturaPKCS7 {
private CMSSignedData signedData = null;
private SignerInformation signerInfo = null;
private X509Certificate certificadoAssinante = null;
/**
* Construtor para assiantura em array de byte
*
* @param assinatura -> array de byte
* @throws CMSException
*/
public TabeliaoAssinaturaPKCS7(byte[] assinatura) throws CMSException {
this(new ByteArrayInputStream(assinatura));
}
/**
* Construtor para assinatura em InputStream
*
* @param assinatura
* @see InputStream
* @throws CMSException
*/
public TabeliaoAssinaturaPKCS7(InputStream assinatura) throws CMSException {
signedData = new CMSSignedData(assinatura);
}
/**
* Construtor para conteudo e assinatura
*
* @param conteudo -> InputStream
* @param assinatura -> InputStream
* @see InputStream
* @throws CMSException
* @throws IOException
*/
public TabeliaoAssinaturaPKCS7(InputStream conteudo, InputStream assinatura) throws CMSException, IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int read;
while((read = conteudo.read(buffer)) > 0) {
bos.write(buffer, 0, read);
}
buffer = bos.toByteArray();
CMSProcessableByteArray data = new CMSProcessableByteArray(buffer);
signedData = new CMSSignedData(data, assinatura);
}
/**
* Construtor para conteudo e assinatura
*
* @param conteudo -> array de byte
* @param assinatura -> InputStream
* @see InputStream
* @throws CMSException
* @throws IOException
*/
public TabeliaoAssinaturaPKCS7(byte[] conteudo, InputStream assinatura) throws CMSException {
CMSProcessableByteArray data = new CMSProcessableByteArray(conteudo);
signedData = new CMSSignedData(data, assinatura);
}
/**
* Construtor para conteudo e assinatura
*
* @param conteudo -> InputStream
* @see InputStream
* @param assinatura -> Array de byte
* @throws CMSException
* @throws IOException
*/
public TabeliaoAssinaturaPKCS7(InputStream conteudo, byte[] assinatura) throws CMSException, IOException {
this(conteudo, new ByteArrayInputStream(assinatura));
}
/**
* Construtor para conteudo e assinatura
*
* @param conteudo -> Array de byte
* @param assinatura -> Array de byte
* @throws CMSException
* @throws IOException
*/
public TabeliaoAssinaturaPKCS7(byte[] conteudo, byte[] assinatura) throws CMSException, IOException {
this(conteudo, new ByteArrayInputStream(assinatura));
}
/**
* retorna o certificado do assinante
*
* @return X509Certificate
* @throws Exception
* @see X509Certificate
*/
@SuppressWarnings("unchecked")
public X509Certificate getCertificadoAssinante() throws Exception {
if (signedData == null) {
return null;
}
if (certificadoAssinante != null) {
return certificadoAssinante;
}
try {
CertStore certStore = signedData.getCertificatesAndCRLs(
"Collection", "SUN");
SignerInformationStore sis = signedData.getSignerInfos();
Collection<SignerInformation> signers = sis.getSigners();
if (signers != null && signers.size() > 0) {
SignerInformation sigInfo = signers.iterator().next();
signerInfo = sigInfo;
Collection<X509Certificate> chain = (Collection<X509Certificate>) certStore
.getCertificates(sigInfo.getSID());
if (chain != null && chain.size() > 0) {
certificadoAssinante = chain.iterator().next();
return certificadoAssinante;
}
}
} catch (NoSuchAlgorithmException e) {
throw new Exception("Sem Algoritmo, no Certificado:"+e.getMessage());
} catch (NoSuchProviderException e) {
throw new Exception("Sem Provider, no Certificado:"+e.getMessage());
} catch (CMSException e) {
throw new Exception("Exce��o de CMS, no Certificado:"+e.getMessage());
} catch (CertStoreException e) {
throw new Exception("Exce��o de CertStore, no Certificado:"+e.getMessage());
}
return null;
}
/**
* Retorna o conteudo do arquivo que foi assinado.
*
* @return array de byte
*/
public byte[] getConteudoAssinado() {
if (signedData == null || signedData.getSignedContent() == null) {
return null;
}
return (byte[]) signedData.getSignedContent().getContent();
}
/**
* Executa as validacoes da assinatura
*
* @return TabeliaoResultadoValidacao
* @throws Exception
* @see TabeliaoResultadoValidacao
* @throws Exception
*/
public TabeliaoResultadoValidacao valida() throws Exception {
X509Certificate cert = getCertificadoAssinante();
// Verifica se o certificado est� junto com a assinatura
if (cert == null) {
throw new Exception(
"N�o foi poss�vel encontrar o certificado na assinatura PKCS7.");
}
byte[] conteudo = getConteudoAssinado();
if (conteudo == null) {
throw new Exception(
"O conte�do assinado n�o est� anexado com a assinatura.");
}
TabeliaoResultadoValidacao resultVal = new TabeliaoResultadoValidacao();
// Verifica se no momento da assinatura o certificado estava expirado
try {
if(signerInfo.verify(cert, null)){
resultVal.addOk(TabeliaoResultadoValidacao.VAL_CONTEUDO);
resultVal.addOk(TabeliaoResultadoValidacao.VAL_VALIDADE);
} else {
//N�o deve entrar neste ELSE.
resultVal.addErro(TabeliaoResultadoValidacao.VAL_VALIDADE, "A informa��o assinada n�o confere com o certificado do assinante.");
}
} catch (CertificateExpiredException e) {
resultVal.addErro(TabeliaoResultadoValidacao.VAL_VALIDADE, e.getMessage());
} catch (CertificateNotYetValidException e) {
resultVal.addErro(TabeliaoResultadoValidacao.VAL_VALIDADE, e.getMessage());
} catch (NoSuchAlgorithmException e) {
resultVal.addErro(TabeliaoResultadoValidacao.VAL_CONTEUDO, e.getMessage());
} catch (NoSuchProviderException e) {
resultVal.addErro(TabeliaoResultadoValidacao.VAL_CONTEUDO, e.getMessage());
} catch (CMSException e) {
resultVal.addErro(TabeliaoResultadoValidacao.VAL_CONTEUDO, e.getMessage());
} catch (Exception e) {
resultVal.addExcecao(TabeliaoResultadoValidacao.VAL_CONTEUDO, e.getMessage());
}
return resultVal;
}
/**
* Executa as validacoes da assinatura (.valida)
* @return TabeliaoResultadoValidacao
* @see TabeliaoResultadoValidacao
* @throws Exception
*/
public TabeliaoResultadoValidacao getResultadoValidacao() throws Exception {
return valida();
}
/**
* Retorna o conteudo assinado
* @return CMSSignedData
* @see CMSSignedData
*/
public CMSSignedData getCMSSignedData(){
return signedData;
}
/**
* Retorna a data da criacao da assinatura
* NAO EH CARIMBO DE TEMPO
* @return Date
* @see Date
*/
public Date getDataAssinatura(){
try {
getCertificadoAssinante();
} catch (Exception e) {
return null;
}
AttributeTable attr = signerInfo.getSignedAttributes();
if (attr != null)
{
Attribute t = attr.get(CMSAttributes.signingTime);
if (t != null)
{
Time time = Time.getInstance(
t.getAttrValues().getObjectAt(0).getDERObject());
return time.getDate();
}
}
return null;
}
}