Subversion Repositories Integrator Subversion

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
414 espaco 1
package nfe;
2
 
3
import br.com.swconsultoria.certificado.Certificado;
4
import br.com.swconsultoria.certificado.CertificadoService;
5
import br.com.swconsultoria.certificado.exception.CertificadoException;
6
import br.com.swconsultoria.nfe.dom.ConfiguracoesNfe;
7
import br.com.swconsultoria.nfe.dom.enuns.AssinaturaEnum;
8
import br.com.swconsultoria.nfe.exception.NfeException;
9
import br.com.swconsultoria.nfe.util.ObjetoUtil;
10
import org.w3c.dom.Document;
11
import org.w3c.dom.NodeList;
12
import org.xml.sax.InputSource;
13
import org.xml.sax.SAXException;
14
 
15
import javax.xml.crypto.MarshalException;
16
import javax.xml.crypto.dsig.*;
17
import javax.xml.crypto.dsig.dom.DOMSignContext;
18
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
19
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
20
import javax.xml.crypto.dsig.keyinfo.X509Data;
21
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
22
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
23
import javax.xml.parsers.DocumentBuilder;
24
import javax.xml.parsers.DocumentBuilderFactory;
25
import javax.xml.parsers.ParserConfigurationException;
26
import javax.xml.transform.Transformer;
27
import javax.xml.transform.TransformerException;
28
import javax.xml.transform.TransformerFactory;
29
import javax.xml.transform.dom.DOMSource;
30
import javax.xml.transform.stream.StreamResult;
31
import java.io.ByteArrayOutputStream;
32
import java.io.IOException;
33
import java.io.StringReader;
34
import java.security.*;
35
import java.security.cert.X509Certificate;
36
import java.util.ArrayList;
37
import java.util.Collections;
38
import java.util.List;
39
 
40
/**
41
 * Classe Responsavel Por Assinar O Xml.
42
 *
43
 * @author Samuel Oliveira - samuel@swconsultoria.com.br - www.swconsultoria.com.br
44
 */
45
public class Assinar {
46
 
47
    private static PrivateKey privateKey;
48
    private static KeyInfo keyInfo;
49
    Assinar assinarXMLsCertfificadoA1;
50
 
51
    /**
52
     * @param stringXml
53
     * @param tipoAssinatura ('NFe' para nfe normal , 'infInut' para inutilizacao, 'evento'
54
     *                       para eventos)
55
     * @return String do Xml Assinado
56
     * @throws NfeException
57
     */
58
    public static String assinaNfe(ConfiguracoesNfe config, String stringXml, AssinaturaEnum tipoAssinatura) throws NfeException {
59
 
60
        stringXml = stringXml.replaceAll("\r\n", "").replaceAll("\n", "").replaceAll(System.lineSeparator(), ""); // Erro quando tem salto de linha.
61
        stringXml = stringXml.replaceAll("\\s+<", "<"); // Erro Espaço antes do final da Tag.
62
        stringXml = assinaDocNFe(config, stringXml, tipoAssinatura);
63
        stringXml = stringXml.replaceAll("&#13;", ""); // Java 11
64
 
65
        return stringXml;
66
    }
67
 
68
    private static String assinaDocNFe(ConfiguracoesNfe config, String xml, AssinaturaEnum tipoAssinatura) throws NfeException {
69
 
70
        try {
71
            Document document = documentFactory(xml);
72
            XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM");
73
            ArrayList<Transform> transformList = signatureFactory(signatureFactory);
74
            loadCertificates(config, signatureFactory);
75
 
76
            for (int i = 0; i < document.getDocumentElement().getElementsByTagName(tipoAssinatura.getTipo()).getLength(); i++) {
77
                assinarNFe(tipoAssinatura, signatureFactory, transformList, privateKey, keyInfo, document, i);
78
            }
79
            return outputXML(document);
80
        } catch (SAXException | IOException | ParserConfigurationException | NoSuchAlgorithmException
81
                | InvalidAlgorithmParameterException | KeyStoreException | UnrecoverableEntryException
82
                | CertificadoException | MarshalException
83
                | XMLSignatureException e) {
84
            throw new NfeException("Erro ao Assinar Nfe" + e.getMessage(),e);
85
        }
86
    }
87
 
88
    private static void assinarNFe(AssinaturaEnum tipoAssinatura, XMLSignatureFactory fac, ArrayList<Transform> transformList,
89
                                   PrivateKey privateKey, KeyInfo ki, Document document, int indexNFe) throws NoSuchAlgorithmException,
90
            InvalidAlgorithmParameterException, MarshalException, XMLSignatureException {
91
 
92
        NodeList elements = document.getElementsByTagName(tipoAssinatura.getTag());
93
 
94
        org.w3c.dom.Element el = (org.w3c.dom.Element) elements.item(indexNFe);
95
        String id = el.getAttribute("Id");
96
        el.setIdAttribute("Id", true);
97
        Reference ref = fac.newReference("#" + id, fac.newDigestMethod(DigestMethod.SHA1, null), transformList, null,
98
                null);
99
 
100
        SignedInfo si = fac.newSignedInfo(
101
                fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null),
102
                fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(ref));
103
 
104
        XMLSignature signature = fac.newXMLSignature(si, ki);
105
 
106
        DOMSignContext dsc;
107
 
108
        if (tipoAssinatura.equals(AssinaturaEnum.INUTILIZACAO)) {
109
            dsc = new DOMSignContext(privateKey, document.getFirstChild());
110
        } else {
111
            dsc = new DOMSignContext(privateKey,
112
                    document.getDocumentElement().getElementsByTagName(tipoAssinatura.getTipo()).item(indexNFe));
113
        }
114
 
115
        dsc.setBaseURI("ok");
116
 
117
        signature.sign(dsc);
118
    }
119
 
120
    private static ArrayList<Transform> signatureFactory(XMLSignatureFactory signatureFactory)
121
            throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
122
 
123
        ArrayList<Transform> transformList = new ArrayList<Transform>();
124
        Transform envelopedTransform = signatureFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null);
125
        Transform c14NTransform = signatureFactory.newTransform("http://www.w3.org/TR/2001/REC-xml-c14n-20010315", (TransformParameterSpec) null);
126
 
127
        transformList.add(envelopedTransform);
128
        transformList.add(c14NTransform);
129
        return transformList;
130
    }
131
 
132
    private static Document documentFactory(String xml) throws SAXException, IOException, ParserConfigurationException {
133
 
134
        DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
135
        docBuilderFactory.setNamespaceAware(true);
136
        DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
137
        return docBuilder.parse(new InputSource(new StringReader(xml)));
138
    }
139
 
140
    private static void loadCertificates(ConfiguracoesNfe config, XMLSignatureFactory signatureFactory)
141
            throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException, CertificadoException {
142
 
143
        Certificado certificado = config.getCertificado();
144
        KeyStore keyStore = CertificadoService.getKeyStore(certificado);
145
 
146
        KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(certificado.getNome(),
147
                new KeyStore.PasswordProtection(ObjetoUtil.verifica(certificado.getSenha()).orElse("").toCharArray()));
148
        privateKey = pkEntry.getPrivateKey();
149
 
150
        KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();
151
        List<X509Certificate> x509Content = new ArrayList<X509Certificate>();
152
 
153
        x509Content.add(CertificadoService.getCertificate(certificado, keyStore));
154
        X509Data x509Data = keyInfoFactory.newX509Data(x509Content);
155
        keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data));
156
    }
157
 
158
    private static String outputXML(Document doc) throws NfeException {
159
 
160
        try (ByteArrayOutputStream os = new ByteArrayOutputStream()){
161
            TransformerFactory tf = TransformerFactory.newInstance();
162
            Transformer trans = tf.newTransformer();
163
            trans.transform(new DOMSource(doc), new StreamResult(os));
164
            String xml = os.toString();
165
            xml = xml.replaceAll("\\r\\n", "");
166
            xml = xml.replaceAll(" standalone=\"no\"", "");
167
            return xml;
168
        } catch (TransformerException | IOException e) {
169
            throw new NfeException("Erro ao Transformar Documento:" + e.getMessage(),e);
170
        }
171
    }
172
}