Login Registre-se
Erro ao assinar xml com certificado A3, utilizando java 32 bits  XML
Índice dos Fóruns » NF-e / NFS-e / CT-e / CF-e / Certificados Digitais
Autor Mensagem
Clermont

JavaC Membro

Membro desde: 24/07/2014 10:13:15
Mensagens: 1
Offline

Prezados, antes de criar esse tópico, li vários e não encontrei nenhum problema semelhante.
Trabalho em uma empresa com framework próprio que funciona apenas com java 32 bits.
Atualmente nosso sistema só utiliza o certificado A1. Estou tentando implementar uma classe que assine um xml com certificado A3.

Eu até que consegui uma classe através desta comunidade.
Segue o código:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

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.XMLSignature;
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 javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
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.NodeList;
import org.xml.sax.SAXException;

public class AssinadorA3 {
private static final String NFE = "NFe";

private PrivateKey privateKey;
private KeyInfo keyInfo;

/**
* Assinatura do XML de Envio de Lote da NF-e utilizando Certificado
* Digital A3.
* @param xml
* @param certificado
* @param senha
* @return
* @throws Exception
*/
public String assinaEnviNFe(String xml, String senha)
throws Exception {
Document document = documentFactory(xml);
XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM");
ArrayList<Transform> transformList = signatureFactory(signatureFactory);
loadCertificates(senha, signatureFactory);

for (int i = 0; i < document.getDocumentElement().getElementsByTagName(NFE).getLength(); i++) {
try {
assinarNFe(signatureFactory, transformList, privateKey, keyInfo, document, i);
} catch (Exception e) {
continue;
}
}

return outputXML(document);
}

private void assinarNFe(XMLSignatureFactory fac,
ArrayList<Transform> transformList, PrivateKey privateKey,
KeyInfo ki, Document document, int indexNFe) throws Exception {

NodeList elements = document.getElementsByTagName("infNFe");
org.w3c.dom.Element el = (org.w3c.dom.Element) elements.item(indexNFe);
String id = el.getAttribute("Id");

Reference ref = fac.newReference("#" + id,
fac.newDigestMethod(DigestMethod.SHA1, null), transformList,
null, null);

SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(
CanonicalizationMethod.INCLUSIVE,
(C14NMethodParameterSpec) null), fac
.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
Collections.singletonList(ref));

XMLSignature signature = fac.newXMLSignature(si, ki);

DOMSignContext dsc = new DOMSignContext(privateKey,
document.getDocumentElement().getElementsByTagName(NFE).item(indexNFe));
signature.sign(dsc);
}

private ArrayList<Transform> signatureFactory(
XMLSignatureFactory signatureFactory)
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
ArrayList<Transform> transformList = new ArrayList<Transform>();
TransformParameterSpec tps = null;
Transform envelopedTransform = signatureFactory.newTransform(
Transform.ENVELOPED, tps);
Transform c14NTransform = signatureFactory.newTransform(
"http://www.w3.org/TR/2001/REC-xml-c14n-20010315", tps);

transformList.add(envelopedTransform);
transformList.add(c14NTransform);
return transformList;
}

private Document documentFactory(String xml) throws SAXException,
IOException, ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
Document document = factory.newDocumentBuilder().parse(
new ByteArrayInputStream(xml.getBytes()));
return document;
}

private void loadCertificates(String senha,
XMLSignatureFactory signatureFactory) throws Exception {

/**
* Para Certificados A3 Cartao usar: SmartCard.cfg;
* Para Certificados A3 Token usar: Token.cfg;
*/
Provider provider = new sun.security.pkcs11.SunPKCS11("SmartCard.cfg");
Security.addProvider(provider);

KeyStore ks = KeyStore.getInstance("pkcs11", provider);
try {
ks.load(null, senha.toCharArray());
} catch (IOException e) {
throw new Exception("Senha do Certificado Digital incorreta ou Certificado inválido.");
}

KeyStore.PrivateKeyEntry pkEntry = null;
Enumeration<String> aliasesEnum = ks.aliases();
while (aliasesEnum.hasMoreElements()) {
String alias = (String) aliasesEnum.nextElement();
if (ks.isKeyEntry(alias)) {
pkEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias,
new KeyStore.PasswordProtection(senha.toCharArray()));
privateKey = pkEntry.getPrivateKey();
break;
}
}

X509Certificate cert = (X509Certificate) pkEntry.getCertificate();
info("SubjectDN: " + cert.getSubjectDN().toString());

KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();
List<X509Certificate> x509Content = new ArrayList<X509Certificate>();

x509Content.add(cert);
X509Data x509Data = keyInfoFactory.newX509Data(x509Content);
keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data));
}

private String outputXML(Document doc) throws TransformerException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
trans.transform(new DOMSource(doc), new StreamResult(os));
String xml = os.toString();
if ((xml != null) && (!"".equals(xml))) {
xml = xml.replaceAll("\\r\\n", "");
xml = xml.replaceAll(" standalone=\"no\"", "");
}
return xml;
}

private static String lerXML(String fileXML) throws IOException {
String linha = "";
StringBuilder xml = new StringBuilder();

BufferedReader in = new BufferedReader(new InputStreamReader(
new FileInputStream(fileXML)));
while ((linha = in.readLine()) != null) {
xml.append(linha);
}
in.close();

return xml.toString();
}

/**
* Log ERROR.
*
* @param error
*/
private static void error(String error) {
System.out.println("| ERROR: " + error);
}

/**
* Log INFO.
*
* @param info
*/
private static void info(String info) {
System.out.println("| INFO: " + info);
}

}

O problema que só consigo enxergar minha "dll" com o java 64bits. quando utilizo o java 32bits apresenta esse erro:
{"erro":"Library c:\\windows\\system32\\aetpkss1.dll does not exist"}
Lembrando que com o java 64 consigo assinar normalmente.

Agradeço desde já quem puder ajudar!
jeroqueiroz

Moderador
[Avatar]

Membro desde: 11/06/2011 09:45:18
Mensagens: 1346
Localização: Bahia
Offline

Já utilizei com ambos e funcionou perfeitamente.

Verifica todo seu ambiente. Driver do A3? Versão do Java?

Jeremias Santos
Seguir no Twitter @jeroqueiroz
Blog Jeroqueiroz


Projeto NF-e, CT-e, CC-e? Comece Por Aqui!


Membros do fórum,

Usem a tag [code] e [/code] quando postarem Códigos Java e ou exemplos de XMLs.
Evitem tópicos duplicados.
Tópico solucionado? Edite o primeiro post e coloque [RESOLVIDO] no final do título.
Evitem reviver tópicos antigos.

O tópico resolveu seu problema? Seja gentil, comente e ou agradeça quem contribuiu com a solução.

Obrigado!
[Email] [WWW] [Yahoo!] [MSN]
ibrsistemas

JavaC Membro

Membro desde: 10/01/2013 22:42:13
Mensagens: 73
Offline

faz o que o jeroqueiroz disse, também uso certificado A1 e A3, meu O.S é x64, porém eu instalo sempre o JRE ou o JDK x32... provavelmente isso é problema do Driver do Smart Card, se for da marca Perto Smart, acessa esse site e baixa o driver correto, assim como o driver do cartão inteligente: http://serasa.certificadodigital.com.br/ajuda/instalacao/outros-downloads-e-cadeias/
 
Índice dos Fóruns » NF-e / NFS-e / CT-e / CF-e / Certificados Digitais
Ir para:   
Powered by JForum 2.1.9 © JForum Team