Como acessar um WebService via HTTPS estando o certificado/chave privada num Token USB (eCNPJ)?

28 respostas
E

Pessoal,

Num teste que fiz consigo acessar beleza quando o keystore está em arquivo do tipo JKS, mas quando as informações de chave privada estão num token ? No caso é um token do tipo eCNPJ sendo que a chave privada não pode ser extraida. Como configurar para o servidor “enxergar” minhas credencias.

Agradeço qualquer ajuda.

abracos.

28 Respostas

O

Opções:

  1. Criar/obter um provider JCE para acessar o token.
  2. Implementar/obter um protocolo que comunica com este tipo de dispositivo, tipo PKCS#11.
  3. Se este dispositivo tiver biblioteca de acesso em código nativo, fazer chamadas via JNI.

O mais fácil é se o fornecedor do token fornecer um provider JCE para acessa-lo.

Você não precisa extrair a chave do token. O token tem que ter a capacidade de criptografar/descriptografar um dado que é passado para ele.
Existem métodos em classes JCE que fazem esta parte. Procure por wrap/unwrap da classe Cipher.

Não entendi o que você chamou de servidor na frase acima.

T

Experimente para ver se os providers da Sun (SunPKCS11, disponível a partir do Java 5.0, e SunMSCAPI, disponível a partir do java 6.0) conseguem efetuar as operações com seu token USB.
Eles dependem de o driver criptográfico estar corretamente instalado na máquina.
A configuração desses providers é feita através do arquivo java.security dentro do diretório jre/lib/security.
Uma vez consegui usar o SunPKCS11 - mas não sei se as operações criptográficas que você precisa são suportadas pelo SunPKCS11.

V

Deixa eu adivinhar, você está tentando implementar um programa para conectar em webservices de secretarias de fazenda para emitir notas fiscais eletrônicas?

E

Sim.

E

thingol:
Experimente para ver se os providers da Sun (SunPKCS11, disponível a partir do Java 5.0, e SunMSCAPI, disponível a partir do java 6.0) conseguem efetuar as operações com seu token USB.
Eles dependem de o driver criptográfico estar corretamente instalado na máquina.
A configuração desses providers é feita através do arquivo java.security dentro do diretório jre/lib/security.
Uma vez consegui usar o SunPKCS11 - mas não sei se as operações criptográficas que você precisa são suportadas pelo SunPKCS11.

Com o codigo abaixo consigo “enxergar” várias informações do meu token:

public class Teste {

public static void main( String args[] ) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException {

Provider p = new sun.security.pkcs11.SunPKCS11(“c:/temp/security/security.cfg);
Security.addProvider(p);
    
    KeyStore ks = KeyStore.getInstance("PKCS11");
    ks.load(null, new String("xxxxxx").toCharArray());
    
    PrivateKey privateKey = (PrivateKey) ks.getKey("ALIAS", new String("xxxxxx").toCharArray());
    Certificate certificate = (Certificate) ks.getCertificate("ALIAS");
    
    System.out.println(privateKey.toString());
}

}

Conteúdo do arquivo de configuração:

name=Safenetikey2032
library=c:\windows\system32\dkck201.dll

attributes = compatibility

*** Essa DLL encontrei citada num exemplo da net e verifiquei que tinha no meu windows. Usei e deu “certo”, outra citada para o modelo do token (SafeNet ikey 2032) seria dkck2032.dll mas essa nao tenho e nao encontrei no site do fabricante para download ****

Isso me retorna para a chave privada:

SunPKCS11-Safenetikey2032 RSA private key, 1024 bits (id 2293760, token object, sensitive, unextractable)

O que gostaria de ajuda para entender seria:

  1. Se é possível e como utilizar esse token USB para assinar um arquivo XML ?

  2. Como configurar no java/netbeans o acesso ao web service via HTTPS usando o certificado contido nesse token ? O WS a ser acessado requer autenticação do cliente, isso já está como uma extensão do certificado do token.

Segue um código de teste de assinatura e a exceção levantada:

public class XMLSigner {

private static final String CANONICALIZE_METHOD = <a href="http://www.w3.org/TR/2001/REC-xml-c14n-20010315">http://www.w3.org/TR/2001/REC-xml-c14n-20010315</a>”;

private static final String C14N_TRANSFORM_METHOD = <a href="http://www.w3.org/TR/2001/REC-xml-c14n-20010315">http://www.w3.org/TR/2001/REC-xml-c14n-20010315</a>”;

private static final String PROVIDER_CLASS_NAME = org.jcp.xml.dsig.internal.dom.XMLDSigRI;

private static final String PROVIDER_NAME = jsr105Provider;
public static OutputStream sign( File inXML, File ouXML ) {
    OutputStream os = null;
    try {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(false);
        // Obtem DOM do documento
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse(inXML);

        // Obtem elemento do documento a ser assinado, será criado uma REFERENCE para o mesmo
        NodeList elements = doc.getElementsByTagName("infNFe");
        Element el = (Element) elements.item(0);
        String id = el.getAttribute("Id");

        // Cria uma factory representando o elemento XML Signature, a partir dela serão criados as parte desse elemento
        String providerName = System.getProperty(PROVIDER_NAME, PROVIDER_CLASS_NAME);
        XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM", (Provider) Class.forName(providerName).newInstance());

        // Cria método de Digest e canonicalização
        DigestMethod digestMethod = signatureFactory.newDigestMethod(DigestMethod.SHA1, null);
        C14NMethodParameterSpec c14NMethodParameterSpec = null;
        CanonicalizationMethod canonicalMethod = signatureFactory.newCanonicalizationMethod(CANONICALIZE_METHOD, c14NMethodParameterSpec);
        
        // Cria classe representando o Hash e algoritmo de criptografia a ser aplicado
        SignatureMethod sm = signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null);

        // Cria a lista de tranformações a serem aplicadas as referencias a serem assinadas
        ArrayList transformList = new ArrayList();
        TransformParameterSpec tps = null;
        Transform envelopedTransform = signatureFactory.newTransform(Transform.ENVELOPED, tps);
        Transform c14NTransform = signatureFactory.newTransform(C14N_TRANSFORM_METHOD, tps);
        transformList.add(envelopedTransform);
        transformList.add(c14NTransform);

        // Cria referencia, parte do XML a ser assinado 
        Reference ref = signatureFactory.newReference("#" + id, digestMethod, transformList, null, null);
        ArrayList refList = new ArrayList();
        refList.add(ref);

        SignedInfo signedInfo = signatureFactory.newSignedInfo(canonicalMethod, sm, refList);

        Provider p = new sun.security.pkcs11.SunPKCS11("c:/temp/security/security.cfg");
        Security.addProvider(p);

        KeyStore ks = KeyStore.getInstance("PKCS11");
        ks.load(null, new String("inteqq").toCharArray());

        PrivateKey privateKey = (PrivateKey) ks.getKey("4e1ece83-89de-4ae8-86f1-9564d7fdf945", new String("inteqq").toCharArray());
        Certificate certificate = (Certificate) ks.getCertificate("4e1ece83-89de-4ae8-86f1-9564d7fdf945");

        DOMSignContext dsc = new DOMSignContext(privateKey, doc.getDocumentElement());

        KeyInfoFactory kif = signatureFactory.getKeyInfoFactory();
        X509Data x509Data = kif.newX509Data(Collections.singletonList(certificate));

        KeyInfo keyInfo = kif.newKeyInfo(Collections.singletonList(x509Data));

        XMLSignature signature = signatureFactory.newXMLSignature(signedInfo, keyInfo);
        signature. sign(dsc);

        os = new FileOutputStream(ouXML);

        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer trans = tf.newTransformer();
        trans.transform(new DOMSource(doc), new StreamResult(os));
    } catch (TransformerException ex) {
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
    } catch (MarshalException ex) {
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
    } catch (XMLSignatureException ex) {
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
    } catch (UnrecoverableKeyException ex) {
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
    } catch (CertificateException ex) {
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
    } catch (KeyStoreException ex) {
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InvalidAlgorithmParameterException ex) {
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
    } catch (ClassNotFoundException ex) {
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
    } catch (SAXException ex) {
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
    } catch (ParserConfigurationException ex) {
        Logger.getLogger(XMLSigner.class.getName()).log(Level.SEVERE, null, ex);
    }
    return os;
}

public static void main( String[] args ) {
    OutputStream out = XMLSigner.sign(new File("c:/temp/entrada/teste-nfe.xml"), new File("c:/temp/entrada/teste-nfe-out.xml"));
}

}

Exceção:

01/02/2008 10:07:01 inteq.nfe.servicos.util.XMLSigner sign

SEVERE: null

javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.dsig.TransformException: java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_MECHANISM_INVALID

at org.jcp.xml.dsig.internal.dom.DOMSignedInfo.canonicalize(DOMSignedInfo.java:175)

at org.jcp.xml.dsig.internal.dom.DOMRSASignatureMethod.sign(DOMRSASignatureMethod.java:140)

at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:367)

at inteq.nfe.servicos.util.XMLSigner.sign(XMLSigner.java:128)

at inteq.nfe.servicos.util.XMLSigner.main(XMLSigner.java:169)

Caused by: javax.xml.crypto.dsig.TransformException: java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_MECHANISM_INVALID

at org.jcp.xml.dsig.internal.dom.ApacheCanonicalizer.transform(ApacheCanonicalizer.java:231)

at org.jcp.xml.dsig.internal.dom.DOMTransform.transform(DOMTransform.java:129)

at org.jcp.xml.dsig.internal.dom.DOMCanonicalizationMethod.canonicalize(DOMCanonicalizationMethod.java:67)

at org.jcp.xml.dsig.internal.dom.DOMSignedInfo.canonicalize(DOMSignedInfo.java:172)

 4 more

Caused by: java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_MECHANISM_INVALID

at sun.security.pkcs11.P11Signature.engineUpdate(P11Signature.java:371)

at java.security.Signature$Delegate.engineUpdate(Signature.java:1118)

at java.security.Signature.update(Signature.java:684)

at org.jcp.xml.dsig.internal.SignerOutputStream.write(SignerOutputStream.java:68)

at com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream.flushBuffer(UnsyncBufferedOutputStream.java:62)

at com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream.flush(UnsyncBufferedOutputStream.java:78)

at com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream.close(UnsyncBufferedOutputStream.java:84)

at com.sun.org.apache.xml.internal.security.c14n.implementations.CanonicalizerBase.engineCanonicalizeSubTree(CanonicalizerBase.java:192)

at com.sun.org.apache.xml.internal.security.c14n.implementations.CanonicalizerBase.engineCanonicalize(CanonicalizerBase.java:138)

at com.sun.org.apache.xml.internal.security.transforms.implementations.TransformC14N.enginePerformTransform(TransformC14N.java:65)

at com.sun.org.apache.xml.internal.security.transforms.Transform.performTransform(Transform.java:350)

at org.jcp.xml.dsig.internal.dom.ApacheCanonicalizer.transform(ApacheCanonicalizer.java:218)

 7 more

Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_MECHANISM_INVALID

at sun.security.pkcs11.wrapper.PKCS11.C_SignUpdate(Native Method)

at sun.security.pkcs11.P11Signature.engineUpdate(P11Signature.java:365)

 18 more

javax.xml.crypto.dsig.TransformException: java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_MECHANISM_INVALID

at org.jcp.xml.dsig.internal.dom.ApacheCanonicalizer.transform(ApacheCanonicalizer.java:231)

at org.jcp.xml.dsig.internal.dom.DOMTransform.transform(DOMTransform.java:129)

at org.jcp.xml.dsig.internal.dom.DOMCanonicalizationMethod.canonicalize(DOMCanonicalizationMethod.java:67)

at org.jcp.xml.dsig.internal.dom.DOMSignedInfo.canonicalize(DOMSignedInfo.java:172)

at org.jcp.xml.dsig.internal.dom.DOMRSASignatureMethod.sign(DOMRSASignatureMethod.java:140)

at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:367)

at inteq.nfe.servicos.util.XMLSigner.sign(XMLSigner.java:128)

at inteq.nfe.servicos.util.XMLSigner.main(XMLSigner.java:169)

Caused by: java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_MECHANISM_INVALID

at sun.security.pkcs11.P11Signature.engineUpdate(P11Signature.java:371)

at java.security.Signature$Delegate.engineUpdate(Signature.java:1118)

at java.security.Signature.update(Signature.java:684)

at org.jcp.xml.dsig.internal.SignerOutputStream.write(SignerOutputStream.java:68)

at com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream.flushBuffer(UnsyncBufferedOutputStream.java:62)

at com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream.flush(UnsyncBufferedOutputStream.java:78)

at com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream.close(UnsyncBufferedOutputStream.java:84)

at com.sun.org.apache.xml.internal.security.c14n.implementations.CanonicalizerBase.engineCanonicalizeSubTree(CanonicalizerBase.java:192)

at com.sun.org.apache.xml.internal.security.c14n.implementations.CanonicalizerBase.engineCanonicalize(CanonicalizerBase.java:138)

at com.sun.org.apache.xml.internal.security.transforms.implementations.TransformC14N.enginePerformTransform(TransformC14N.java:65)

at com.sun.org.apache.xml.internal.security.transforms.Transform.performTransform(Transform.java:350)

at org.jcp.xml.dsig.internal.dom.ApacheCanonicalizer.transform(ApacheCanonicalizer.java:218)

 7 more

Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_MECHANISM_INVALID

at sun.security.pkcs11.wrapper.PKCS11.C_SignUpdate(Native Method)

at sun.security.pkcs11.P11Signature.engineUpdate(P11Signature.java:365)

 18 more

java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_MECHANISM_INVALID

at sun.security.pkcs11.P11Signature.engineUpdate(P11Signature.java:371)

at java.security.Signature$Delegate.engineUpdate(Signature.java:1118)

at java.security.Signature.update(Signature.java:684)

at org.jcp.xml.dsig.internal.SignerOutputStream.write(SignerOutputStream.java:68)

at com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream.flushBuffer(UnsyncBufferedOutputStream.java:62)

at com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream.flush(UnsyncBufferedOutputStream.java:78)

at com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream.close(UnsyncBufferedOutputStream.java:84)

at com.sun.org.apache.xml.internal.security.c14n.implementations.CanonicalizerBase.engineCanonicalizeSubTree(CanonicalizerBase.java:192)

at com.sun.org.apache.xml.internal.security.c14n.implementations.CanonicalizerBase.engineCanonicalize(CanonicalizerBase.java:138)

at com.sun.org.apache.xml.internal.security.transforms.implementations.TransformC14N.enginePerformTransform(TransformC14N.java:65)

at com.sun.org.apache.xml.internal.security.transforms.Transform.performTransform(Transform.java:350)

at org.jcp.xml.dsig.internal.dom.ApacheCanonicalizer.transform(ApacheCanonicalizer.java:218)

at org.jcp.xml.dsig.internal.dom.DOMTransform.transform(DOMTransform.java:129)

at org.jcp.xml.dsig.internal.dom.DOMCanonicalizationMethod.canonicalize(DOMCanonicalizationMethod.java:67)

at org.jcp.xml.dsig.internal.dom.DOMSignedInfo.canonicalize(DOMSignedInfo.java:172)

at org.jcp.xml.dsig.internal.dom.DOMRSASignatureMethod.sign(DOMRSASignatureMethod.java:140)

at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:367)

at inteq.nfe.servicos.util.XMLSigner.sign(XMLSigner.java:128)

at inteq.nfe.servicos.util.XMLSigner.main(XMLSigner.java:169)

Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_MECHANISM_INVALID

at sun.security.pkcs11.wrapper.PKCS11.C_SignUpdate(Native Method)

at sun.security.pkcs11.P11Signature.engineUpdate(P11Signature.java:365)

O que siginifica esse CKR_MECHANISM_INVALID ?

Desculpem o tamanho da mensagem.

Desde java agradeço qualquer ajudar.

T

Isso é um erro definido pelas bibliotecas de PKCS#11 (Mecanismo inválido).

Pode ocorrer quando o algoritmo de assinatura ou de digest, ou de padding da assinatura, não é o aceito pelo dispositivo, mas isso é estranho no seu caso, já que você está solicitando RSA + SHA1, que costuma ser o padrão.

Você tem algum contato com o fabricante (Safenet, que tinha comprado a Rainbow - no meu tempo esse iKey era fabricado pela Rainbow)?

V

Hahaha, eu sabia!
Eu também estou tendo que enfrentar este dragão que o governo inventou.
Infelizmente quanto a essa parte da chave, eu não posso ajudar muito porque foi um outro cara aqui da equipe que fez essa parte e nesse ponto eu entendo muito pouco.

E

victorwss:
elissandromendes:

Sim

Hahaha, eu sabia!
Eu também estou tendo que enfrentar este dragão que o governo inventou.
Infelizmente quanto a essa parte da chave, eu não posso ajudar muito porque foi um outro cara aqui da equipe que fez essa parte e nesse ponto eu entendo muito pouco.

Verdade, é um dragão !! rs

Qual o token que vcs utilizaram ?

Teria como ver se no codigo acima estou cometendo algum erro, ou de repente manda um codigo de vcs pra eu verificar contra esse meu token aqui ?

abracos.

E

Amigos,

E quanto a acessar o WS via HTTPS usando esse token alguma dica ?

Usando o IE consigo ver blz o WSDL de um dos serviços. Como faco isso no Java e de preferencia no ambiente do Netbeans.

Isso já me adiantaria bastante, pois o token de assinatura do xml será o da empresa que parece será em arquivo, daí esse meu seria apenas para agir como do transmissor.

Agradeco.

V

Cara, tenta algo mais ou menos assim. Não sei se vai ajudar:

System.setProperty("javax.net.ssl.trustStore", "C:\\blablabla\\tstore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "sua_senha_aqui");
System.setProperty("javax.net.ssl.keyStoreType", "pkcs12");
O

Bem, como diria o estripador, vamos por parte:

  1. Web Services
    Procure por um framework que implemente WS-SOAP. Exemplos: Axis, XFire.

  2. É necessário certificação do cliente para acessar este Web Service?
    Se sim, você vai ter que usar JSSE. De uma procurada por exemplos aqui mesmo no GUJ.

  3. É a mesma chave (eCNPJ) que vai assinar a mensagem que vai autenticar para acesso via Web Services?
    Se sim, você vai ter que setar assim:

System.setProperty("javax.net.ssl.keyStoreType", "pkcs11");

e configurar a parte de certificados em uma outra keystore.

E

oyama:
Bem, como diria o estripador, vamos por parte:

  1. Web Services
    Procure por um framework que implemente WS-SOAP. Exemplos: Axis, XFire.

Estou usando o JAX-WS do Java 6 para implementar o cliente. Aparentemente está OK, testei acessando um servidor construido com os WSDLs dos servicos da sefaz que consegui baixar, porem sem acessar via HTTPS.

Tranquilo irei dar uma olhada.

oyama:

3) É a mesma chave (eCNPJ) que vai assinar a mensagem que vai autenticar para acesso via Web Services?
Se sim, você vai ter que setar assim:

System.setProperty("javax.net.ssl.keyStoreType", "pkcs11");

e configurar a parte de certificados em uma outra keystore.

Quando em produção não serão a mesma. Teremos a nossa, um eCNPJ para acessar o WS e nosso cliente terá a de assinatura ou essa de assinatura do cliente servirá tambem para acessar o WS.

Um pergunta quanto a configuração que vc citou, tenho como exportar o certificado do token e converte-lo de forma a importa-lo num arquivo JKS e assim informar esse JKS como sendo o meu keystore donde o SSL buscara a autenticacao.

Vi alguma coisa na net vou dar uma olhada, se já tiver algo por ai agradeco.

abracos.

V

Olha, vou te dar essa dica: Não confie no WSDL porque algumas UFs não o geram corretamente (e o azar por isso é do contribuinte). Analise-o já pensando em que tipo de atitude tomar para remendar quaisquer inconsistências que tiver.

E

Bom galera,

Estou aguardando resposta do pessoal sa SafeNet BR pra saber o que seria esse problema de INVALID MECHANISM.

Acredito que o código que estou usando está ok! Dever ser algum pro de configuração, onde devo estar deixando ligado alguns dos mecanismos que são citados na documentação só que não é o correto pra esse meu modelo.

Assim que tiver uma resposta positiva posto aqui.

De agora, muito massa ajuda de vcs.

Obrigado mesmo !!

abraços.

P

elissandromendes:
Bom galera,

Estou aguardando resposta do pessoal sa SafeNet BR pra saber o que seria esse problema de INVALID MECHANISM.

Acredito que o código que estou usando está ok! Dever ser algum pro de configuração, onde devo estar deixando ligado alguns dos mecanismos que são citados na documentação só que não é o correto pra esse meu modelo.

Assim que tiver uma resposta positiva posto aqui.

De agora, muito massa ajuda de vcs.

Obrigado mesmo !!

abraços.

Opa, estou com a mesma bronca. Tem alguma dica?

Grato

Alencar

G

Galera… estou com um problema parecido…
tenho um programa pra emissao da nfe que funciona perfeitamente com os certificados PFX e SmartCard(CartaoInteligente)

Porem agora tenho que implementar para o certificado no dispositivo de token(pendrive)

So que nao vai nem a pau…
eu até consigo ler o certificado do token usando o esquema do .cfg… com a dll do fornecedor e tal…

Porem qdo mando a mensagem soap, da o seguinte erro:

14/05/2010 16:24:22 com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPConnection post
SEVERE: SAAJ0009: Message send failed
com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: java.security.PrivilegedActionException: com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Message send failed
at com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPConnection.call(HttpSOAPConnection.java:146)

Estou usando o Safenet iKey 2032

Alguem tem alguma dica pra me dar ??
Obrigado…

P

O conteudo do arquivo de configuração (pkcs11.cfg) é um pouco diferente para este Token:

name=eToken

library=c:\windows\system32\dkck201.dll

disabledMechanisms = {

CKM_SHA1_RSA_PKCS

}

Alencar

G

Ainda esta dando o mesmo erro…!!

MInha conexao esta assim:

String keyPass = "";
        String proto = "SSLv3";
        keyPass = nfs.getCfg().getDescriptoSenha();
        Provider p = null;
        if(nfs.getCfg().getUsaToken().equalsIgnoreCase("S")){

        p = new sun.security.pkcs11.SunPKCS11(nfs.getCfg().getCfg());
        ks = KeyStore.getInstance("PKCS11", p);
        ks.load(null, keyPass.toCharArray());
        }else{
        p = new com.sun.net.ssl.internal.ssl.Provider();
        ks = KeyStore.getInstance("PKCS12", p);
        ks.load(new FileInputStream(nfs.getCfg().getLocalPFX()), keyPass.toCharArray());
        }

        Security.addProvider(p);

        KeyManagerFactory kmf = null;
        kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(ks, keyPass.toCharArray ());
        KeyManager[] km =  kmf.getKeyManagers();
        TrustManagerFactory tmf = null;
        tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(ks);

        SSLContext sc = null;
        sc = SSLContext.getInstance(proto);
        sc.init(km, trustAllCerts, new java.security.SecureRandom());
        SSLContext.setDefault(sc);
 
        SSLSocketFactory socketFactory = sc.getSocketFactory();
        socket = (SSLSocket)socketFactory.createSocket(host, port);
        socket.addHandshakeCompletedListener(this);
        socket.setUseClientMode(true);
        socket.startHandshake();

Valew

L

Boa tarde elissandromendes

Estou com o mesmo problema seu, verifiquei o seguinte (token da rainbow);

No token existe a seguinte cadeia:
[color=blue] AC Raiz
AC Secretaria da Receita Federal do Brasil
AC Serasa RFB
Empresa com o certificado E-CNPJ
[/color]

No momento que executo o comando:

ks.load(null, new String("xxxxxx").toCharArray());

o mesmo me retorna a informaçao da AC Secretaria da Receita Federal do Brasil (subject=CN=AC Secretaria da Receita Federal do Brasil, O=ICP-Brasil, C=BR)
no entanto deveria vir a informação do “Empresa com o certificado E-CNPJ”.

Como que está retornando para ti esta informação?

Talvez já tenha resolvido, pela data, é bem antiga, teria alguma resposta para mim?

Muito obrigado

P

lcspohn:
Boa tarde elissandromendes

Estou com o mesmo problema seu, verifiquei o seguinte (token da rainbow);

No token existe a seguinte cadeia:
[color=blue] AC Raiz
AC Secretaria da Receita Federal do Brasil
AC Serasa RFB
Empresa com o certificado E-CNPJ
[/color]

No momento que executo o comando:

ks.load(null, new String("xxxxxx").toCharArray());

o mesmo me retorna a informaçao da AC Secretaria da Receita Federal do Brasil (subject=CN=AC Secretaria da Receita Federal do Brasil, O=ICP-Brasil, C=BR)
no entanto deveria vir a informação do “Empresa com o certificado E-CNPJ”.

Como que está retornando para ti esta informação?

Talvez já tenha resolvido, pela data, é bem antiga, teria alguma resposta para mim?

Muito obrigado

Neste caso, você precisa “varrer” os certificados que retornam do token e tentar extrair a PK. Quando conseguir, será o certificado do seu cliente.
Caso contrário, é tão somente um certificado da cadeia validadora.
Para facilitar eu criei um arquivo de configuração onde o meu sistema extrai o alias correto e seta neste arquivo.
Isso evita que tenha que pesquisar todas as vezes que vai usar o token/cartão. Além disso, caso o processo falhe na localização do alias correto,
ainda tenho a possibilidade de setá-lo a mão.

Alencar

L

Boa Tarde Alencar

Muito obrigado pelo retorno.

Ref. ao que vc falou, eu já faço isso, segue modelo que fiz para teste:

KeyStore ks = KeyStore.getInstance("PKCS11");
	ks.load(null, certificado.getcertificadoPassword().toCharArray());
	
    Enumeration<String> aliasesEnum = ks.aliases();
    while (aliasesEnum.hasMoreElements()) {  
        String alias = (String) aliasesEnum.nextElement();
	        
        X509Certificate certif = (X509Certificate)ks.getCertificate(alias);
        System.out.println( "SN =     " + certif.getSerialNumber().toString(16) );
        System.out.println( "Issuer = " + certif.getIssuerDN().toString() );
        System.out.println( "subject= " + certif.getSubjectDN().toString() );
	}

Neste caso acima é para varrer todos os certificados que existem no token.

Normalmente só traz o certificado da empresa e neste token que eu tenho está estranho, está trazendo somente o da secretaria da receita federal.

[color=red]SunPKCS11-Safenetikey2032 RSA private key, 1024 bits (id 2621440, token object, sensitive, unextractable)
SN = 5
Issuer = CN=Autoridade Certificadora Raiz Brasileira v1, OU=Instituto Nacional de Tecnologia da Informacao - ITI, O=ICP-Brasil, C=BR
subject= CN=AC Secretaria da Receita Federal do Brasil, O=ICP-Brasil, C=BR
[/color]

No subject deveria trazer o nome da empresa e ou cnpj, se eu visualizar este certificado pelo próprio token está correto e pelo internet explorer também, consegui emitir uma nota fiscal pelo site da receita normalmente com este token.

Mas via código java não consigo, estou utilizando a versão 1.6.0_20 do java.

P

Eis o motivo pelo qual fiz um arquivo de configuração. Quando nada mais funciona, seto o alias do certificado certo no braço.

Alencar

L

Bom dia Alencar,

Mas neste caso o arquivo de configuiração para mim não irá resolver, fiz este teste não deu certo, o problema que não aparece os certificados após o load. Pode ser que eu esteja enganado, mas o código abaixo deveria listar todos os certificados no token, correto?
Provider p = new sun.security.pkcs11.SunPKCS11(getcertificadoFile());

Security.addProvider(p);

KeyStore ks = KeyStore.getInstance("PKCS11");
ks.load(null, null);
	
Enumeration<String> aliasesEnum = ks.aliases();
while (aliasesEnum.hasMoreElements()) {  
    String alias = (String) aliasesEnum.nextElement();
	        
    System.out.println("----> Certificado alias: " + alias + "    Key store type: " + ks.getType());
    X509Certificate certif = (X509Certificate)ks.getCertificate(alias);
    System.out.println( "SN =     " + certif.getSerialNumber().toString(16) );
    System.out.println( "Issuer = " + certif.getIssuerDN().toString() );
    System.out.println( "subject= " + certif.getSubjectDN().toString() );
}
No entanto só me mostra uma cadeia.

o problema é: No IE mostra a cadeia completa e o certificado está OK (Repositório de certificados do windows), já neste código acima só mostra um certificado da cadeia, no caso o da secretaria da receita federal. Será por que?

P

lcspohn:
Bom dia Alencar,

…o problema é: No IE mostra a cadeia completa e o certificado está OK (Repositório de certificados do windows), já neste código acima só mostra um certificado da cadeia, no caso o da secretaria da receita federal. Será por que?

Ja tive casos em que foi necessário incluir no token a cadeia certificadora correta, pois a que tinha no token não validava o
certificado do cliente.
No IE, a cadeia é auto instalada (não sei como), por isso lá você vê ela completa.

O que eu faço: Pelo software de instalação/administração do token, analiso a cadeia visualmente. Caso ela não feche com o certificado
ou falte parte dela, importo o certificado correto/restante pelo software do token.

QQ coisa, contate-me em pvt. Após resolver o problema, você publica a solução aqui, para conhecimento de todos.

Alencar

M

Olá Meus Camaradas, eu já to sendo chamado se São Jorge aqui na firma.

Segue abaixo o codigo que usei para assinar e enviar com o SmartCard da Safeweb, por pendrive é a mesma coisa, só que já vou avisando, fica consideravelmente lento para um numero grande de nf-es.

Espero que ajude.

try {
			
			String tag = "infNFe";
			String caminhoCertificado = Utilitario.caminhoCertCli();
			String senha = Utilitario.senhaCertCli();
			
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			factory.setNamespaceAware(false);
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document docs = builder.parse(new File(caminhoNfe));
			
			NodeList elements = docs.getElementsByTagName(tag);
			Element el = (Element) elements.item(0);
			String id = el.getAttribute("Id");
			
			NodeList elements2 = docs.getElementsByTagName("nNF");
			Element elIdNfe = (Element) elements2.item(0);
			idNfeS = elIdNfe.getTextContent();
			
			String providerName = System.getProperty(PROVIDER_NAME, PROVIDER_CLASS_NAME);
			XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM", (Provider) Class.forName(providerName).newInstance());		

			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); 
			SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,(C14NMethodParameterSpec) null), fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(ref)); 

			//A3
			Provider p = new sun.security.pkcs11.SunPKCS11("c:/sistema/token.cfg");
			Security.addProvider(p);
			
			X509Certificate certificado = null;
			KeyStore ks = null;
			try {
				ks = KeyStore.getInstance("PKCS11");
			} catch (KeyStoreException e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
			}
			try {
				ks.load(null, "safeweb".toCharArray());
			} catch (NoSuchAlgorithmException e) {
				log.info("Erro Assinatura Envio 1: " + e.getMessage());
				e.printStackTrace();
			} catch (CertificateException e) {
				log.info("Erro Assinatura Envio 2: " + e.getMessage());
				e.printStackTrace();
			} catch (IOException e) {
				log.info("Erro Assinatura Envio 3: " + e.getMessage());
				e.printStackTrace();
			}
			
			Enumeration aliasesEnum = ks.aliases(); 
			String alias = ""; 
			while (aliasesEnum.hasMoreElements()) { 
				alias = (String) aliasesEnum.nextElement(); 
				if (ks.isKeyEntry(alias)) {
					//log.info("Entrou: " + alias);
					certificado = (X509Certificate) ks.getCertificate(alias);
					break; 
				} 
			} 


			//A3
                        //aqui eu coloquei fixo, mas, pode ficar conforme a linha de baixo
			KeyStore.PrivateKeyEntry keyEntryA3 = (PrivateKeyEntry) ks.getEntry("3ab3ec9f-2b00-434e-9b88-4154f3853a08", new KeyStore.PasswordProtection("safeweb".toCharArray()));
                        //KeyStore.PrivateKeyEntry keyEntryA3 = (PrivateKeyEntry) ks.getEntry(alias, new KeyStore.PasswordProtection("safeweb".toCharArray()));
			X509Certificate cert = (X509Certificate) keyEntryA3.getCertificate();
						
			//log.info("Certificado: " + keyEntryA3);
			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); 
			Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(caminhoNfe)); 

			DOMSignContext dsc = new DOMSignContext(keyEntryA3.getPrivateKey(), doc.getDocumentElement().getElementsByTagName("NFe").item(0));
			
			XMLSignature signature = fac.newXMLSignature(si, ki); 
			signature.sign(dsc); 

			doc.setXmlStandalone(true);
			
			NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); 
			
			if (nl.getLength() == 0) { 
				throw new Exception("Elemento assinatura não encontrado"); 
			} 
			DOMValidateContext valContext = new DOMValidateContext( new X509KeySelector(ks), nl.item(0)); 
			XMLSignature signatures = fac.unmarshalXMLSignature(valContext); 
			boolean coreValidity = signatures.validate(valContext); 
			if (coreValidity == false) { 
				System.err.println("Falha na Assinatura!");			
				log.info("Falha na Assinatura da NF-e " + idNfeS);				
			} else { 
				System.out.println("Assinatura Correta!");				
				log.info("Assinatura  da NF-e " + idNfeS + " correta.");
			} 
						
			OutputFormat format    = new OutputFormat(doc); 
			StringWriter stringOut = new StringWriter ();    
	    	XMLSerializer serial   = new XMLSerializer (stringOut,format);
		    serial.serialize(doc);
		    
		    nfeDadosMsg = stringOut.toString();
		
		} catch (Exception e){
			texto.append("Exception a: " + e.getMessage() + "\n");
			texto.setCaretPosition(texto.getText().length());
			texto.repaint();
		}
	
		String retornoProc = null;
		
		Provider p = new sun.security.pkcs11.SunPKCS11("c:/sistema/token.cfg");
		Security.addProvider(p);
				
		KeyStore ks = null;
		try {
			ks = KeyStore.getInstance("PKCS11");
		} catch (KeyStoreException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
		try {
			ks.load(null, "safeweb".toCharArray());			
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (CertificateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		Enumeration aliasesEnum = null;
		try {
			aliasesEnum = ks.aliases();
		} catch (KeyStoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		while (aliasesEnum.hasMoreElements()) {
		   String alias = (String)aliasesEnum.nextElement();
		   X509Certificate cert = null;
		   try {
			   cert = (X509Certificate) ks.getCertificate(alias);			   
			   certificadoVector.add(cert);
		   } catch (KeyStoreException e) {
			   // TODO Auto-generated catch block
			   e.printStackTrace();
		   }
		   
		   //System.out.println("Certificate: " + cert);
		   PrivateKey privateKey = null;
		   try {
			   privateKey = (PrivateKey) ks.getKey(alias, null);
		   } catch (UnrecoverableKeyException e) {
			   // TODO Auto-generated catch block
			   e.printStackTrace();
		   } catch (KeyStoreException e) {
			   // TODO Auto-generated catch block
			   e.printStackTrace();
		   } catch (NoSuchAlgorithmException e) {
			   // TODO Auto-generated catch block
			   e.printStackTrace();
		   }
		   //System.out.println("Private key: " + privateKey);
		}
		
		DocumentBuilderFactory factoryV = DocumentBuilderFactory.newInstance();
        System.out.println("DocumentBuilderFactory: "+ factoryV.getClass().getName());
        
	System.setProperty("javax.net.ssl.keyStoreType", ks.getType());   
        System.setProperty("javax.net.ssl.keyStore", "NONE"); 
        System.setProperty("javax.net.ssl.keyStoreProvider", "SunPKCS11-Safeweb");   
        System.setProperty("javax.net.ssl.keyStorePassword", "safeweb");   
		
        System.setProperty("javax.net.ssl.trustStoreType", Utilitario.tipoCertSrv());
		System.setProperty("javax.net.ssl.trustStore", Utilitario.caminhoCertSrv());//Aqui vem o arquivo criado através do comando keytool no passo 3
		System.setProperty("javax.net.ssl.trustStorePassword", Utilitario.senhaCertSrv());//Aqui a senha deste keystore
		
		//versao 2.00
		br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub.NfeCabecMsg cabecalho = new br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub.NfeCabecMsg();
		cabecalho.setCUF("43");
		cabecalho.setVersaoDados("2.00");

		br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub.NfeCabecMsgE cabE = new br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub.NfeCabecMsgE();     
		cabE.setNfeCabecMsg(cabecalho);     
		
		OMElement el = null;
		try {
			el = AXIOMUtil.stringToOM(nfeDadosMsg);
		} catch (XMLStreamException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		el.build();
		System.out.println("el -> " + el.toString());
		
		br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub.NfeDadosMsg dadosMsg = new br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub.NfeDadosMsg();
		//dadosMsg.setExtraElement(oNfeDadosMsg.getFirstElement());
		dadosMsg.setExtraElement(el);

		br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub.NfeRecepcaoLote2Result result = null;
		try {
			result = new br.inf.portalfiscal.www.nfe.wsdl.nferecepcao2.NfeRecepcao2Stub().nfeRecepcaoLote2(dadosMsg, cabE);			
		} catch (AxisFault e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
L

Pessoal, pegando o código do repositório do windows conseguir assinar o aquivo

//  KeyStore ks = KeyStore.getInstance("PKCS11");  
KeyStore ks = KeyStore.getInstance("Windows-MY");
ks.load(null, certificado.getcertificadoPassword().toCharArray());  
   
Enumeration<String> aliasesEnum = ks.aliases();  
while (aliasesEnum.hasMoreElements()) {    
  String alias = (String) aliasesEnum.nextElement();  
          
  X509Certificate certif = (X509Certificate)ks.getCertificate(alias);  
  System.out.println( "SN =     " + certif.getSerialNumber().toString(16) );  
  System.out.println( "Issuer = " + certif.getIssuerDN().toString() );  
  System.out.println( "subject= " + certif.getSubjectDN().toString() );  
}

Mas, no momento que assinar pede a senha PIN na tela e no momento que tentar enviar para a SEFAZ apresente erro:

; nested exception is:
javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate

F

Pessoal,

Bom dia!

Estou com um problema com o token ikey2032.

Para me conectar a base de dados da empresa naqual trabalho utilizo os progrmas pageantsc e puttysc, no windows xp eu configurava o puttysc com a dll (dkck201.dll) onde tinha a chave do meu Certificado.

Com a nova versão para windows 7 (http://loja.certificadodigital.com.br/Serasa/Instale%20o%20token/D162) Minha chave não reconhece.

Tem como descobrir se há uma nova dll para o windows 7 ?

Agradeço muito a ajuda de vocês.

att.:
Fábio Araújo

F

Consegui…

No Windows XP a DLL que você informava era dkck201.dll, em C:\WINDOWS\system32\ na opção SSH > pkcs11 do Putty.

Para o Windows 7, você terá que informar a dll: eTPKCS11.dll, no mesmo caminho C:\WINDOWS\system32\

Criado 31 de janeiro de 2008
Ultima resposta 2 de set. de 2010
Respostas 28
Participantes 9