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.Base64Utils; import gov.pr.celepar.tabeliao.util.CertificationChainAndSignatureBase64; import gov.pr.celepar.tabeliao.util.PrivateKeyAndCertChain; import gov.pr.celepar.tabeliao.util.XmlSigUtil; import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.GregorianCalendar; import java.util.List; import java.util.Locale; import javax.xml.crypto.MarshalException; import javax.xml.crypto.dom.DOMStructure; import javax.xml.crypto.dsig.CanonicalizationMethod; import javax.xml.crypto.dsig.DigestMethod; import javax.xml.crypto.dsig.Reference; import javax.xml.crypto.dsig.SignatureMethod; import javax.xml.crypto.dsig.SignedInfo; import javax.xml.crypto.dsig.Transform; import javax.xml.crypto.dsig.XMLObject; import javax.xml.crypto.dsig.XMLSignature; import javax.xml.crypto.dsig.XMLSignatureException; import javax.xml.crypto.dsig.XMLSignatureFactory; import javax.xml.crypto.dsig.dom.DOMSignContext; import javax.xml.crypto.dsig.keyinfo.KeyInfo; import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; import javax.xml.crypto.dsig.keyinfo.X509Data; import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; import javax.xml.crypto.dsig.spec.TransformParameterSpec; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; 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 geracao do arquivo XML Assinado no formato Enveloped * Criando as propriedades XADES reconhecidas pela ICP-BRASIL * de acordo com os documentos DOC-ICP-15.05 e DOC-ICP-15.02 * * @author Emerson Sachio Saito - GIC/CELEPAR * */ public class GerarEnvelopedXML { private GerarEnvelopedXML(){ } /** * Prepara o arquivo XML para assinatura e retorna o documento * * @deprecated Interface sem op��o de contra-assinatura, mudou a assinatura para: assinarArquivoEnvelopedXml * @param aFileName -> Nome do arquivo * @param tagToSign -> nome da tag a ser assinada, se nulo assina o documento todo. * @param politicaId -> Id da politica de Assinatura * @param politicaUri -> url onde se entra a politica de assinatura * @param privateKeyAndCertChain -> KeyStore * @see gov.pr.celepar.tabeliao.util.PrivateKeyAndCertChain * @return Document * @throws XMLSignatureException * */ public static Document signFileEnvelopedXml(String aFileName, String tagToSign, String politicaId, String politicaUri, PrivateKeyAndCertChain privateKeyAndCertChain) throws XMLSignatureException { // Carrega o arquivo XML a ser assinado DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); try { Document docAssinar = dbf.newDocumentBuilder().parse(new FileInputStream(aFileName)); Document signingResult = signDocumentEnvelopedXml(docAssinar, tagToSign, politicaId, politicaUri, privateKeyAndCertChain); return signingResult; }catch (ParserConfigurationException pcex) { String errorMessage = "Erro no Parser do arquivo para assinar, verificar se � arquivo XML v�lido" + aFileName + "."; throw new XMLSignatureException(errorMessage, pcex); } catch (FileNotFoundException fnfe) { String errorMessage = "N�o foi poss�vel ler o arquivo para assinar " + aFileName + "."; throw new XMLSignatureException(errorMessage, fnfe); } catch (SAXException saxe) { String errorMessage = "Erro ao tentar ler o arquivo para assinar, verificar se � arquivo XML v�lido" + aFileName + "."; throw new XMLSignatureException(errorMessage, saxe); } catch (IOException ioe) { String errorMessage = "Erro ao tentar ler o arquivo para assinar, problema de IO:" + aFileName + "."; throw new XMLSignatureException(errorMessage, ioe); } } /** * Prepara o arquivo XML para assinatura e retorna o documento, * Na contra-assinatura a TAG da assinatura anterior faz parte da tag CounterSignture * * @param aFile -> java.io.InputStream com XML Assinado * @param tagToSign -> nome da tag a ser assinada, se nulo assina o documento todo. * @param politicaId -> Id da politica de Assinatura * @param politicaUri -> url onde se entra a politica de assinatura * @param contraAssinatura -> se true faz contra-assinatura * @param privateKeyAndCertChain -> KeyStore * @see gov.pr.celepar.tabeliao.util.PrivateKeyAndCertChain * @return Document * @throws XMLSignatureException */ public static Document assinarArquivoEnvelopedXml(InputStream aFile, String tagToSign, String politicaId, String politicaUri, boolean contraAssinatura, PrivateKeyAndCertChain privateKeyAndCertChain) throws XMLSignatureException { Document docAssinar; try { docAssinar = XmlSigUtil.carregarArquivoXML(aFile); } catch (ParserConfigurationException e) { String errorMessage = "Erro ao carregar o arquivo a ser assinado\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } catch (SAXException e) { String errorMessage = "Erro ao carregar o arquivo a ser assinado\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } catch (IOException e) { String errorMessage = "Erro ao carregar o arquivo a ser assinado\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } Document signingResult = assinandoDocumentoEnvelopedXml(docAssinar, tagToSign, politicaId, politicaUri, contraAssinatura, privateKeyAndCertChain); return signingResult; } /** * Prepara o arquivo XML para assinatura e retorna o documento, * Na contra-assinatura a TAG da assinatura anterior faz parte da tag CounterSignture * * @param arquivoDocument -> Arquivo do tipo org.w3c.dom.Document * @param tagToSign -> nome da tag a ser assinada, se nulo assina o documento todo. * @param politicaId -> Id da politica de Assinatura * @param politicaUri -> url onde se entra a politica de assinatura * @param contraAssinatura -> se true faz contra-assinatura * @param privateKeyAndCertChain -> KeyStore * @see gov.pr.celepar.tabeliao.util.PrivateKeyAndCertChain * @return Document * @throws XMLSignatureException */ public static Document assinarArquivoEnvelopedXml(Document arquivoDocument, String tagToSign, String politicaId, String politicaUri, boolean contraAssinatura, PrivateKeyAndCertChain privateKeyAndCertChain) throws XMLSignatureException { Document docAssinar = arquivoDocument; Document signingResult = assinandoDocumentoEnvelopedXml(docAssinar, tagToSign, politicaId, politicaUri, contraAssinatura, privateKeyAndCertChain); return signingResult; } /** * Prepara o arquivo XML para assinatura e retorna o documento, * Na contra-assinatura a TAG da assinatura anterior faz parte da tag CounterSignture * * @param conteudo -> Conteudo para assinatura do tipo byte[] * @param tagToSign -> nome da tag a ser assinada, se nulo assina o documento todo. * @param politicaId -> Id da politica de Assinatura * @param politicaUri -> url onde se entra a politica de assinatura * @param contraAssinatura -> se true faz contra-assinatura * @param privateKeyAndCertChain -> KeyStore * @see gov.pr.celepar.tabeliao.util.PrivateKeyAndCertChain * @return Document * @throws XMLSignatureException */ public static Document assinarArquivoEnvelopedXml(byte[] conteudo, String tagToSign, String politicaId, String politicaUri, boolean contraAssinatura, PrivateKeyAndCertChain privateKeyAndCertChain) throws XMLSignatureException { Document docAssinar; try { docAssinar = XmlSigUtil.carregarArquivoXML(new ByteArrayInputStream(conteudo)); } catch (ParserConfigurationException e) { String errorMessage = "Erro ao carregar o arquivo a ser assinado\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } catch (SAXException e) { String errorMessage = "Erro ao carregar o arquivo a ser assinado\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } catch (IOException e) { String errorMessage = "Erro ao carregar o arquivo a ser assinado\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } Document signingResult = assinandoDocumentoEnvelopedXml(docAssinar, tagToSign, politicaId, politicaUri, contraAssinatura, privateKeyAndCertChain); return signingResult; } /** * Prepara o arquivo XML para assinatura e retorna o documento, * Na contra-assinatura a TAG da assinatura anterior faz parte da tag CounterSignture * * @param conteudoString -> Conteudo para assinatura do tipo String * @param tagToSign -> nome da tag a ser assinada, se nulo assina o documento todo. * @param politicaId -> Id da politica de Assinatura * @param politicaUri -> url onde se entra a politica de assinatura * @param contraAssinatura -> se true faz contra-assinatura * @param privateKeyAndCertChain -> KeyStore * @see gov.pr.celepar.tabeliao.util.PrivateKeyAndCertChain * @return Document * @throws XMLSignatureException */ public static Document assinarArquivoEnvelopedXml(String conteudoString, String tagToSign, String politicaId, String politicaUri, boolean contraAssinatura, PrivateKeyAndCertChain privateKeyAndCertChain) throws XMLSignatureException { Document docAssinar; try { docAssinar = XmlSigUtil.carregarArquivoXML(conteudoString); } catch (ParserConfigurationException e) { String errorMessage = "Erro ao carregar o arquivo a ser assinado\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } catch (SAXException e) { String errorMessage = "Erro ao carregar o arquivo a ser assinado\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } catch (IOException e) { String errorMessage = "Erro ao carregar o arquivo a ser assinado\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } Document signingResult = assinandoDocumentoEnvelopedXml(docAssinar, tagToSign, politicaId, politicaUri, contraAssinatura, privateKeyAndCertChain); return signingResult; } /** * Prepara o arquivo XML para assinatura e retorna o documento, * Na contra-assinatura a TAG da assinatura anterior faz parte da tag CounterSignture * * @param conteudoInputSource -> Conteudo para assinatura do tipo org.xml.sax.InputSource * @param tagToSign -> nome da tag a ser assinada, se nulo assina o documento todo. * @param politicaId -> Id da politica de Assinatura * @param politicaUri -> url onde se entra a politica de assinatura * @param contraAssinatura -> se true faz contra-assinatura * @param privateKeyAndCertChain -> KeyStore * @see gov.pr.celepar.tabeliao.util.PrivateKeyAndCertChain * @return Document * @throws XMLSignatureException */ public static Document assinarArquivoEnvelopedXml(InputSource conteudoInputSource, String tagToSign, String politicaId, String politicaUri, boolean contraAssinatura, PrivateKeyAndCertChain privateKeyAndCertChain) throws XMLSignatureException { Document docAssinar; try { docAssinar = XmlSigUtil.carregarArquivoXML(conteudoInputSource); } catch (ParserConfigurationException e) { String errorMessage = "Erro ao carregar o arquivo a ser assinado\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } catch (SAXException e) { String errorMessage = "Erro ao carregar o arquivo a ser assinado\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } catch (IOException e) { String errorMessage = "Erro ao carregar o arquivo a ser assinado\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } Document signingResult = assinandoDocumentoEnvelopedXml(docAssinar, tagToSign, politicaId, politicaUri, contraAssinatura, privateKeyAndCertChain); return signingResult; } /** * Assina o arquivo XML e retorna o documento * * @deprecated Interface sem op��o de contra-assinatura, mudou a interface para: assinandoDocumentoEnvelopedXml * @param aDocumentToSign -> Arquivo xml para assinatura * @param tagToSign -> nome da tag a ser assinada, se nulo assina o documento todo. Se usada, necessida de um identificador para a TAG so e permitido: Id/ID/id. * @param politicaId -> Id da politica de Assinatura * @param politicaUri -> url onde se entra a politica de assinatura * @param privateKeyAndCertChain -> KeyStore * @return Document * @throws XMLSignatureException */ public static Document signDocumentEnvelopedXml(Document aDocumentToSign, String tagToSign, String politicaId, String politicaUri, PrivateKeyAndCertChain privateKeyAndCertChain) throws XMLSignatureException { // constante para metodo de transforma��o XML String C14N_TRANSFORM_METHOD = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"; // Checa se a chave privada est� dispon�vel PrivateKey privateKey = privateKeyAndCertChain.mPrivateKey; if (privateKey == null) { String errorMessage = "N�o achou a chave privada do smart card."; throw new XMLSignatureException(errorMessage); } // Checa se certificado X.509 est� dispon�vel Certificate[] certChain = privateKeyAndCertChain.mCertificationChain; if (certChain == null) { String errorMessage = "N�o achou o certificado p�blico."; throw new XMLSignatureException(errorMessage); } // Criando o result object CertificationChainAndSignatureBase64 signingResult = new CertificationChainAndSignatureBase64(); // Salva a cadeia de certificados X.509 em Base64 try { signingResult.mCertificationChain = Base64Utils.encodeX509CertChainToBase64(certChain); } catch (CertificateException cee) { String errorMessage = "Certificado inv�lido."; throw new XMLSignatureException(errorMessage); } // Cria as constantes. String xadesNS="http://uri.etsi.org/01903/v1.3.2#"; String varMimeType = "text/xml"; // Criar uma DOM XMLSignatureFactory que ser� usada para a assinatura envolopada XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM"); // Criar uma Referencia para o enveloped document (se a URI for "", significa que // a assinatura e para o documento todos. // tambem est� sendo especificado o algoritimo de hash SHA1 e // a transformacao ENVELOPED para o XML. // Obtem id do elemento (TAG) do documento a ser assinado, String id = ""; if (tagToSign != null){ if (tagToSign.trim().length() > 0 && !tagToSign.trim().equalsIgnoreCase("null")){ NodeList elements = aDocumentToSign.getElementsByTagName(tagToSign); org.w3c.dom.Element el = (org.w3c.dom.Element) elements.item(0); if( (id = el.getAttribute("id")) != "" || (id = el.getAttribute("iD")) != "" || (id = el.getAttribute("Id")) != "" || (id = el.getAttribute("ID")) != ""){ id = "#"+id; } } } Reference ref; try { ArrayList<Transform> transformList = new ArrayList<Transform>(); TransformParameterSpec tps = null; Transform envelopedTransform = fac.newTransform(Transform.ENVELOPED, tps); Transform c14NTransform = fac.newTransform(C14N_TRANSFORM_METHOD, tps); transformList.add(envelopedTransform); transformList.add(c14NTransform); ArrayList<Reference> refList = new ArrayList<Reference>(); DigestMethod digestMethod = fac.newDigestMethod( DigestMethod.SHA1, null); ref = fac.newReference(id,digestMethod, transformList, null, null); refList.add(ref); // Criar a SignedInfo. SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null),fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(ref)); List<Certificate> list = new ArrayList<Certificate>(); for(int i=0 ; i<certChain.length ; i++) { list.add(certChain[i]); } X509Certificate cert = (X509Certificate)certChain[0]; // Cria o KeyInfo contido em X509Data. KeyInfoFactory kif = fac.getKeyInfoFactory(); List<Serializable> x509Content = new ArrayList<Serializable>(); x509Content.add(cert.getSubjectX500Principal().getName()); x509Content.add(cert); X509Data xd = kif.newX509Data(x509Content); KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd)); // Cria o DOMSignContext e especifica a chave RSA e // a localizacao da Assinatura XML resultante do elemento pai DOMSignContext dsc = new DOMSignContext (privateKey, aDocumentToSign.getDocumentElement()); // Element QPElement = XmlSigUtil.criarElemento(aDocumentToSign,"QualifyingProperties",null,xadesNS); Element SPElement = XmlSigUtil.criarElemento(aDocumentToSign, "SignedProperties", null,xadesNS); SPElement.setAttributeNS(null, "Id", "SignedProperties"); QPElement.appendChild(SPElement); Element SSPElement = XmlSigUtil.criarElemento(aDocumentToSign, "SignedSignatureProperties", null,xadesNS); SPElement.appendChild(SSPElement); Element STElement = XmlSigUtil.criarElemento(aDocumentToSign, "SigningTime", null,xadesNS); Locale locale = new Locale("pt","BR"); GregorianCalendar calendar = new GregorianCalendar(); SimpleDateFormat formatador = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ",locale); STElement.setTextContent(formatador.format(calendar.getTime())); SSPElement.appendChild(STElement); Element SCElement = XmlSigUtil.criarElemento(aDocumentToSign, "SigningCertificate", null,xadesNS); Element certElement = XmlSigUtil.criarElemento(aDocumentToSign, "cert", null,xadesNS); Element certDigestElement = XmlSigUtil.criarElemento(aDocumentToSign, "CertDigest", null,xadesNS); Element DigestMethodElement = XmlSigUtil.criarElemento(aDocumentToSign, "DigestMethod", null,xadesNS); DigestMethodElement.setAttributeNS(null,"Algorithm", cert.getSigAlgName()); certDigestElement.appendChild(DigestMethodElement); Element DigestValueElement = XmlSigUtil.criarElemento(aDocumentToSign, "DigestValue", null,xadesNS); DigestValueElement.setTextContent(Integer.toString(cert.hashCode())); certDigestElement.appendChild(DigestValueElement); certElement.appendChild(certDigestElement); Element certIssuerSerial = XmlSigUtil.criarElemento(aDocumentToSign, "IssuerSerial", null,xadesNS); Element X509IssuerName = XmlSigUtil.criarElemento(aDocumentToSign, "X509IssuerName", null,xadesNS); X509IssuerName.setTextContent(cert.getIssuerDN().getName()); certIssuerSerial.appendChild(X509IssuerName); Element X509SerialNumber = XmlSigUtil.criarElemento(aDocumentToSign, "X509SerialNumber", null,xadesNS); X509SerialNumber.setTextContent(cert.getSerialNumber().toString()); certIssuerSerial.appendChild(X509SerialNumber); certElement.appendChild(certIssuerSerial); SCElement.appendChild(certElement); SSPElement.appendChild(SCElement); if (politicaId != null){ if (politicaId.trim().length() > 0 && !politicaId.trim().equalsIgnoreCase("null")){ Element SPIElement = XmlSigUtil.criarElemento(aDocumentToSign, "SignaturePolicyIdentifier", null,xadesNS); Element SPIdElement = XmlSigUtil.criarElemento(aDocumentToSign, "SignaturePolicyId", null,xadesNS); Element SiPIdElement = XmlSigUtil.criarElemento(aDocumentToSign, "SigPolicyId", null,xadesNS); SiPIdElement.setTextContent(politicaId); //Element SPHElement = XmlSigUtil.criarElemento(aDocumentToSign, "SigPolicyHash", null,xadesNS); Element SPQElement = XmlSigUtil.criarElemento(aDocumentToSign, "SigPolicyQualifiers", null,xadesNS); Element SPQrElement = XmlSigUtil.criarElemento(aDocumentToSign, "SigPolicyQualifier", null,xadesNS); Element SPUriElement = XmlSigUtil.criarElemento(aDocumentToSign, "SPURI", null,xadesNS); SPUriElement.setTextContent(politicaUri); SPQrElement.appendChild(SPUriElement); SPQElement.appendChild(SPQrElement); SPIdElement.appendChild(SiPIdElement); //SPIdElement.appendChild(SPHElement); SPIdElement.appendChild(SPQElement); SPIElement.appendChild(SPIdElement); SSPElement.appendChild(SPIElement); } } //Element SPPElement = XmlSigUtil.criarElemento(aDocumentToSign, "SignatureProductionPlace", null,xadesNS); //SSPElement.appendChild(SPPElement); //Element SRElement = XmlSigUtil.criarElemento(aDocumentToSign, "SignerRole", null,xadesNS); //SSPElement.appendChild(SRElement); Element SDOPElement = XmlSigUtil.criarElemento(aDocumentToSign, "SignedDataObjectProperties", null,xadesNS); SPElement.appendChild(SDOPElement); Element DOFElement = XmlSigUtil.criarElemento(aDocumentToSign, "DataObjectFormat", null,xadesNS); Element mimetype = XmlSigUtil.criarElemento(aDocumentToSign,"MimeType",null,xadesNS); mimetype.setTextContent(varMimeType); DOFElement.appendChild(mimetype); SDOPElement.appendChild(DOFElement); //Element UPElement = XmlSigUtil.criarElemento(aDocumentToSign, "UnsignedProperties", null,xadesNS); //QPElement.appendChild(UPElement); DOMStructure qualifPropStruct = new DOMStructure(QPElement); List<DOMStructure> xmlObj = new ArrayList<DOMStructure>(); xmlObj.add(qualifPropStruct); XMLObject object = fac.newXMLObject(xmlObj,null,null,null); List<XMLObject> objects = Collections.singletonList(object); // Cria a assinatura XML, mas ainda n�o assina. XMLSignature signature = fac.newXMLSignature(si, ki,objects,null,null); // efetua a assinatura. signature.sign(dsc); } catch (NoSuchAlgorithmException nsae) { String errorMessage = "Algoritmo n�o encontrado ao assinar o arquivo.\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + nsae.getMessage(); throw new XMLSignatureException(errorMessage, nsae); } catch (InvalidAlgorithmParameterException iape) { String errorMessage = "Algoritmo inv�lido ao assinar o arquivo.\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + iape.getMessage(); throw new XMLSignatureException(errorMessage, iape); } catch (MarshalException me) { String errorMessage = "Erro do tipo Marshal ao assinar o arquivo XML.\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + me.getMessage(); throw new XMLSignatureException(errorMessage, me); }catch (Exception e) { String errorMessage = "Erro do tipo Exception ao assinar o arquivo XML.\n" + "Anote este erro e contate com o respons�vel pelo sistema!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } return aDocumentToSign; } /** * Assina o arquivo XML e retorna o documento, com op��o de contra-assinatura * * @param aDocumentToSign -> Arquivo xml para assinatura * @param tagToSign -> nome da tag a ser assinada, se nulo assina o documento todo. Se usada, necessida de um identificador para a TAG so e permitido: Id/ID/id. * @param politicaId -> Id da politica de Assinatura * @param politicaUri -> url onde se entra a politica de assinatura * @param contraAssinatura -> se true, faz a contra assinatura * @param privateKeyAndCertChain -> KeyStore * @return Document * @throws XMLSignatureException */ public static Document assinandoDocumentoEnvelopedXml(Document aDocumentToSign, String tagToSign, String politicaId, String politicaUri, boolean contraAssinatura, PrivateKeyAndCertChain privateKeyAndCertChain) throws XMLSignatureException { // constante para metodo de transforma��o XML String C14N_TRANSFORM_METHOD = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"; // Checa se a chave privada est� dispon�vel PrivateKey privateKey = privateKeyAndCertChain.mPrivateKey; if (privateKey == null) { String errorMessage = "N�o achou a chave privada do smart card."; throw new XMLSignatureException(errorMessage); } // Checa se certificado X.509 est� dispon�vel Certificate[] certChain = privateKeyAndCertChain.mCertificationChain; if (certChain == null) { String errorMessage = "N�o achou o certificado p�blico."; throw new XMLSignatureException(errorMessage); } // Criando o result object CertificationChainAndSignatureBase64 signingResult = new CertificationChainAndSignatureBase64(); // Salva a cadeia de certificados X.509 em Base64 try { signingResult.mCertificationChain = Base64Utils.encodeX509CertChainToBase64(certChain); } catch (CertificateException cee) { String errorMessage = "Certificado inv�lido."; throw new XMLSignatureException(errorMessage); } // Cria as constantes. String xadesNS="http://uri.etsi.org/01903/v1.3.2#"; String varMimeType = "text/xml"; // Criar uma DOM XMLSignatureFactory que ser� usada para a assinatura envolopada XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM"); // Criar uma Referencia para o enveloped document (se a URI for "", significa que // a assinatura e para o documento todos. // tambem est� sendo especificado o algoritimo de hash SHA1 e // a transformacao ENVELOPED para o XML. // Obtem id do elemento (TAG) do documento a ser assinado, String id = ""; if (tagToSign != null){ if (tagToSign.trim().length() > 0 && !tagToSign.trim().equalsIgnoreCase("null")){ NodeList elements = aDocumentToSign.getElementsByTagName(tagToSign); org.w3c.dom.Element el = (org.w3c.dom.Element) elements.item(0); if( (id = el.getAttribute("id")) != "" || (id = el.getAttribute("iD")) != "" || (id = el.getAttribute("Id")) != "" || (id = el.getAttribute("ID")) != ""){ id = "#"+id; } } } NodeList contraAssinaturaNL = null; if (contraAssinatura) { contraAssinaturaNL = aDocumentToSign.getElementsByTagName("Signature"); if (contraAssinaturaNL.getLength() < 1){ try { throw new Exception("N�o h� assinatura para contra-assinar"); } catch (Exception e) { String errorMessage = "Erro ao gerar Contra-Assinatura.\n" + "N�o foi encontrada uma assinatura no arquivo XML!\n" + "Verifique o arquivo ou n�o utilize a op��o: Contra-Assinatura!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } } } Reference ref; try { ArrayList<Transform> transformList = new ArrayList<Transform>(); TransformParameterSpec tps = null; Transform envelopedTransform = fac.newTransform(Transform.ENVELOPED, tps); Transform c14NTransform = fac.newTransform(C14N_TRANSFORM_METHOD, tps); transformList.add(envelopedTransform); transformList.add(c14NTransform); ArrayList<Reference> refList = new ArrayList<Reference>(); DigestMethod digestMethod = fac.newDigestMethod( DigestMethod.SHA1, null); ref = fac.newReference(id,digestMethod, transformList, null, null); refList.add(ref); // Criar a SignedInfo. SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null),fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(ref)); List<Certificate> list = new ArrayList<Certificate>(); for(int i=0 ; i<certChain.length ; i++) { list.add(certChain[i]); } X509Certificate cert = (X509Certificate)certChain[0]; // Cria o KeyInfo contido em X509Data. KeyInfoFactory kif = fac.getKeyInfoFactory(); List<Serializable> x509Content = new ArrayList<Serializable>(); x509Content.add(cert.getSubjectX500Principal().getName()); x509Content.add(cert); X509Data xd = kif.newX509Data(x509Content); KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd)); // Cria o DOMSignContext e especifica a chave RSA e // a localizacao da Assinatura XML resultante do elemento pai DOMSignContext dsc = new DOMSignContext (privateKey, aDocumentToSign.getDocumentElement()); // Element QPElement = XmlSigUtil.criarElemento(aDocumentToSign,"QualifyingProperties",null,xadesNS); Element SPElement = XmlSigUtil.criarElemento(aDocumentToSign, "SignedProperties", null,xadesNS); SPElement.setAttributeNS(null, "Id", "SignedProperties"); QPElement.appendChild(SPElement); Element SSPElement = XmlSigUtil.criarElemento(aDocumentToSign, "SignedSignatureProperties", null,xadesNS); SPElement.appendChild(SSPElement); Element STElement = XmlSigUtil.criarElemento(aDocumentToSign, "SigningTime", null,xadesNS); Locale locale = new Locale("pt","BR"); GregorianCalendar calendar = new GregorianCalendar(); SimpleDateFormat formatador = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ",locale); STElement.setTextContent(formatador.format(calendar.getTime())); SSPElement.appendChild(STElement); Element SCElement = XmlSigUtil.criarElemento(aDocumentToSign, "SigningCertificate", null,xadesNS); Element certElement = XmlSigUtil.criarElemento(aDocumentToSign, "cert", null,xadesNS); Element certDigestElement = XmlSigUtil.criarElemento(aDocumentToSign, "CertDigest", null,xadesNS); Element DigestMethodElement = XmlSigUtil.criarElemento(aDocumentToSign, "DigestMethod", null,xadesNS); DigestMethodElement.setAttributeNS(null,"Algorithm", cert.getSigAlgName()); certDigestElement.appendChild(DigestMethodElement); Element DigestValueElement = XmlSigUtil.criarElemento(aDocumentToSign, "DigestValue", null,xadesNS); DigestValueElement.setTextContent(Integer.toString(cert.hashCode())); certDigestElement.appendChild(DigestValueElement); certElement.appendChild(certDigestElement); Element certIssuerSerial = XmlSigUtil.criarElemento(aDocumentToSign, "IssuerSerial", null,xadesNS); Element X509IssuerName = XmlSigUtil.criarElemento(aDocumentToSign, "X509IssuerName", null,xadesNS); X509IssuerName.setTextContent(cert.getIssuerDN().getName()); certIssuerSerial.appendChild(X509IssuerName); Element X509SerialNumber = XmlSigUtil.criarElemento(aDocumentToSign, "X509SerialNumber", null,xadesNS); X509SerialNumber.setTextContent(cert.getSerialNumber().toString()); certIssuerSerial.appendChild(X509SerialNumber); certElement.appendChild(certIssuerSerial); SCElement.appendChild(certElement); SSPElement.appendChild(SCElement); if (politicaId != null){ if (politicaId.trim().length() > 0 && !politicaId.trim().equalsIgnoreCase("null")){ Element SPIElement = XmlSigUtil.criarElemento(aDocumentToSign, "SignaturePolicyIdentifier", null,xadesNS); Element SPIdElement = XmlSigUtil.criarElemento(aDocumentToSign, "SignaturePolicyId", null,xadesNS); Element SiPIdElement = XmlSigUtil.criarElemento(aDocumentToSign, "SigPolicyId", null,xadesNS); SiPIdElement.setTextContent(politicaId); //Element SPHElement = XmlSigUtil.criarElemento(aDocumentToSign, "SigPolicyHash", null,xadesNS); Element SPQElement = XmlSigUtil.criarElemento(aDocumentToSign, "SigPolicyQualifiers", null,xadesNS); Element SPQrElement = XmlSigUtil.criarElemento(aDocumentToSign, "SigPolicyQualifier", null,xadesNS); Element SPUriElement = XmlSigUtil.criarElemento(aDocumentToSign, "SPURI", null,xadesNS); SPUriElement.setTextContent(politicaUri); SPQrElement.appendChild(SPUriElement); SPQElement.appendChild(SPQrElement); SPIdElement.appendChild(SiPIdElement); //SPIdElement.appendChild(SPHElement); SPIdElement.appendChild(SPQElement); SPIElement.appendChild(SPIdElement); SSPElement.appendChild(SPIElement); } } //Element SPPElement = XmlSigUtil.criarElemento(aDocumentToSign, "SignatureProductionPlace", null,xadesNS); //SSPElement.appendChild(SPPElement); //Element SRElement = XmlSigUtil.criarElemento(aDocumentToSign, "SignerRole", null,xadesNS); //SSPElement.appendChild(SRElement); Element SDOPElement = XmlSigUtil.criarElemento(aDocumentToSign, "SignedDataObjectProperties", null,xadesNS); SPElement.appendChild(SDOPElement); Element DOFElement = XmlSigUtil.criarElemento(aDocumentToSign, "DataObjectFormat", null,xadesNS); Element mimetype = XmlSigUtil.criarElemento(aDocumentToSign,"MimeType",null,xadesNS); mimetype.setTextContent(varMimeType); DOFElement.appendChild(mimetype); SDOPElement.appendChild(DOFElement); if (contraAssinaturaNL != null) { Element UPElement = XmlSigUtil.criarElemento(aDocumentToSign, "UnsignedProperties", null,xadesNS); Element CSElement = XmlSigUtil.criarElemento(aDocumentToSign, "CounterSignature", null,xadesNS); CSElement.appendChild(contraAssinaturaNL.item(0)); UPElement.appendChild(CSElement); QPElement.appendChild(UPElement); } DOMStructure qualifPropStruct = new DOMStructure(QPElement); List<DOMStructure> xmlObj = new ArrayList<DOMStructure>(); xmlObj.add(qualifPropStruct); XMLObject object = fac.newXMLObject(xmlObj,null,null,null); List<XMLObject> objects = Collections.singletonList(object); // Cria a assinatura XML, mas ainda n�o assina. XMLSignature signature = fac.newXMLSignature(si, ki,objects,null,null); // efetua a assinatura. signature.sign(dsc); } catch (NoSuchAlgorithmException nsae) { String errorMessage = "Algoritmo n�o encontrado ao assinar o arquivo.\n" + "Anote este erro e contate o respons�vel pelo sistema!\n" + "Detalhes: " + nsae.getMessage(); throw new XMLSignatureException(errorMessage, nsae); } catch (InvalidAlgorithmParameterException iape) { String errorMessage = "Algoritmo inv�lido ao assinar o arquivo.\n" + "Anote este erro e contate o respons�vel pelo sistema!\n" + "Detalhes: " + iape.getMessage(); throw new XMLSignatureException(errorMessage, iape); } catch (MarshalException me) { String errorMessage = "Erro do tipo Marshal ao assinar o arquivo XML.\n" + "Anote este erro e contate o respons�vel pelo sistema!\n" + "Detalhes: " + me.getMessage(); throw new XMLSignatureException(errorMessage, me); }catch (Exception e) { String errorMessage = "Erro do tipo Exception, ao assinar o arquivo XML.\n" + "Anote este erro e contate o respons�vel pelo sistema!\n" + "Detalhes: " + e.getMessage(); throw new XMLSignatureException(errorMessage, e); } return aDocumentToSign; } }