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.util.XmlSigUtil;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import javax.xml.crypto.dom.DOMStructure;
import javax.xml.parsers.ParserConfigurationException;
import org.jcp.xml.dsig.internal.dom.DOMXMLObject;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
*
* Classe para tratamento e validacao de assinatura em formato EnvelopedXML
*
* @version 1.0
* @author Emerson Sachio Saito - GIC/CELEPAR
*
*/
public class TabeliaoAssinaturaEnvelopedXML extends TabeliaoAssinaturaXML {
/**
* Instancia a classe a partir de um array de bytes
* @param arquivoAs -> Arquivo a ser assinado
* @throws XMLSignatureException
* @throws XMLSecurityException
*/
public TabeliaoAssinaturaEnvelopedXML(byte[] arquivoAs) throws Exception {
try {
this.setXmlAssinado(XmlSigUtil.carregarArquivoXML(new ByteArrayInputStream(arquivoAs)));
} catch (ParserConfigurationException e) {
String errorMessage = "Erro de ParserConfiguration ao carregar o arquivo assinado\n" +
"Detalhes: " + e.getMessage();
throw new Exception(errorMessage, e);
} catch (SAXException e) {
String errorMessage = "Erro de SAX ao carregar o arquivo assinado\n" +
"Detalhes: " + e.getMessage();
throw new Exception(errorMessage, e);
} catch (IOException e) {
String errorMessage = "Erro de IO ao carregar o arquivo assinado\n" +
"Detalhes: " + e.getMessage();
throw new Exception(errorMessage, e);
}
}
/**
* Instancia a classe a partir de um InputStream
* @param arquivoAs -> Arquivo a ser assinado
* @throws XMLSignatureException
* @throws XMLSecurityException
*/
public TabeliaoAssinaturaEnvelopedXML(InputStream arquivoAs) throws Exception{
try {
this.setXmlAssinado(XmlSigUtil.carregarArquivoXML(arquivoAs));
} catch (ParserConfigurationException e) {
String errorMessage = "Erro de ParserConfiguration ao carregar o arquivo assinado\n" +
"Detalhes: " + e.getMessage();
throw new Exception(errorMessage, e);
} catch (SAXException e) {
String errorMessage = "Erro de SAX ao carregar o arquivo assinado\n" +
"Detalhes: " + e.getMessage();
throw new Exception(errorMessage, e);
} catch (IOException e) {
String errorMessage = "Erro de IO ao carregar o arquivo assinado\n" +
"Detalhes: " + e.getMessage();
throw new Exception(errorMessage, e);
}
}
/**
* Instancia a classe a partir de um objeto Document contendo o XML Assinado
* @param arquivoAs
* @throws XMLSignatureException
* @throws XMLSecurityException
* @throws IOException
*/
public TabeliaoAssinaturaEnvelopedXML(Document arquivoAs) throws Exception, IOException {
this.setXmlAssinado(arquivoAs);
}
/**
* Instancia a classe a partir de uma String contendo o XML Assinado
* @param arquivoAs
* @throws XMLSignatureException
* @throws XMLSecurityException
* @throws IOException
*/
public TabeliaoAssinaturaEnvelopedXML(String arquivoAs) throws Exception, IOException {
try {
this.setXmlAssinado(XmlSigUtil.carregarArquivoXML(arquivoAs));
} catch (ParserConfigurationException e) {
String errorMessage = "Erro de ParserConfiguration ao carregar o arquivo assinado\n" +
"Detalhes: " + e.getMessage();
throw new Exception(errorMessage, e);
} catch (SAXException e) {
String errorMessage = "Erro de SAX ao carregar o arquivo assinado\n" +
"Detalhes: " + e.getMessage();
throw new Exception(errorMessage, e);
}
}
/**
* Instancia a classe a partir de um org.xml.sax.InputSource contendo o XML Assinado
* @param arquivoAs
* @throws XMLSignatureException
* @throws XMLSecurityException
* @throws IOException
*/
public TabeliaoAssinaturaEnvelopedXML(InputSource arquivoAs) throws Exception, IOException {
try {
this.setXmlAssinado(XmlSigUtil.carregarArquivoXML(arquivoAs));
} catch (ParserConfigurationException e) {
String errorMessage = "Erro de ParserConfiguration ao carregar o arquivo assinado\n" +
"Detalhes: " + e.getMessage();
throw new Exception(errorMessage, e);
} catch (SAXException e) {
String errorMessage = "Erro de SAX ao carregar o arquivo assinado\n" +
"Detalhes: " + e.getMessage();
throw new Exception(errorMessage, e);
}
}
/**
* Retorna o nome da TAG que foi assinada, na assinatura de indice ix,
* A identificacao da TAG e feita pelo ID referente a URI (getUriTagAssinada(ix))
* este ID deve estar registrado (IdResolver.registerElementById)
* se vazio ou null significa que o arquivo todo foi assinado.
*
*
* @param ix indica de qual a assinatura.
* @return String com o Nome ou a situacao da TAG.
*
* @throws XMLSecurityException
*/
public String getNomeTagAssinada(int ix) throws Exception {
String nomeTagAssinada = null;
// Verifica se ha assinaturas no arquivo.
if (this.getAssinaturas().isEmpty()) {
nomeTagAssinada = "sem assinatura";
return nomeTagAssinada;
}
if (this.getAssinaturas().get(ix).getSignedInfo().getReferences().isEmpty()){
nomeTagAssinada = "";
}else{
String idTag = this.getUriTagAssinada(ix).replaceFirst("#", "").trim();
Element Elem = getXmlAssinado().getElementById(idTag);
if (Elem != null){
nomeTagAssinada = Elem.getLocalName();
}
}
return nomeTagAssinada;
}
/**
* Verifica se a assinatura informada eh uma contra assinatura.
* @param ix
* @return true se eh uma contra assinatura. False se nao eh.
* @throws Exception
*/
public boolean isContraAssintura(int ix) throws Exception{
if (this.getContraAssinatura(ix) != null){
return true;
}else{
return false;
}
}
/**
* Retorna um NodeList da propriedade CounterSignature, se houver.
* esta lista contem o elemento Signature que foi contra assinado, este por sua vez
* tambem pode possuir um elemento CounterSignature recursivamente igual.
*
* @param ix -> indice da assinatura
* @return NodeList -> CounterSignature ou nulo
* @throws Exception
*/
public NodeList getContraAssinatura(int ix) throws Exception{
NodeList nodeContraAssiantura = null;
if (this.getAssinaturas().isEmpty()){
return nodeContraAssiantura;
}
if (!this.getAssinaturas().get(ix).getObjects().isEmpty()){
DOMXMLObject objDX = null;
Iterator<?> it = this.getAssinaturas().get(ix).getObjects().iterator();
while (it.hasNext()) {
Object ob1 = it.next();
if (ob1 instanceof DOMXMLObject){
objDX = (DOMXMLObject) ob1;
for (int i=0; i < objDX.getContent().size();i++){
DOMStructure Dos = (DOMStructure) objDX.getContent().get(i);
if (Dos.getNode().getLocalName() == "QualifyingProperties"){
Element el = (Element) Dos.getNode();
nodeContraAssiantura = el.getElementsByTagName("CounterSignature");
break;
}
}
// se a lista estiver vazia retornar� nulo
if (nodeContraAssiantura.getLength() < 1){
nodeContraAssiantura = null;
}
}
}
}
return nodeContraAssiantura;
}
/**
* Retorna a data de Assinatura contida em SigningTime
* Nao eh carimbo de tempo.
* @param ix indica de qual a assinatura.
* @return Date com data da assinatura
* @throws ParseException
* @throws DOMException
*/
public Date getDataAssinatura(int ix) throws DOMException, ParseException {
Date dataAssinatura = null;
if (this.getAssinaturas().isEmpty()){
return dataAssinatura;
}
if (!this.getAssinaturas().get(ix).getObjects().isEmpty()){
DOMXMLObject objDX = null;
Iterator<?> it = this.getAssinaturas().get(ix).getObjects().iterator();
while (it.hasNext()) {
Object ob1 = it.next();
if (ob1 instanceof DOMXMLObject){
objDX = (DOMXMLObject) ob1;
for (int i=0; i < objDX.getContent().size();i++){
DOMStructure Dos = (DOMStructure) objDX.getContent().get(i);
if (Dos.getNode().getLocalName() == "QualifyingProperties"){
Element el = (Element) Dos.getNode();
NodeList nodeQualifying = el.getElementsByTagName("SigningTime");
if (nodeQualifying.getLength() > 0){
Locale locale = new Locale("pt","BR");
SimpleDateFormat formatador = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ",locale);
dataAssinatura = (Date)formatador.parse(nodeQualifying.item(0).getTextContent());
}
break;
}
}
}
}
}
return dataAssinatura;
}
/**
* Retorna o XML que contem SigningCertificate, que eh uma das propriedades assinadas obrigatorias da ICP-BRASIL.
* contem cert = conforme DOC-ICP-04; CertDigest: /DigestMethod e /DigestValue; IssuerSerial: /X509IssuerName e /X509SerialNumber
* @param ix indica de qual a assinatura.
* @return org.w3c.NodeList contendo SigningCertificate ou nulo
* @throws Exception
*/
public NodeList getSigningCertificate(int ix) throws Exception{
NodeList nodeSigningCertificate = null;
if (this.getAssinaturas().isEmpty()){
return null;
}
if (!this.getAssinaturas().get(ix).getObjects().isEmpty()){
DOMXMLObject objDX = null;
Iterator<?> it = this.getAssinaturas().get(ix).getObjects().iterator();
while (it.hasNext()) {
Object ob1 = it.next();
if (ob1 instanceof DOMXMLObject){
objDX = (DOMXMLObject) ob1;
for (int i=0; i < objDX.getContent().size();i++){
DOMStructure Dos = (DOMStructure) objDX.getContent().get(i);
if (Dos.getNode().getLocalName() == "QualifyingProperties"){
Element el = (Element) Dos.getNode();
nodeSigningCertificate = el.getElementsByTagName("SigningCertificate");
break;
}
}
// se a lista estiver vazia retornar� nulo
if (nodeSigningCertificate.getLength() < 1){
nodeSigningCertificate = null;
}
}
}
}
return nodeSigningCertificate;
}
/**
* Retorna SignaturePolicyIdentifier, que identifica qual eh a politica de assinatura.
* Eh uma das propriedades assinadas obrigatorias da ICP-BRASIL. Atualmente contem dos atributos:
* SigPolicyId e SPURI
*
* @param ix indica de qual a assinatura.
* @return NodeList da politica de assinatura ou nulo.
* @throws DOMException
*/
public NodeList getSignaturePolicyIdentifier(int ix) throws DOMException {
NodeList signaturePolicyIdentifier = null;
if (this.getAssinaturas().isEmpty()){
return signaturePolicyIdentifier;
}
if (!this.getAssinaturas().get(ix).getObjects().isEmpty()){
DOMXMLObject objDX = null;
Iterator<?> it = this.getAssinaturas().get(ix).getObjects().iterator();
while (it.hasNext()) {
Object ob1 = it.next();
if (ob1 instanceof DOMXMLObject){
objDX = (DOMXMLObject) ob1;
for (int i=0; i < objDX.getContent().size();i++){
DOMStructure Dos = (DOMStructure) objDX.getContent().get(i);
if (Dos.getNode().getLocalName() == "QualifyingProperties"){
Element el = (Element) Dos.getNode();
signaturePolicyIdentifier = el.getElementsByTagName("SignaturePolicyIdentifier");
break;
}
}
// se a lista estiver vazia retornar� nulo
if (signaturePolicyIdentifier.getLength() < 1){
signaturePolicyIdentifier = null;
}
}
}
}
return signaturePolicyIdentifier;
}
/**
* Retorna SigPolicyId, que e uma das propriedades de SignaturePolicyIdentifier
* @param ix indica de qual a assinatura.
* @return String de SigPolicyId
* @throws DOMException
*/
public String getSigPolicyId(int ix) throws DOMException {
String sigPolicyId = null;
if (this.getAssinaturas().isEmpty()){
return sigPolicyId;
}
if (!this.getAssinaturas().get(ix).getObjects().isEmpty()){
DOMXMLObject objDX = null;
Iterator<?> it = this.getAssinaturas().get(ix).getObjects().iterator();
while (it.hasNext()) {
Object ob1 = it.next();
if (ob1 instanceof DOMXMLObject){
objDX = (DOMXMLObject) ob1;
for (int i=0; i < objDX.getContent().size();i++){
DOMStructure Dos = (DOMStructure) objDX.getContent().get(i);
if (Dos.getNode().getLocalName() == "QualifyingProperties"){
Element el = (Element) Dos.getNode();
NodeList nodeSigId = el.getElementsByTagName("SigPolicyId");
if (nodeSigId.getLength() > 0){
sigPolicyId = nodeSigId.item(0).getTextContent();
}
break;
}
}
}
}
}
return sigPolicyId;
}
/**
* Retorna SPURI, que eh uma das propriedades de SignaturePolicyIdentifier
* @param ix indica de qual a assinatura.
* @return String de SPURI
* @throws DOMException
*/
public String getSPURI(int ix) throws DOMException {
String SPURI = null;
if (this.getAssinaturas().isEmpty()){
return SPURI;
}
if (!this.getAssinaturas().get(ix).getObjects().isEmpty()){
DOMXMLObject objDX = null;
Iterator<?> it = this.getAssinaturas().get(ix).getObjects().iterator();
while (it.hasNext()) {
Object ob1 = it.next();
if (ob1 instanceof DOMXMLObject){
objDX = (DOMXMLObject) ob1;
for (int i=0; i < objDX.getContent().size();i++){
DOMStructure Dos = (DOMStructure) objDX.getContent().get(i);
if (Dos.getNode().getLocalName() == "QualifyingProperties"){
Element el = (Element) Dos.getNode();
NodeList nodeSPURI = el.getElementsByTagName("SPURI");
if (nodeSPURI.getLength() > 0){
SPURI = nodeSPURI.item(0).getTextContent();
}
break;
}
}
}
}
}
return SPURI;
}
/**
* Retorna DataObjectFormat do objeto Assinado
* Eh uma das propriedades assinadas obrigatorias da ICP-BRASIL. Nao faz muito sentido para ENVELOPEDXML.
* @param ix indica de qual a assinatura.
* @return String com formato (MimeTye) do conteudo assinado.
* @throws Exception
*/
public String getDataObjectFormat(int ix) throws DOMException {
String dataObjectFormat = null;
if (this.getAssinaturas().isEmpty()){
return dataObjectFormat;
}
if (!this.getAssinaturas().get(ix).getObjects().isEmpty()){
DOMXMLObject objDX = null;
Iterator<?> it = this.getAssinaturas().get(ix).getObjects().iterator();
while (it.hasNext()) {
Object ob1 = it.next();
if (ob1 instanceof DOMXMLObject){
objDX = (DOMXMLObject) ob1;
for (int i=0; i < objDX.getContent().size();i++){
DOMStructure Dos = (DOMStructure) objDX.getContent().get(i);
if (Dos.getNode().getLocalName() == "QualifyingProperties"){
Element el = (Element) Dos.getNode();
NodeList nodeMimeType = el.getElementsByTagName("MimeType");
if (nodeMimeType.getLength() > 0 ){
dataObjectFormat = nodeMimeType.item(0).getTextContent();
}
break;
}
}
}
}
}
return dataObjectFormat;
}
}