Consigo assinar, mas como são necessárias assinaturas para cada RPS e para o Lote completo, isso para notas fiscais de serviços em Natal-RN, estou com o seguinte problema: Todas as assinaturas estão saindo após a tag LoteRps, mas as assinaturas dos RPS deveriam sair após a tag InfRps.
InfRps> RPS>ListaRps>
LoteRps>
Transforms>W96COaIvAILx9vgFBT8GNWvF9HE=DigestValue>Reference>SignedInfo>thfrMorJ9ybJGQCtM/wUd75hNEZ2P3m2Q0pxk/yc/FAPIkF5q3Tg8E2rAN0d88aL3Xy+NJqQj4R5
Ehb9USE9sCjJajrccApqWmK3Qb7A0/Puuyng5c7pQDhmIr/9JUhwlBY0J0xEWEWoAiWyCsLREcUP
kEXOmiWBZORtANdYqM4=SignatureValue>MIIGITCCBQmgAwIBAgIQMjAxMDAyMTkxNTA2Mzc4NzANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
BhMCQlIxEzARBgNVBAoTCklDUC1CcmFzaWwxNjA0BgNVBAsTLVNlY3JldGFyaWEgZGEgUmVjZWl0
YSBGZWRlcmFsIGRvIEJyYXNpbCAtIFJGQjEuMCwGA1UEAxMlQXV0b3JpZGFkZSBDZXJ0aWZpY2Fk
k6/OR8Ps8havSS7cWmbu+UNEL3zSGgjOJgzqzZJDXPRKEhTpakuD7Lhvmjx5x8jw9kGziKoC7rzk
LHDbWgMN2USUYsh6E9NvQSR9BH5ubsJo+t9HCwzZKXTuqA==X509Certificate>X509Data>KeyInfo>Signature>
Transforms>knAs0QHNe7sW4fWQN9+ExX8C8UM=DigestValue>Reference>SignedInfo>v5oyMaAca+WI3ibvogXRf21VO3wQHTmWnHT0f7kKaVeCN0BDOb/VMsGxMZiMXg6i06/VL2LoOEcp
nj2rfT8SyFNlJhGSqiz7f2J8v0uWNLUNC5tG/vztLUfHUMraDcAqDUoareTT2nmZc9LQMlKIGtY1
PMnPq0ggy1OytHhObyc=SignatureValue>MIIGITCCBQmgAwIBAgIQMjAxMDAyMTkxNTA2Mzc4NzANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
BhMCQlIxEzARBgNVBAoTCklDUC1CcmFzaWwxNjA0BgNVBAsTLVNlY3JldGFyaWEgZGEgUmVjZWl0
k6/OR8Ps8havSS7cWmbu+UNEL3zSGgjOJgzqzZJDXPRKEhTpakuD7Lhvmjx5x8jw9kGziKoC7rzk
LHDbWgMN2USUYsh6E9NvQSR9BH5ubsJo+t9HCwzZKXTuqA==X509Certificate>X509Data>KeyInfo>Signature>
EnviarLoteRpsEnvio>
A classe que assina:
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.OutputStream; import java.security.KeyStore; import java.security.Provider; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.xml.crypto.dsig.Reference; import javax.xml.crypto.dsig.SignedInfo; import javax.xml.crypto.dsig.Transform; import javax.xml.crypto.dsig.XMLSignature; import javax.xml.crypto.dsig.XMLSignatureFactory; import javax.xml.crypto.dsig.dom.DOMSignContext; import javax.xml.crypto.dsig.dom.DOMValidateContext; 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.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import java.util.Enumeration;
public class Assinador {
private static final String C14N_TRANSFORM_METHOD = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"; private static final String PROVIDER_CLASS_NAME = "org.jcp.xml.dsig.internal.dom.XMLDSigRI"; private static final String PROVIDER_NAME = "jsr105Provider";
public void assinar(String tag, String caminhoXml, String caminhoCertificado, String senha, String caminhoXmlNovo) throws Exception {
String providerName = System.getProperty(PROVIDER_NAME, PROVIDER_CLASS_NAME); XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM", (Provider) Class.forName(providerName).newInstance()); KeyInfoFactory kif = fac.getKeyInfoFactory(); KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(new FileInputStream(caminhoCertificado), senha.toCharArray()); Enumeration aliasesEnum = ks.aliases(); String alias = ""; while (aliasesEnum.hasMoreElements()) { alias = (String) aliasesEnum.nextElement(); if (ks.isKeyEntry(alias)) { break; } } KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, new KeyStore.PasswordProtection(senha.toCharArray())); List transformList = new ArrayList(); TransformParameterSpec tps = null; Transform envelopedTransform = fac.newTransform("http://www.w3.org/2000/09/xmldsig#enveloped-signature", tps); Transform c14NTransform = fac.newTransform("http://www.w3.org/TR/2001/REC-xml-c14n-20010315", tps); transformList.add(envelopedTransform); transformList.add(c14NTransform);
X509Certificate cert = (X509Certificate) keyEntry.getCertificate(); List x509Content = new ArrayList(); x509Content.add(cert); X509Data xd = kif.newX509Data(x509Content); KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(false); DocumentBuilder builder = factory.newDocumentBuilder(); Document docs = builder.parse(new File(caminhoXml)); NodeList elements = docs.getElementsByTagName(tag); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(caminhoXml)); for (int i = 0; i < elements.getLength(); i++) { Element el = (Element) elements.item(i); String id = el.getAttribute("Id"); el.setIdAttribute("Id", true); Reference ref = fac.newReference("#" + id, fac.newDigestMethod("http://www.w3.org/2000/09/xmldsig#sha1", null), transformList, null, null); SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod("http://www.w3.org/TR/2001/REC-xml-c14n-20010315", (C14NMethodParameterSpec) null), fac.newSignatureMethod("http://www.w3.org/2000/09/xmldsig#rsa-sha1", null), Collections.singletonList(ref));
XMLSignature signature = fac.newXMLSignature(si, ki, null, "ass_" + tag + "_" + id, null); DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), doc.getDocumentElement()); signature.sign(dsc); } OutputStream os = new FileOutputStream(caminhoXmlNovo); TransformerFactory tf = TransformerFactory.newInstance(); Transformer trans = tf.newTransformer(); trans.transform(new DOMSource(doc), new StreamResult(os));
NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
if (nl.getLength() == 0) { throw new Exception("Cannot find Signature element"); } DOMValidateContext valContext = new DOMValidateContext(new X509KeySelector(ks), nl.item(0)); XMLSignature signatures = fac.unmarshalXMLSignature(valContext); boolean coreValidity = signatures.validate(valContext); if (coreValidity == false) { System.err.println("Falha na Assinatura!"); } else { System.out.println("Assinatura Correta!"); } }
}