Problemas com Assinatura Digital

10 respostas
C

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.

C

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.

C

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

C

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?

C

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.

C

era problema no java msm…reinstalei e funcionou perfeitamente…

vlw a ajuda

C

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