Skip to content

Commit

Permalink
Merge pull request #8 from yurikilian/master
Browse files Browse the repository at this point in the history
PR das Issues #7 e #9
  • Loading branch information
pablopdomingos authored Nov 7, 2017
2 parents afda619 + 9e9169c commit 16715e9
Show file tree
Hide file tree
Showing 25 changed files with 1,597 additions and 134 deletions.
Original file line number Diff line number Diff line change
@@ -1,37 +1,46 @@
package com.pablodomingos.assinatura;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.crypto.dsig.*;
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.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Collections;
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.OutputKeys;
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.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class AssinaturaDigital {
private static String INFRPS = "InfRps";
private static String[] ELEMENTOS_ASSINAVEIS = new String[]{"LoteRps", "InfPedidoCancelamento"};
private static String[] ELEMENTOS_ASSINAVEIS = new String[] {"LoteRps", "InfPedidoCancelamento"};
private CertificadoConfig config;

public AssinaturaDigital(CertificadoConfig config) {
Expand All @@ -57,50 +66,62 @@ public String assinarXML(String xml) throws Exception {
X509Data x509Data = keyInfoFactory.newX509Data(x509Content);
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data));

Document document = documentFactory(xml);
Document document = documentFactory(removeAcentos(xml));

//Assinando todos RPS
// Assinando todos RPS
NodeList elements = document.getElementsByTagName(INFRPS);
for (int i = 0; i < elements.getLength(); i++) {
Element element = (Element) elements.item(i);

String id = element.getAttribute("Id");
element.setIdAttribute("Id", true);

Reference reference = signatureFactory.newReference("#" + id, signatureFactory.newDigestMethod(DigestMethod.SHA1, null), transformList, null, null);
SignedInfo signedInfo = signatureFactory.newSignedInfo( signatureFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
(C14NMethodParameterSpec) null), signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
Reference reference = signatureFactory.newReference("#" + id,
signatureFactory.newDigestMethod(DigestMethod.SHA1, null), transformList, null, null);
SignedInfo signedInfo = signatureFactory.newSignedInfo(
signatureFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
(C14NMethodParameterSpec) null),
signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
Collections.singletonList(reference));

XMLSignature signature = signatureFactory.newXMLSignature(signedInfo, keyInfo);
signature.sign(new DOMSignContext(pkEntry.getPrivateKey(), element.getParentNode()));
}

Document documentAssinado = documentFactory(converteDocParaXml(document));
//Assinando o Lote de RPS

// Assinando o Lote de RPS
for (final String elementoAssinavel : AssinaturaDigital.ELEMENTOS_ASSINAVEIS) {
NodeList elementsAssinado = documentAssinado.getDocumentElement().getElementsByTagName(elementoAssinavel);
NodeList elementsAssinado =
documentAssinado.getDocumentElement().getElementsByTagName(elementoAssinavel);
for (int i = 0; i < elementsAssinado.getLength(); i++) {
Element element = (Element) elementsAssinado.item(i);

String id = element.getAttribute("Id");
element.setIdAttribute("Id", true);

Reference reference = signatureFactory.newReference("#" + id, signatureFactory.newDigestMethod(DigestMethod.SHA1, null), transformList, null, null);
SignedInfo signedInfo = signatureFactory.newSignedInfo( signatureFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
(C14NMethodParameterSpec) null), signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
Reference reference = signatureFactory.newReference("#" + id,
signatureFactory.newDigestMethod(DigestMethod.SHA1, null), transformList, null, null);
SignedInfo signedInfo = signatureFactory.newSignedInfo(
signatureFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
(C14NMethodParameterSpec) null),
signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
Collections.singletonList(reference));

XMLSignature signature = signatureFactory.newXMLSignature(signedInfo, keyInfo);
signature.sign(new DOMSignContext(pkEntry.getPrivateKey(), element.getParentNode()));
}
}



return converteDocParaXml(documentAssinado);
}

public static String removeAcentos(String str) {
CharSequence cs = new StringBuilder(str == null ? "" : str);
return Normalizer.normalize(cs, Normalizer.Form.NFKD)
.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
}

private Document documentFactory(String xml)
throws SAXException, IOException, ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Expand All @@ -122,12 +143,12 @@ private ArrayList<Transform> signatureFactory(XMLSignatureFactory signatureFacto
transformList.add(c14NTransform);
return transformList;
}

private String converteDocParaXml(Document doc) throws TransformerException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
Transformer trans = TransformerFactory.newInstance().newTransformer();
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
trans.transform(new DOMSource(doc), new StreamResult(os));
return os.toString();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@
import java.security.Provider;
import java.security.Security;
import java.security.cert.CertificateException;

import java.util.Arrays;
import com.pablodomingos.classes.rps.enums.NFSeAmbiente;


public class CertificadoConfig {

private TipoCertificado tipoCertificado;
Expand All @@ -23,7 +22,8 @@ public class CertificadoConfig {
private String caminhoParaCadeiaCertificado;
private KeyStore keyStoreCertificado;
private NFSeAmbiente ambiente;

private InputStream inputStream;

public CertificadoConfig(CertificadoConfigBuilder builder) {
super();
this.senhaCertificado = builder.senhaCertificado;
Expand All @@ -32,36 +32,24 @@ public CertificadoConfig(CertificadoConfigBuilder builder) {
this.caminhoParaCertificado = builder.caminhoParaCertificado;
this.caminhoParaCadeiaCertificado = builder.caminhoParaCadeiaCertificado;
this.ambiente = builder.ambiente;

}

public KeyStore getCertificadoKeyStore() throws KeyStoreException {
try {
if (keyStoreCertificado == null) {
InputStream certificadoStream = null;

if (tipoCertificado.equals(TipoCertificado.A3_TOKEN)) {

InputStream inputFile = getClass().getClassLoader().getResourceAsStream("Token.cfg");
Provider provider = new sun.security.pkcs11.SunPKCS11(inputFile);
Security.addProvider(provider);
this.keyStoreCertificado = KeyStore.getInstance("pkcs11", provider);

} else if (tipoCertificado.equals(TipoCertificado.A3_CARD)) {

InputStream inputFile = getClass().getClassLoader().getResourceAsStream("SmartCard.cfg");
Provider provider = new sun.security.pkcs11.SunPKCS11(inputFile);
Security.addProvider(provider);
this.keyStoreCertificado = KeyStore.getInstance("pkcs11", provider);
if (Arrays.asList(TipoCertificado.A3_TOKEN, TipoCertificado.A3_CARD)
.contains(tipoCertificado)) {
this.inputStream = getClass().getClassLoader()
.getResourceAsStream(tipoCertificado.getArquivoConfiguracao());
this.carregarModuloPKCS11();

} else if (tipoCertificado.equals(TipoCertificado.A1)) {

certificadoStream = new FileInputStream(caminhoParaCertificado);
this.inputStream = new FileInputStream(caminhoParaCertificado);
this.keyStoreCertificado = KeyStore.getInstance("pkcs12");

}

this.keyStoreCertificado.load(certificadoStream, this.getSenhaCertificado().toCharArray());
this.keyStoreCertificado.load(inputStream, this.getSenhaCertificado().toCharArray());

}

Expand All @@ -72,43 +60,58 @@ public KeyStore getCertificadoKeyStore() throws KeyStoreException {
}
}

public void carregarCertificados(){
@SuppressWarnings("restriction")
private void carregarModuloPKCS11() throws KeyStoreException {
try {
KeyStore keystoreInstance = KeyStore.getInstance("pkcs11");
if (keystoreInstance != null && keystoreInstance.getProvider() != null) {
this.keyStoreCertificado = keystoreInstance;
}
} catch (KeyStoreException ke) {
Provider provider = new sun.security.pkcs11.SunPKCS11(this.inputStream);
Security.addProvider(provider);
this.keyStoreCertificado = KeyStore.getInstance("pkcs11", provider);
}
}

@SuppressWarnings("restriction")
public void carregarCertificados() {
try {
this.getCertificadoKeyStore();
} catch (KeyStoreException e) {
e.printStackTrace();
}
System.clearProperty("javax.net.ssl.keyStore");
System.clearProperty("javax.net.ssl.keyStorePassword");
System.clearProperty("javax.net.ssl.trustStore");
if(this.getTipoCertificado().equals(TipoCertificado.A1)){
System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());

System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
System.setProperty("javax.net.ssl.keyStore", this.getCaminhoParaCertificado());
System.setProperty("javax.net.ssl.keyStorePassword", this.getSenhaCertificado());
}else if(this.getTipoCertificado().equals(TipoCertificado.A3_CARD)){
System.setProperty("javax.net.ssl.keyStore", "NONE");
System.setProperty("javax.net.ssl.keyStoreType", "PKCS11");
System.setProperty("javax.net.ssl.keyStoreProvider", "SunPKCS11-SmartCard");
}else if(this.getTipoCertificado().equals(TipoCertificado.A3_TOKEN)){
System.setProperty("javax.net.ssl.keyStore", "NONE");
System.setProperty("javax.net.ssl.keyStoreType", "PKCS11");
System.setProperty("javax.net.ssl.keyStoreProvider", "SunPKCS11-eToken");
System.clearProperty("javax.net.ssl.keyStore");
System.clearProperty("javax.net.ssl.keyStorePassword");
System.clearProperty("javax.net.ssl.trustStore");

if (this.getTipoCertificado().equals(TipoCertificado.A1)) {

System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());

System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
System.setProperty("javax.net.ssl.keyStore", this.getCaminhoParaCertificado());
System.setProperty("javax.net.ssl.keyStorePassword", this.getSenhaCertificado());

} else if (this.getTipoCertificado().equals(TipoCertificado.A3_CARD)) {

System.setProperty("javax.net.ssl.keyStore", "NONE");
System.setProperty("javax.net.ssl.keyStoreType", "PKCS11");
System.setProperty("javax.net.ssl.keyStoreProvider", "SunPKCS11-SmartCard");

} else if (this.getTipoCertificado().equals(TipoCertificado.A3_TOKEN)) {

System.setProperty("javax.net.ssl.keyStore", "NONE");
System.setProperty("javax.net.ssl.keyStoreType", "PKCS11");
System.setProperty("javax.net.ssl.keyStoreProvider", "SunPKCS11-eToken");

}
System.setProperty("javax.net.ssl.trustStoreType", "JKS");

System.setProperty("javax.net.ssl.trustStoreType", "JKS");
System.setProperty("javax.net.ssl.trustStore", this.getCaminhoParaCadeiaCertificado());
}

public TipoCertificado getTipoCertificado() {
return tipoCertificado;
}
Expand All @@ -124,7 +127,7 @@ public String getAliasCertificado() {
public String getCaminhoParaCertificado() {
return caminhoParaCertificado;
}

public String getCaminhoParaCadeiaCertificado() {
return caminhoParaCadeiaCertificado;
}
Expand All @@ -142,9 +145,11 @@ public static class CertificadoConfigBuilder {
private TipoCertificado tipoCertificado;
private String senhaCertificado;
private String aliasCertificado = null;
private String caminhoParaCertificado = Paths.get("/certificado/certificado.pfx").toAbsolutePath().toString();
private String caminhoParaCadeiaCertificado = Paths.get("/certificado/nfse-bh.cacerts").toAbsolutePath().toString();
private NFSeAmbiente ambiente = NFSeAmbiente.HOMOLOGACAO;
private String caminhoParaCertificado =
Paths.get("/certificado/certificado.pfx").toAbsolutePath().toString();
private String caminhoParaCadeiaCertificado =
Paths.get("/certificado/nfse-bh.cacerts").toAbsolutePath().toString();
private NFSeAmbiente ambiente = NFSeAmbiente.HOMOLOGACAO;

public CertificadoConfigBuilder(TipoCertificado tipoCertificado, String senhaCertificado) {

Expand All @@ -165,19 +170,29 @@ public CertificadoConfigBuilder comCaminhoCertificadoCliente(String caminhoParaC
return this;
}

public CertificadoConfigBuilder comCaminhoCadeiaDeCertificados(String caminhoParaCadeiaCertificado) {
public CertificadoConfigBuilder comCaminhoCadeiaDeCertificados(
String caminhoParaCadeiaCertificado) {
this.caminhoParaCadeiaCertificado = caminhoParaCadeiaCertificado;
return this;
}

public CertificadoConfigBuilder comAmbiente(NFSeAmbiente ambiente) {
this.ambiente = ambiente;
return this;
}

public CertificadoConfig build() {
return new CertificadoConfig(this);
}

}


public void fechar() {
try {
this.inputStream.close();
} catch (Exception e) {
/* ignore */
}
}
}
Loading

0 comments on commit 16715e9

Please sign in to comment.