[Resolvido] SunMSCAPI X SunPKCS11 - Identificar e carregar Token Certificado A3

24 respostas
P

Boa tarde pessoal!

Estou apanhando feio com o seguinte problema:

Desenvolvi uma aplicação que efetua a assinatura digital tanto com certificado A1 quanto A3.
Agora preciso implementar a aplicação para escolher antes da assinatura qual certificado ele deseja utilizar seja A1 ou A3 porém o usuário pode usar QUALQUER tipo de token A3 e até aonde eu entendi, através do SunPKCS11 ele sempre irá exigir um arquivo de configuração (exp: token.cfg).

O fato é que nem sempre o usuário final tem essas informações para gerar o arquivo, dei uma lida em vários materiais no google e não encontrei nenhum solução (quase) pronta.

Achei muito bom o material JavaTM PKCS#11 Reference Guide (http://migre.me/EWdb) e Java ? Cryptography Architecture
Sun Providers Documentation (http://migre.me/EWeV) porém até onde eu entendi sempre irei precisar do arquivo de configuração, o que não é viável!

Comecei a dar uma lida sobre o SunMSCAPI, e com base no código do vanderlanio(http://migre.me/EXcd) inclui o 'if' para listar os certificados do usuário.

KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
ks.load(null, null);
	
Enumeration<String> aliasEnum = ks.aliases();
	
while (aliasEnum.hasMoreElements()) {
	String aliasKey = (String) aliasEnum.nextElement();
		
	if (ks.isKeyEntry(aliasKey)) {
		System.out.print(aliasKey + "\n");
	}			
}
[size=18] [/size]

Bom em resumo preciso encontrar uma maneira de encontrar o token a3 e descobrir seu name e library ehehe, se alguém puder ajudar agradeço MUITO mesmo!

Obrigado!

P.S: 1° post no GUJ, fiquei em dúvida entre abrir um novo tópico ou inserir a msg neste: http://guj.com.br/posts/list/91330.java#797805 se fiz errado desculpa aé! heheh

24 Respostas

P

O que fiz em cenário semelhante foi utilizar uma tabela interna com o nome dos módulos mais comuns e procurá-los no sistema do cliente em localizações igualmente “bem conhecidas”. Para a tabela inicial utilizei informações do projecto OpenSC, entre outros. O código de inicialização tenta localizar as DLLs (ou .SO em Linux) e, se encontrar uma, cria o arquivo de configuração “on-the-fly” e cria o provider.

Um pouco enrolado, mas funciona.

P

ai caramba!!!

que trabalhareira hahaha

psevestre estou estudando agora o OpenSC parace ser muito interessante (http://www.opensc-project.org/opensc) e ainda vou continuar pesquisando outras soluções heheh

por acaso vc tem 1 caminho das pedras for dummies sobrando aé??? :smiley:

bom supondo q no meu caso são quase 1 mil “pontos de venda” que podem ou não utilizar o token A3 e estão espalhados por todo o Brasil acho que eu vou encontrar com mts tokens por ai hahaah

valeu!

P

opa, voltando ao tópico apenas para finalizar…

faz quase 2 meses que eu consegui resolver esse PROBLEMINHA aqui heheh

tipo conseguir dar um “load” no token A3, carregar uma lista com todos os certificados A1 e A3 no pc e depois escolher qual será utilizado e informar a senha.

para isso eu utilizei MSCAPI pois o sistema Java esta integrado ao ERP que roda apenas em ambientes windows.

bom é isso aé, finished!

L

Oi pedruhenrik,

Estou apanhando aqui para acessar o certificado A3 de um SmartCard. Poderia postar seu código para eu ver como vc vez a sua solução?

Obrigado,

Leonardo

P

olá leonardom, td bem?

desculpa a demora em responder, só vi ontem o email do tópico,hehe malz ai,

abaixo esta como eu faço p/ localizar o certificado q será utilizado,
nos demais processos eu só passo o aliaskey como parametro.

KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
ks.load(null, null);
Enumeration<String> aliasEnum = ks.aliases();
	while (aliasEnum.hasMoreElements()) {
		String aliasKey = (String) aliasEnum.nextElement();
		if (ks.isKeyEntry(aliasKey)) {
             		system.out.println(aliasKey);
		}
	}

ajudou em alguma coisa?heheh
vou abrir o projeto e acho q consigo passar mais código depois, ok?
lembrando q desse jeito só funciona em sistemas operacionais windows e só consegui testar com certificados A1 e A3 do token.
Tem 1 cliente q tentou utilizar com smartcard mas ainda não tive retorno se deu certo ou não.
Teoricamente ñ era p/ ter erros já q fica preso ao repositório de certificados do windows.

até.

abs!

J

pedruhenrik:
olá leonardom, td bem?

desculpa a demora em responder, só vi ontem o email do tópico,hehe malz ai,

abaixo esta como eu faço p/ localizar o certificado q será utilizado,
nos demais processos eu só passo o aliaskey como parametro.

KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
ks.load(null, null);
Enumeration<String> aliasEnum = ks.aliases();
	while (aliasEnum.hasMoreElements()) {
		String aliasKey = (String) aliasEnum.nextElement();
		if (ks.isKeyEntry(aliasKey)) {
             		system.out.println(aliasKey);
		}
	}

ajudou em alguma coisa?heheh
vou abrir o projeto e acho q consigo passar mais código depois, ok?
lembrando q desse jeito só funciona em sistemas operacionais windows e só consegui testar com certificados A1 e A3 do token.
Tem 1 cliente q tentou utilizar com smartcard mas ainda não tive retorno se deu certo ou não.
Teoricamente ñ era p/ ter erros já q fica preso ao repositório de certificados do windows.

até.

abs!


O que essa linha faz?
KeyStore ks = KeyStore.getInstance(“Windows-MY”, “SunMSCAPI”);

O que é esse Windows-MY?

P

até onde eu entendi ela q vai criar a instancia keystore p/ poder acessar os certificados disponiveis no windows.

o primeiro parametro é o tipo de keystore,
nesse caso o keystore do windows,

tb tem o Windows-ROOT mas oq deu certo p/ mim foi o Windows-My msm.

outra maneira tb de acessar o token:

Provider p = new
sun.security.pkcs11.SunPKCS11("C:\\NFE\\token.cfg");
Security.addProvider(p);

KeyStore ks = KeyStore.getInstance("PKCS11");
ks.load(null, senha.toCharArray());

o arquivo token.cfg:

name = eToken //o name do token no meu caso 1 token Aladin
library =  C:\WINDOWS\system32\eTpkcs11.dll //passa a dll utilizada pelo token

e ai o processo de assinatura é quase o mesmo do token A1(se não o mesmo…rsrs)

att,

J

estou com um problema meio bobo, mas não consegui identificar o motivo.

tenho uma exception, quando tento rodar qualquer código que envolva KeyStore (com Windows-MY ou Windows-ROOT)

KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");

java.security.NoSuchProviderException: no such provider: SunMSCAPI

Eu preciso alguma configuração/permissão de segurança no meu sistema operacional pra isso? (estou usando Windows 7 e JAVA 6)

O

@pedruhenrik

seus exemplos de uso do repositório do windows me ajudaram muito, eu consigo listar os certificados e assinar um arquivo, porém estou tendo problemas na hora de fazer uma conexão soap.

Você consegue consumir um webservice de nfe utilizando o repositório do windows? poderia postar algum código de exemplo?

obrigado

P

opa q bom q ajudou!

http://www.guj.com.br/java/237281-tutorial-consumir-webservice-nfe-20

da uma olhada nesse link e vê se te ajuda, ok?

att,

H

pessoal será que existe alguma bibilioteca dessas no linux?

Obrigado!

P

talvez eu esteja falando a maior besteira do universo…mas será q openssl não ajudaria nesse caso?

att,

H

Boa noite pedrohenrick estou com um problema no meu e-token pois perdi a senha e nao consigo acessa-lo ja usei quase todas as tentativas e se bloquea-lo terei que pedir outro certificado e pagar tudo novamente. Gostaria de saber se tem como acessar o token e mudar ou descobrir qual é a senha.
Fico no Aguardo obrigado

F

Um token normalmente possui um PIN (senha) e um PUK, que é usado quando você erra a senha repetidas vezes. Consulte o fabricante.
Escrevi um post sobre tokens em meu site: http://www.flaviojmendes.com/blog/2012/02/24/assinando-um-documento-com-token-ou-smartcard/

J

Pessoal, já consegui fazer a leitura do Token a3 e assinar um arquivo. Mas estou com o seguinte problema: o sistema que estou trabalhando gera um certificado que pode ser usado somente nele. No entanto quando o usuário instala o certificado e digita a senha, ela nunca mais é solicitada no mesmo computador.

Alguém sabe dizer se isso é configurável no navegador ou se isso é alguma configuração de leitura ? existe a possibilidade de sempre forçar o usuário a digitar a senha ?

Obrigado.

F

Boa Tarde , uma duvida ja consegui localizar o eToken com esse trecho de codigo

Enumeration<String> aliasEnum = ks.aliases();  
		while (aliasEnum.hasMoreElements()) {  
			String aliasKey = (String) aliasEnum.nextElement();  
			if (ks.isKeyEntry(aliasKey)) {  
				System.out.println(" key > " + aliasKey);  
			}  
		}

Agora gostaria de saber como faço para carregar o eToken por exemplo para validar se a senha esta correta ou não.

H

Cara, vc está usando isso em um contexto web ?

F

Não , estou em uma aplicação desktop .

H

Cara,

Dá uma olhada nesse link espero que te ajude.

Abraços

F

Duvida Pessoal .

APÓS varias tentativas eu CONSEGUI efetuar a assinatura do xml com o meu certificado.
mas para eu conseguir assinar meu xml eu precisei localizar a .DLL e criar um arquivo .CFG e dai
funcionou beleza !!!

A duvida é a seguinte :

como farei pra localizar as DLLs utilizadas pelo meus clientes ?

Pelo que eu li ate agora existe uma maneira diferente de fazer essa assinatura que seria pelo repositório do windows
como seria para fazer desse jeito ?? pois até agora não achei exemplos

Obrigado Galera

H

Cara…

Algo parecido com isso :

// Obtém um keystore com os certificados pessoais do usuário logado no windows
KeyStore keyStore = KeyStore.getInstance("Windows-MY", providerName);			
		
// Carrega o keystore
keyStore.load(null, null);
J

pedruhenrik:

O que essa linha faz?
KeyStore ks = KeyStore.getInstance(“Windows-MY”, “SunMSCAPI”);

até onde eu entendi ela q vai criar a instancia keystore p/ poder acessar os certificados disponiveis no windows.

o primeiro parametro é o tipo de keystore,
nesse caso o keystore do windows,

tb tem o Windows-ROOT mas oq deu certo p/ mim foi o Windows-My msm.

outra maneira tb de acessar o token:

Provider p = new
sun.security.pkcs11.SunPKCS11("C:\\NFE\\token.cfg");
Security.addProvider(p);

KeyStore ks = KeyStore.getInstance("PKCS11");
ks.load(null, senha.toCharArray());

o arquivo token.cfg:

name = eToken //o name do token no meu caso 1 token Aladin
library =  C:\WINDOWS\system32\eTpkcs11.dll //passa a dll utilizada pelo token

e ai o processo de assinatura é quase o mesmo do token A1(se não o mesmo…rsrs)

att,

no meu pc so tenho a dll opensc-pkcs11.dll
gostaria de saber como faço para conseguir essa dll que vc mencionou. porque a que eu estou utilizando aqui dá o seguinte ero:

java.security.KeyStoreException: PKCS11 not found
	at java.security.KeyStore.getInstance(KeyStore.java:705)
	at org.opensc.util.Test.main(Test.java:20)
Caused by: java.security.NoSuchAlgorithmException: no such algorithm: PKCS11 for provider SunPKCS11-eToken
	at sun.security.jca.GetInstance.getService(GetInstance.java:100)
	at sun.security.jca.GetInstance.getInstance(GetInstance.java:218)
	at java.security.Security.getImpl(Security.java:724)
	at java.security.KeyStore.getInstance(KeyStore.java:702)
	... 1 more
J

eu consegui resolver . No computador que eu desenvolvi não tinha os drivers do Aladdin PRO.
resumidamente, pra eu ter essa dll só faltava todos os drivers fornecido por mim pela propria certificadora:

meu certificado é da CERTISIGN e la na pagina deles tem o driver especifico:
https://www.certisign.com.br/atendimento-suporte/downloads/tokens/windows

funcionou!

E

josemdvdf:
Pessoal, já consegui fazer a leitura do Token a3 e assinar um arquivo. Mas estou com o seguinte problema: o sistema que estou trabalhando gera um certificado que pode ser usado somente nele. No entanto quando o usuário instala o certificado e digita a senha, ela nunca mais é solicitada no mesmo computador.

Alguém sabe dizer se isso é configurável no navegador ou se isso é alguma configuração de leitura ? existe a possibilidade de sempre forçar o usuário a digitar a senha ?

Obrigado.

Bom dia a todos.

cara tem como postar teu código que tu assina o xml ?

E me passar o teu xml ?

porque eu estou tentando fazer de uma forma aqui, mas ele não está assinando…

mas também não da erro nenhum…

eu faço isso

Provider provider = new sun.security.pkcs11.SunPKCS11("C:/SmartCard.cfg");  
	        Security.addProvider(provider);   
	  
	        KeyStore ks = KeyStore.getInstance("pkcs11", provider);  
	        try {  
	            ks.load(null, senha.toCharArray());  
	        } catch (IOException e) {  
	            throw new Exception("Senha do Certificado Digital incorreta ou Certificado inválido.");  
	        }  
	  
	        KeyStore.PrivateKeyEntry pkEntry = null;  
	        Enumeration<String> aliasesEnum = ks.aliases();  
	        while (aliasesEnum.hasMoreElements()) {  
	            String alias = (String) aliasesEnum.nextElement();  
	            if (ks.isKeyEntry(alias)) {  
	                pkEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias,  
	                        new KeyStore.PasswordProtection(senha.toCharArray()));  
	                privateKey = pkEntry.getPrivateKey();  
	                break;  
	            }  
	        }  
	  
	        X509Certificate cert = (X509Certificate) pkEntry.getCertificate();  
	        info("SubjectDN: " + cert.getSubjectDN().toString());  
	  
	        KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();  
	        List<X509Certificate> x509Content = new ArrayList<X509Certificate>();  
	  
	        x509Content.add(cert);  
	        X509Data x509Data = keyInfoFactory.newX509Data(x509Content);  
	        keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data));
Criado 14 de maio de 2010
Ultima resposta 7 de jul. de 2015
Respostas 24
Participantes 13