Subversion Repositories Integrator Subversion

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 espaco 1
package nfe;
2
 
3
import java.io.ByteArrayInputStream;
4
import java.io.ByteArrayOutputStream;
5
import java.io.IOException;
6
import java.security.InvalidAlgorithmParameterException;
7
import java.security.KeyStore;
8
import java.security.KeyStoreException;
9
import java.security.NoSuchAlgorithmException;
10
import java.security.NoSuchProviderException;
11
import java.security.PrivateKey;
12
import java.security.UnrecoverableEntryException;
13
import java.security.cert.CertificateException;
14
import java.security.cert.X509Certificate;
15
import java.util.ArrayList;
16
import java.util.Collections;
17
import java.util.List;
18
 
19
import javax.xml.crypto.MarshalException;
20
import javax.xml.crypto.dsig.CanonicalizationMethod;
21
import javax.xml.crypto.dsig.DigestMethod;
22
import javax.xml.crypto.dsig.Reference;
23
import javax.xml.crypto.dsig.SignatureMethod;
24
import javax.xml.crypto.dsig.SignedInfo;
25
import javax.xml.crypto.dsig.Transform;
26
import javax.xml.crypto.dsig.XMLSignature;
27
import javax.xml.crypto.dsig.XMLSignatureException;
28
import javax.xml.crypto.dsig.XMLSignatureFactory;
29
import javax.xml.crypto.dsig.dom.DOMSignContext;
30
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
31
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
32
import javax.xml.crypto.dsig.keyinfo.X509Data;
33
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
34
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
35
import javax.xml.parsers.DocumentBuilderFactory;
36
import javax.xml.parsers.ParserConfigurationException;
37
import javax.xml.transform.Transformer;
38
import javax.xml.transform.TransformerException;
39
import javax.xml.transform.TransformerFactory;
40
import javax.xml.transform.dom.DOMSource;
41
import javax.xml.transform.stream.StreamResult;
42
 
43
import org.w3c.dom.Document;
44
import org.w3c.dom.NodeList;
45
import org.xml.sax.SAXException;
46
 
47
import br.com.samuelweb.certificado.Certificado;
48
import br.com.samuelweb.certificado.CertificadoService;
49
import br.com.samuelweb.certificado.exception.CertificadoException;
50
import nfe.dom.ConfiguracoesIniciaisNfe;
51
import nfe.exception.NfeException;
52
import nfe.util.XmlUtil;
53
 
54
/**
55
 * Classe Responsavel Por Assinar O Xml.
56
 *
57
 * @author Samuel Oliveira - samuk.exe@hotmail.com - www.samuelweb.com.br
58
 */
59
class Assinar {
60
 
61
    static final String INFINUT = "infInut";
62
    static final String EVENTO = "evento";
63
 
64
    private static ConfiguracoesIniciaisNfe configuracoesNfe;
65
 
66
    private static PrivateKey privateKey;
67
 
68
    private static KeyInfo keyInfo;
69
 
70
    Assinar assinarXMLsCertfificadoA1;
71
 
72
    /**
73
     * @param stringXml
74
     * @param tipo      ('NFe' para nfe normal , 'infInut' para inutilizacao, 'evento' para eventos)
75
     * @return String do Xml Assinado
76
     * @throws NfeException
77
     */
78
    static String assinaNfe(String stringXml, String tipo) throws NfeException {
79
 
80
        configuracoesNfe = ConfiguracoesIniciaisNfe.getInstance();
81
 
82
        stringXml = XmlUtil.removeAcentos(stringXml);
83
        stringXml = assinaDocNFe(stringXml, tipo);
84
 
85
        return stringXml;
86
    }
87
 
88
    /**
89
     * Assinatura do XML de Envio de Lote da NF-e utilizando Certificado
90
     * Digital.
91
     *
92
     * @param Conteudo do Xml
93
     * @param Nome     do Certificado Digital
94
     * @return String do XMl Assinado
95
     * @throws Exception
96
     */
97
    private static String assinaDocNFe(String xml, String tipo) throws NfeException {
98
 
99
        try {
100
            Document document = documentFactory(xml);
101
            XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM");
102
            ArrayList<Transform> transformList = signatureFactory(signatureFactory);
103
            loadCertificates(signatureFactory);
104
 
105
            for (int i = 0; i < document.getDocumentElement().getElementsByTagName(tipo).getLength(); i++) {
106
                assinarNFe(tipo, signatureFactory, transformList, privateKey, keyInfo, document, i);
107
            }
108
 
109
            return outputXML(document);
110
        } catch (SAXException | IOException | ParserConfigurationException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | KeyStoreException | UnrecoverableEntryException | NoSuchProviderException | CertificateException | CertificadoException | MarshalException | XMLSignatureException e) {
111
            throw new NfeException("Erro ao Assinar Nfe" + e.getMessage());
112
        }
113
    }
114
 
115
    private static void assinarNFe(String tipo, XMLSignatureFactory fac, ArrayList<Transform> transformList, PrivateKey privateKey, KeyInfo ki, Document document, int indexNFe) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, MarshalException, XMLSignatureException {
116
 
117
        NodeList elements;
118
        switch (tipo) {
119
            case EVENTO:
120
                elements = document.getElementsByTagName("infEvento");
121
                break;
122
            case INFINUT:
123
                elements = document.getElementsByTagName("infInut");
124
                break;
125
            default:
126
                elements = document.getElementsByTagName("infNFe");
127
        }
128
 
129
        org.w3c.dom.Element el = (org.w3c.dom.Element) elements.item(indexNFe);
130
        String id = el.getAttribute("Id");
131
 
132
        el.setIdAttribute("Id", true);
133
 
134
        Reference ref = fac.newReference("#" + id, fac.newDigestMethod(DigestMethod.SHA1, null), transformList, null, null);
135
 
136
        SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null), fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
137
                Collections.singletonList(ref));
138
 
139
        XMLSignature signature = fac.newXMLSignature(si, ki);
140
 
141
        DOMSignContext dsc;
142
 
143
        if (tipo.equals(INFINUT)) {
144
            dsc = new DOMSignContext(privateKey, document.getFirstChild());
145
        } else {
146
            dsc = new DOMSignContext(privateKey, document.getDocumentElement().getElementsByTagName(tipo).item(indexNFe));
147
        }
148
 
149
        dsc.setBaseURI("ok");
150
 
151
        signature.sign(dsc);
152
    }
153
 
154
    private static ArrayList<Transform> signatureFactory(XMLSignatureFactory signatureFactory) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
155
 
156
        ArrayList<Transform> transformList = new ArrayList<Transform>();
157
        TransformParameterSpec tps = null;
158
        Transform envelopedTransform = signatureFactory.newTransform(Transform.ENVELOPED, tps);
159
        Transform c14NTransform = signatureFactory.newTransform("http://www.w3.org/TR/2001/REC-xml-c14n-20010315", tps);
160
 
161
        transformList.add(envelopedTransform);
162
        transformList.add(c14NTransform);
163
        return transformList;
164
    }
165
 
166
    private static Document documentFactory(String xml) throws SAXException, IOException, ParserConfigurationException {
167
 
168
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
169
        factory.setNamespaceAware(true);
170
        return factory.newDocumentBuilder().parse(new ByteArrayInputStream(xml.getBytes()));
171
    }
172
 
173
    private static void loadCertificates(XMLSignatureFactory signatureFactory) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException, NoSuchProviderException, CertificateException, IOException, CertificadoException {
174
 
175
        Certificado certificado = configuracoesNfe.getCertificado();
176
        KeyStore keyStore = CertificadoService.getKeyStore(certificado);
177
 
178
        KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(certificado.getNome(), new KeyStore.PasswordProtection(certificado.getSenha().toCharArray()));
179
        privateKey = pkEntry.getPrivateKey();
180
 
181
        KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();
182
        List<X509Certificate> x509Content = new ArrayList<X509Certificate>();
183
 
184
        x509Content.add(CertificadoService.getCertificate(certificado, keyStore));
185
        X509Data x509Data = keyInfoFactory.newX509Data(x509Content);
186
        keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data));
187
    }
188
 
189
    private static String outputXML(Document doc) throws NfeException {
190
 
191
        try {
192
            ByteArrayOutputStream os = new ByteArrayOutputStream();
193
            TransformerFactory tf = TransformerFactory.newInstance();
194
            Transformer trans = tf.newTransformer();
195
            trans.transform(new DOMSource(doc), new StreamResult(os));
196
            String xml = os.toString();
197
            xml = xml.replaceAll("\\r\\n", "");
198
            xml = xml.replaceAll(" standalone=\"no\"", "");
199
            return xml;
200
        } catch (TransformerException e) {
201
            throw new NfeException("Erro ao Transformar Documento:" + e.getMessage());
202
        }
203
 
204
    }
205
 
206
}