Problemas com Assinatura Digital

10 respostas
cs.santos0

iai pessual, blz?

estou construindo um assinador para uma assinatura digital, mas estou com bastante problemas. Tenho um código que foi passado para mim q possivelmente assina um xml, porem não consigo fazer ele executar com sucesso.

Segue o assinador:

package br.cienci.nfe.servico.assinador;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.security.KeyStore;
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.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.NodeList;

public class Assinador
{
	private static final String C14N_TRANSFORM_METHOD = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";

	// tipo
	// '1' - NFE
	public static final String NFE = "1";
	// '2' - CANCELAMENTO
	public static final String CANCELAMENTO = "2";
	// '3' - INUTILIZACAO
	public static final String INUTILIZACAO = "3";

	public void assinar(String caminhoXml, String caminhoCertificado, String senha, String caminhoXmlNovo, String tipo) throws Exception
	{

		//
		String tag = "";
		if(tipo.equals(NFE))
			tag = "infNFe";
		else if (tipo.equals(CANCELAMENTO))
			tag = "infCanc";
		else if (tipo.equals(INUTILIZACAO))
			tag = "infInut";


		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(true);
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document docs = builder.parse(new File(caminhoXml));

		XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM", new org.jcp.xml.dsig.internal.dom.XMLDSigRI());

		// Create a Reference to the enveloped document (in this case,
		// you are signing the whole document, so a URI of "" signifies
		// that, and also specify the SHA1 digest algorithm and
		// the ENVELOPED Transform.
		ArrayList transformList = new ArrayList();
		TransformParameterSpec tps = null;
		Transform envelopedTransform = fac.newTransform(Transform.ENVELOPED,tps);
		Transform c14NTransform = fac.newTransform(C14N_TRANSFORM_METHOD, tps);
		transformList.add(envelopedTransform);
		transformList.add(c14NTransform);

		//Reference ref = fac.newReference("#" + id, fac.newDigestMethod(DigestMethod.SHA1, null), transformList, null, null);
		Reference ref = fac.newReference("", fac.newDigestMethod(DigestMethod.SHA1, null), transformList, null, null);
		// Create the SignedInfo.
		SignedInfo si = fac
				.newSignedInfo(fac.newCanonicalizationMethod(
						CanonicalizationMethod.INCLUSIVE,
						(C14NMethodParameterSpec) null), fac
						.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
						Collections.singletonList(ref));

		// Load the KeyStore and get the signing key and certificate.
		///Provider p = new sun.security.pkcs11.SunPKCS11("c:/taliam/sclara.cer");
		//Security.addProvider(p);
		//KeyStore ks = KeyStore.getInstance("PKCS11");
		//ks.load(null, new String("safeweb").toCharArray());

		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)) {
				//System.out.println(alias);
				break;
			}
		}

		// Original
		//KeyStore ks = KeyStore.getInstance("JKS");
		//ks.load(new FileInputStream("santaclara.jks"), "RAIMUNDO".toCharArray());

		//
		KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, new KeyStore.PasswordProtection(senha.toCharArray()));

		X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
		// Create the KeyInfo containing the X509Data.
		KeyInfoFactory kif = fac.getKeyInfoFactory();
		List x509Content = new ArrayList();
		// x509Content.add(cert.getSubjectX500Principal().getName());

		x509Content.add(cert);
		X509Data xd = kif.newX509Data(x509Content);
		KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));

		// Instantiate the document to be signed.
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		dbf.setNamespaceAware(true);
		Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(caminhoXml));

		// Create a DOMSignContext and specify the RSA PrivateKey and
		// location of the resulting XMLSignature's parent element.
		DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), doc.getDocumentElement());

		// Create the XMLSignature, but don't sign it yet.
		XMLSignature signature = fac.newXMLSignature(si, ki);

		// Marshal, generate, and sign the enveloped signature.
		signature.sign(dsc);

		// Output the resulting document.
		OutputStream os = new FileOutputStream(caminhoXmlNovo);
		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer trans = tf.newTransformer();
		trans.transform(new DOMSource(doc), new StreamResult(os));

		// Find Signature element.
		NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");

		if (nl.getLength() == 0) {
			throw new Exception("Cannot find Signature element");
		}
		/*
		// Create a DOMValidateContext and specify a KeySelector and document
		// context.
		DOMValidateContext valContext = new DOMValidateContext( new X509KeySelector(ks), nl.item(0));
		// Unmarshal the XMLSignature.
		XMLSignature signatures = fac.unmarshalXMLSignature(valContext);
		// Validate the XMLSignature.
		boolean coreValidity = signatures.validate(valContext);
		// Check core validation status.
		if (coreValidity == false) {
			System.err.println("Falha na Assinatura!");
		} else {
			System.out.println("Assinatura Correta!");
		}
	*/
	}

}

e o erro:

java.io.IOException: parseAlgParameters failed: PBE AlgorithmParameters not available
        at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.parseAlgParameters(PKCS12KeyStore.java:527)
        at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1267)
        at java.security.KeyStore.load(KeyStore.java:1185)
        at br.com.cienci.nfe.signature.Assinador.assinar(Assinador.java:103)
        at br.com.cienci.nfe.signature.Assinador.main(Assinador.java:192)
Caused by: java.security.NoSuchAlgorithmException: PBE AlgorithmParameters not available
        at sun.security.jca.GetInstance.getInstance(GetInstance.java:142)
        at java.security.Security.getImpl(Security.java:659)
        at java.security.AlgorithmParameters.getInstance(AlgorithmParameters.java:113)
        at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.parseAlgParameters(PKCS12KeyStore.java:523)
        ... 4 more

alguem ai sabe oq preciso fazer para resolver esse problema?
vlw

10 Respostas

T

O mais provável é que o tal código funcione com Java 6.0 mas não com Java 5.0.

cs.santos0

o problema é que eu ja estou tentando rodar ele com o java 6…

e em outro computador esse codigo funciona…(pelo menos é oq me disseram…rsrs)

se vc puder me ajudar lhe agradeço mto…
vlw

O

Acho que o problema é o arquivo de “keystore” (caminhoCertificado). Ele está no formato PKCS12? Faça um teste usando o keytool.

cs.santos0

depois de apanhar mto desse código e de horas tentando achar algo sobre isso, acabei vendo algo sobre esse keytool…porem ainda não me aprofundei nele…

por quais razões vc acha q é isso?..como utilizar esse keytool?..como fazer esse teste?..ja q estou usando PKCS12…oq devo fazer?..

vcs podem me dar uma ajuda com isso?..creio q esteja próximo de resolver esse problema, porem ja pesquisei e não achei nda q possa resolver ainda…

como disse, qualquer ajuda será bem vinda.
Vlw

O
java.io.IOException: parseAlgParameters failed: PBE AlgorithmParameters not available
        at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.parseAlgParameters(PKCS12KeyStore.java:527)
        at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1267)
        at java.security.KeyStore.load(KeyStore.java:1185)
        at br.com.cienci.nfe.signature.Assinador.assinar(Assinador.java:103)
        at br.com.cienci.nfe.signature.Assinador.main(Assinador.java:192)
Caused by: java.security.NoSuchAlgorithmException: PBE AlgorithmParameters not available
        at sun.security.jca.GetInstance.getInstance(GetInstance.java:142)
        at java.security.Security.getImpl(Security.java:659)
        at java.security.AlgorithmParameters.getInstance(AlgorithmParameters.java:113)
        at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.parseAlgParameters(PKCS12KeyStore.java:523)
        ... 4 more

Por causa do erro que aparece na stacktrace: PBE é o mecanismo de criptografar um arquivo usando uma senha. Aparentemente, não está sendo possível decriptografar usando storetype PKCS12. Por isso a minha desconfiança que o arquivo que você está passando como parâmetro não esteja no formato PKCS#12.

keytool -v -list -keystore <arquivo> -storetype PKCS12

http://java.sun.com/javase/6/docs/technotes/tools/windows/keytool.html

cs.santos0

estou passando esse arquivo:

certificado_rns.p12

não é esse?

qual o procedimento?..eu devo gerar o arquivo com o keytool e depois importar ele para a aplicação igual eu estou fazendo, ou tem algo a mais?

cs.santos0

fui fazer um teste pelo q vc me disse, abri o prompt e fui fazendo....

C:\Documents and Settings\Intel>cd C:\Documents and Settings\Intel\Desktop\Nova
pasta

C:\Documents and Settings\Intel\Desktop\Nova pasta>keytool -v -list -keystore ce
rtificado_rns.p12  -storetype PKCS12
Enter keystore password:
keytool error: java.io.IOException: parseAlgParameters failed: PBE AlgorithmPara
meters not available
java.io.IOException: parseAlgParameters failed: PBE AlgorithmParameters not avai
lable
        at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.parseAlgParameters(PKC
S12KeyStore.java:527)
        at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeySt
ore.java:1267)
        at java.security.KeyStore.load(KeyStore.java:1185)
        at sun.security.tools.KeyTool.doCommands(KeyTool.java:711)
        at sun.security.tools.KeyTool.run(KeyTool.java:171)
        at sun.security.tools.KeyTool.main(KeyTool.java:165)
Caused by: java.security.NoSuchAlgorithmException: PBE AlgorithmParameters not a
vailable
        at sun.security.jca.GetInstance.getInstance(GetInstance.java:142)
        at java.security.Security.getImpl(Security.java:659)
        at java.security.AlgorithmParameters.getInstance(AlgorithmParameters.jav
a:113)
        at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.parseAlgParameters(PKC
S12KeyStore.java:523)
        ... 5 more

C:\Documents and Settings\Intel\Desktop\Nova pasta>

e na hora de gerar deu o msm erro q estava dando....será q é problema com o meu java instalado?...vc ja fez isso ai e deu certo?...tem algum jar adicional ou plugin para ler isso?

vlw

O

Duas possibilidades:
[list]Ou o arquivo não está no formato PKCS#12[/list]
Como foi gerado este arquivo? Se você não sabe o formato, sugiro você gerar novas chaves.

[list]Ou a sua instalação da JDK está com problema[/list]
Pegue este arquivo e faça o mesmo teste em outra máquina. Se funcionar é a instalação da JDK. Re-instale.

cs.santos0

era problema no java msm…reinstalei e funcionou perfeitamente…

vlw a ajuda

cs.santos0

Como esse não é um assunto nada trivial...vou postar aki o meu assinador usando PKCS12...para quem precisar ai um dia...

package br.com.cienci.nfe.signature;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.cert.CertificateException;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
import javax.xml.crypto.*;
import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dom.*;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.*;
import javax.xml.crypto.dsig.spec.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.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.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;

/**
 *
 * @author Ciro S. Santos
 */
public class DigitalSignature {

    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 boolean sign(String xml, String certificado, String senha, String novoXml) {

        try {
            String providerName = System.getProperty(PROVIDER_NAME, PROVIDER_CLASS_NAME);  

            XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM",
                    (Provider) Class.forName(providerName).newInstance());

            ArrayList<Transform> transformList = new ArrayList<Transform>();
            TransformParameterSpec tps = null;
            Transform envelopedTransform = fac.newTransform(Transform.ENVELOPED, tps);
            Transform c14NTransform = fac.newTransform(C14N_TRANSFORM_METHOD, tps);
            transformList.add(envelopedTransform);
            transformList.add(c14NTransform);

            Reference ref = fac.newReference("",
                    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));           

            File file3 = new File("src\\securityResources");
            String path3 = file3.getAbsolutePath() + "\\" + certificado;
            KeyStore ks = KeyStore.getInstance("PKCS12");
            FileInputStream fis = new FileInputStream(path3);
            ks.load(fis, 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()));

            X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
            KeyInfoFactory kif = fac.getKeyInfoFactory();
            List x509Content = new ArrayList();
            x509Content.add(cert);
            X509Data xd = kif.newX509Data(x509Content);
            KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));            

            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            File file = new File("src\\generatedXml");
            String path = file.getAbsolutePath() + "\\" + xml;
            Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(path));

            DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), doc.getDocumentElement());
            XMLSignature signature = fac.newXMLSignature(si, ki);
            signature.sign(dsc);

            File file1 = new File("src\\signedXml");
            String path1 = file1.getAbsolutePath() + "\\" + novoXml;
            OutputStream os = new FileOutputStream(path1);

            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer trans = tf.newTransformer();
            trans.transform(new DOMSource(doc), new StreamResult(os));

        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
            return false;
        } catch (InstantiationException ex) {
            ex.printStackTrace();
            return false;
        } catch (IllegalAccessException ex) {
            ex.printStackTrace();
            return false;
        } catch (TransformerConfigurationException ex) {
            ex.printStackTrace();
            return false;
        } catch (TransformerException ex) {
            ex.printStackTrace();
            return false;
        } catch (MarshalException ex) {
            ex.printStackTrace();
            return false;
        } catch (XMLSignatureException ex) {
            ex.printStackTrace();
            return false;
        } catch (UnrecoverableEntryException ex) {
            ex.printStackTrace();
            return false;
        } catch (CertificateException ex) {
            ex.printStackTrace();
            return false;
        } catch (KeyStoreException ex) {
            ex.printStackTrace();
            return false;
        } catch (InvalidAlgorithmParameterException ex) {
            ex.printStackTrace();
            return false;
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
            return false;
        } catch (ParserConfigurationException ex) {
            ex.printStackTrace();
            return false;
        } catch (SAXException ex) {
            ex.printStackTrace();
            return false;
        } catch (IOException ex) {            
            ex.printStackTrace();
            return false;
        }
        return true;
    }    
}

flw, um abraço!

Criado 13 de outubro de 2008
Ultima resposta 14 de out. de 2008
Respostas 10
Participantes 3