Esses dias tive um desafio bem bacana, que foi gravar e ler informações em um dispositivo de segurança programado em Java. O dispositivo é o Alladin eToken Pro 72K (Java).
Utilizei ele para autenticação de duas vias, conforme descrito nesse post, mas foi necessário armazenar algumas informações de segurança para aderir a requisição de um cliente na implantação dos requisitos impostos pelo PCI Security Standards Council na criptografia de dados, para não cair na mesma falha que a Playstation Network.
O maior problema que encontrei foi na integração com os drivers do token, mas graças ao departamento de uma universidade da Aústria, consegui encontrar um wrapper JNI para o driver do token: http://jce.iaik.tugraz.at.
Com isso, criei uma biblioteca que pode autenticar, listar, ler e escrever dados no token. Não posso entrar em detalhes gerais do funcionamento da solução completa, por questões de segurança e contrato de confidencialidade, mas posso mostrar como gravar e recuperar informações do token. Para facilitar minha vida, criei duas classes, uma responsável pela conexão com o token e outra responsável pela manipulação dos dados. As classes estão comentadas. É necessário ter o driver do token instalado e configurado na máquina. O procedimento descrito aqui é para Linux, mas o mesmo pode ser feito em windows, bastando apontar o caminho do arquivo .so para um arquivo .dll.
Faça o download do PKCS#11 Wrapper no site: https://jce.iaik.tugraz.at/sic/Products/Core-Crypto-Toolkits/PKCS-11-Wrapper. A biblioteca é gratuita, mas é necessário realizar um cadastro. Descompacte-o. Procure por um arquivo situado dentro da pasta release da sua plataforma. No meu caso a pasta é: ./native/platforms/linux_x64/release. O arquivo se chama libpkcs11wrapper.so para a versão linux. Copie ele para uma outra pasta, juntamente com o arquivo ./java/lib/iaikPkcs11Wrapper.jar. Será necessário esses arquivos para executar o programa.
A primeira classe é responsável pela conexão com o Token: ETokenConnection.
package br.com.thiagovespa.etoken.utils; import iaik.pkcs.pkcs11.Module; import iaik.pkcs.pkcs11.Slot; import iaik.pkcs.pkcs11.Token; import iaik.pkcs.pkcs11.TokenException; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; /** * Classe responsável pela conexão com tokens * * @author Thiago Galbiatti Vespa * @version 2.1 */ public class ETokenConnection { private final static Logger logger = Logger .getLogger(ETokenConnection.class.getName()); private Module pkcs11Module; /** * Inicializa a conexão com o módulo do token * * @param libraryPath * caminho para o driver do token * @throws Exception */ public ETokenConnection(String libraryPath) throws Exception { try { pkcs11Module = Module.getInstance(libraryPath); pkcs11Module.initialize(null); } catch (IOException ex) { logger.log(Level.SEVERE, null, ex); throw ex; } catch (TokenException ex) { logger.log(Level.SEVERE, null, ex); throw ex; } } /** * Recupera todos os slots de token que estão com o token presente * * @return todos os slots de token que estão com o token presente * @throws TokenException */ public Slot[] getTokenSlots() throws TokenException { return pkcs11Module.getSlotList(Module.SlotRequirement.TOKEN_PRESENT); } /** * Recupera todos os slots de token * * @return todos os slots de token * @throws TokenException */ public Slot[] getAllTokenSlots() throws TokenException { return pkcs11Module.getSlotList(Module.SlotRequirement.ALL_SLOTS); } /** * Recupera o primeiro slot que possui um token conectado * * @return primeiro slot que possui um token conectado * @throws TokenException */ public Slot getFirstTokenSlots() throws TokenException { Slot[] slots = getTokenSlots(); if (slots.length < 0) { return slots[0]; } return null; } /** * Recupera o primeiro token no primeiro slot que possui um token conectado * * @return primeiro token no primeiro slot que possui um token conectado * @throws TokenException */ public Token getFirstToken() throws TokenException { Slot slot = getFirstTokenSlots(); if (slot != null) { return slot.getToken(); } return null; } /** * Finaliza a conexão com o móduglo * * @throws TokenException */ public void close() throws TokenException { pkcs11Module.finalize(this); } }
No construtor é necessário passar o caminho do driver do token. Após abrir conexão, você pode obter informações sobre os slots do token e os tokens conectados, um exemplo de uso seria o seguinte:
ETokenConnection conn = null; try { conn = new ETokenConnection("/usr/lib/libeTPkcs11.so"); Slot slot = conn.getFirstTokenSlots(); if (slot != null) { logger.info("Token conectado!"); logger.info(slot.getSlotInfo().toString()); } else { logger.warning("Token não conectado!"); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (conn != null) { conn.close(); } } catch (TokenException e) { // Nada } }
Esse código realiza a conexão com o token (linha 3), recupera o primeiro token (linha 4), mostra informações do slot que possui o token conectado (linha 7) e desconecta (linha 17).
Para manipular os dados do token, criei outra classe: ETokenDataManager.
package br.com.thiagovespa.etoken.utils; import iaik.pkcs.pkcs11.Session; import iaik.pkcs.pkcs11.Token; import iaik.pkcs.pkcs11.TokenException; import iaik.pkcs.pkcs11.TokenInfo; import iaik.pkcs.pkcs11.objects.Data; import iaik.pkcs.pkcs11.objects.X509AttributeCertificate; import iaik.pkcs.pkcs11.objects.X509PublicKeyCertificate; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** * Manipula dados no token * * @author Thiago Galbiatti Vespa * @version 2.0 */ public class ETokenDataManager { private final static Logger logger = Logger .getLogger(ETokenConnection.class.getName()); private Token token; private Session session; /** * Construtor para manipulação de dados no token * * @param token * token que terá os dados manipulados * @throws TokenException * caso o token não esteja conectado */ public ETokenDataManager(Token token) throws TokenException { if (token == null) { logger.severe("Não há token conectado!"); throw new TokenException("Token is not connected!"); } this.token = token; } /** * Abre uma sessão segura com o token * * @param userPIN * senha utilizada no token * @throws TokenException * em caso de senha inválida ou login inválido */ public void openSession(String userPIN) throws TokenException { this.session = token.openSession(Token.SessionType.SERIAL_SESSION, Token.SessionReadWriteBehavior.RW_SESSION, null, null); TokenInfo tokenInfo = token.getTokenInfo(); if (tokenInfo.isLoginRequired()) { if (tokenInfo.isProtectedAuthenticationPath()) { session.login(Session.UserType.USER, null); } else { session.login(Session.UserType.USER, userPIN.toCharArray()); } } } /** * Fecha a conexão com o token * * @throws TokenException */ public void closeSession() throws TokenException { session.logout(); session.closeSession(); session = null; } /** * Realiza a leitura de dados do token * * @param application * aplicação que gravou os dados * @param label * label que identifica os dados * @return dados recuperados e nulo caso não encontrado * @throws TokenException */ public byte[] readData(String application, String label) throws TokenException { if (session == null) { logger.severe("Sessão fechada!"); throw new TokenException("Session is closed!"); } // cria o template para busca Data dataObjectTemplate = new Data(); if (application != null) { // se tiver aplicação atribui dataObjectTemplate.getApplication().setCharArrayValue( application.toCharArray()); } // atribui o label dataObjectTemplate.getLabel().setCharArrayValue(label.toCharArray()); logger.info(dataObjectTemplate.toString()); // inicia a busca session.findObjectsInit(dataObjectTemplate); Object[] foundDataObjects = session.findObjects(1); Data dataObject; if (foundDataObjects.length > 0) { // Estamos considerando que só terá um objeto para o template // definido // Pode haver mais que um dataObject = (Data) foundDataObjects[0]; logger.info("Achou um objeto: "); logger.info(dataObject.toString()); } else { dataObject = null; } // Finaliza a busca session.findObjectsFinal(); if (dataObject == null || dataObject.getValue() == null) { return null; } byte[] data = dataObject.getValue().getByteArrayValue(); return data; } /** * Realiza a gravação de dados no token * * @param data * dados a serem gravados * @param application * aplicação responsável pela gravação * @param label * label para identificação dos dados * @param modifiable * verdadeiro se os dados forem modificáveis * @param privateData * verdadeiro se os dados forem privados * @throws TokenException */ public void writeData(byte[] data, String application, String label, Boolean modifiable, Boolean privateData) throws TokenException { if (session == null) { logger.severe("Sessão fechada!"); throw new TokenException("Session is closed!"); } logger.info("Gravando dados no token..."); // cria o template para inserção Data dataObjectTemplate = new Data(); if (application != null) { // se tiver aplicação atribui dataObjectTemplate.getApplication().setCharArrayValue( application.toCharArray()); } // atribui o label dataObjectTemplate.getLabel().setCharArrayValue(label.toCharArray()); // atribui o conteúdo dataObjectTemplate.getValue().setByteArrayValue(data); // torna o dado persistente no token dataObjectTemplate.getToken().setBooleanValue(Boolean.TRUE); // atribui se o objeto é modificável ou não dataObjectTemplate.getModifiable().setBooleanValue(modifiable); // atribui se o objeto é privado ou não dataObjectTemplate.getPrivate().setBooleanValue(privateData); // cria o objeto no token session.createObject(dataObjectTemplate); logger.info("Dados gravados!"); } /** * Grava o conteúdo do arquivo no token * * @param path * caminho da localização do arquivo * @param application * aplicação responsável pela gravação * @param label * label para identificação dos dados * @param modifiable * verdadeiro se os dados forem modificáveis * @param privateData * verdadeiro se os dados forem privados * @throws IOException * caso o arquivo não exista ou não esteja acessível * @throws TokenException */ public void writeFromFile(String path, String application, String label, Boolean modifiable, Boolean privateData) throws IOException, TokenException { File file = new File(path); InputStream is = new BufferedInputStream(new FileInputStream(file)); try { byte[] dataArray = new byte[(int) file.length()]; is.read(dataArray); writeData(dataArray, application, label, modifiable, privateData); } finally { is.close(); } } /** * Lista todos os objetos em um token convertendo para um objeto certificado * se for um * * @return todos os objetos em um token * @throws TokenException */ public List<Object> listObjects() throws TokenException { List<Object> objectsInToken = new ArrayList<Object>(); session.findObjectsInit(null); iaik.pkcs.pkcs11.objects.Object[] objects = session.findObjects(1); CertificateFactory x509CertificateFactory = null; while (objects.length > 0) { Object object = objects[0]; if (object instanceof X509PublicKeyCertificate) { try { byte[] encodedCertificate = ((X509PublicKeyCertificate) object) .getValue().getByteArrayValue(); if (x509CertificateFactory == null) { x509CertificateFactory = CertificateFactory .getInstance("X.509"); } Certificate certificate = x509CertificateFactory .generateCertificate(new ByteArrayInputStream( encodedCertificate)); logger.info("Certificado lido"); objectsInToken.add(certificate); } catch (Exception ex) { logger.log(Level.SEVERE, "Could not decode this X509PublicKeyCertificate";, ex); } } else if (object instanceof X509AttributeCertificate) { try { byte[] encodedCertificate = ((X509AttributeCertificate) object) .getValue().getByteArrayValue(); if (x509CertificateFactory == null) { x509CertificateFactory = CertificateFactory .getInstance("X.509"); } Certificate certificate = x509CertificateFactory .generateCertificate(new ByteArrayInputStream( encodedCertificate)); logger.info("Certificado att lido"); objectsInToken.add(certificate); } catch (Exception ex) { logger.log(Level.SEVERE, "Could not decode this X509AttributeCertificate", ex); } } else { logger.info("Objeto lido"); objectsInToken.add(object); } objects = session.findObjects(1); } session.findObjectsFinal(); return objectsInToken; } }
O construtor recebe um token de parâmetro (linha 44), obtido no objeto de conexão e realiza operações para inserir dados (linha 160 e 217), consultar e listar os dados existentes no token (linha 98 e 239). O método openSession (linha 60) é responsável por abrir a sessão segura (através da senha do token).
Abaixo segue o exemplo de um código que consulta, insere e lista objetos em um token.
ETokenConnection conn = null; try { conn = new ETokenConnection("/usr/lib/libeTPkcs11.so"); Token token = conn.getFirstToken(); if (token != null) { logger.info("Token conectado!"); ETokenDataManager dataManager = new ETokenDataManager(token); dataManager.openSession("senhaSecreta"); String msg = new String(dataManager.readData(null, "Teste Label")); logger.info("Dados recuperados: " + msg); byte[] data = dataManager.readData("TesteApp", "Secreto"); if (data == null) { dataManager.writeData("Dados sigilosos".getBytes(), "TesteApp", "Secreto", Boolean.FALSE, Boolean.TRUE); } else { msg = new String(data); logger.info("Dados recuperados: " + msg); } System.out.println("Foram encontrados: " + dataManager.listObjects().size() + " objetos"); for (Object o : dataManager.listObjects()) { System.out.println(o); System.out.println("-------"); } dataManager.closeSession(); } else { logger.warning("Token não conectado!"); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (conn != null) { conn.close(); } } catch (TokenException e) { // Nada } }
Agora é só utilizar. O próximo passo é criar uma aplicação gráfica para manipular tokens e seus dados. Quem tiver interesse é só me avisar.
Muito Bom Thiago.. parabéns !
jr
Olá Thiago,
Estou construindo uma ferramenta para assinatura digital multi-os, usando certificados A3, assim que finalizá-lo eu mando para você publicar.
Um abraço
Valeu
Olá Thiago, vc diz no principio do teu site que "Precisando é só avisar!", pois eu te avisar agora, hehe...
Estou trabalhando num projeto público que evita que mães carentes precisem ir ao cartório para registrar seus filhos, fazendo o registro na própria maternidade.
A maternidade digitaliza os documentos da mãe e os envia ao cartório para análise.
Estes documentos enviados são assinados digitalmente, por isso a necessidade de um assinador digital.
Minha pergunta é, como relaciono o seu código acima, para realizar a assinatura de um arquivo no formato PKCS#7.
Se vc tiver uma idéia ou qualquer luz que seja, por favor me envie.
Muito obrigado
Só um detalhe, todo o código para validação de um certificado digital X509 eu já tenho pronto, como lhe disse finalizando eu mando tudo para vc compartilhar com galera.
Um abraço
Você vai utilizar essa classe para assinar:
http://download.oracle.com/javase/6/docs/api/java/security/Signature.html
Utilize o método getInstance e depois o initSign passando a chave privada do token. Utilize o método update para colocar os dados a serem assinados e o método sign para pegar a assinatura.
Para verificar a assinatura é só utilizar o método verify passando a assinatura.
Vou ver se consigo criar um post disso em breve.
Olá Thiago,
Coloquei estou com o seguinte erro. Na hora que ele faz o pkcs11Module = Module.getInstance(libraryPath); ele lança uma exceção: java.io.IOException: Não foi possível encontrar o procedimento especificado.
Sabe o que pode ser?
Obrigado.
Olá Flávio. Pelo erro você está em ambiente Windows e você tem duas possibilidades: ou a versão da DLL utilizada não é compatível com seu Windows ou o software não está encontrando as DLLs e suas dependências. Você pode me enviar o código utilizado e onde estão localizadas as DLLs? Seu windows é 32 ou 64 bits?
Fala Thiago! Consegui resolver o problema!
Muito Obrigado pelo tutorial!
Flávio Mendes, como você conseguiu resolver esse problema ?
Ele conseguiu e me respondeu por e-mail. A dll dele não estava sendo encontrada no sistema. Ele colocou na system32 e achou.
Cara, estou com outro problema. Uma vez que o o keystore é carregado com a senha certa, posso colocar a senha errada que ele continua como se estivesse válido. Sabe o que pode ser?
Já tentei dar um
Security.removeProvider("SunPKCS11-eToken");
e um
Security.getProvider("SunPKCS11-eToken").clear();
e não adianta....
Obrigado!
Você está dando um close na session?
Olé Thiago (Xará), eu tenho uma pergunta sobre essa solução, ela serve tanto para sistemas web e desktop?
Desktop, mas utilizei em um servidor web :).
Dependendo de como você for utilizar serve para sistemas web também!
ola, estou tendo um problema na hora de ele ler a DLL no sistema, e nao estou conseguindo identificar o erro, vou passar o ST, se vc tiver um luz, obrigado.
trying to connect to PKCS#11 module: C:\Users\luciano.silva.ext\Downloads\iaikPkcs11Wrapper1.2.17\native\platforms\win32\release\pkcs11wrapper.dlljava.io.IOException: Não foi possível encontrar o procedimento especificado.
at iaik.pkcs.pkcs11.wrapper.PKCS11Implementation.connect(Native Method)
at iaik.pkcs.pkcs11.wrapper.PKCS11Implementation.(PKCS11Implementation.java:166)
at iaik.pkcs.pkcs11.wrapper.PKCS11Connector.connectToPKCS11Module(PKCS11Connector.java:75)
at demo.pkcs.pkcs11.wrapper.SimpleTest.(SimpleTest.java:112)
at demo.pkcs.pkcs11.wrapper.SimpleTest.main(SimpleTest.java:131)
Enviado às 17:48 de quarta-feira
Olá Thiago,
bom artigo, parabéns.
Sabe se é possível carregar e ler a livraria (libeTPkcs11.so) usar da memoria em vez de ser de uma path no disco?
Originalmente ela se encontra dentro do JAR que vou distribuir ao meu cliente, e não quero copiar para o disco.
Cumps
É só você carregar o arquivo assim getClass().getResourceAsStream("libeTPkcs11.so")
ola estou com um enorme problema , o token foi instaldo normalmente A3 mas , foi inicializado e perdeu os dados existentes nele , oq posso fazer para recuperar sou leiga no assunto .. fico no aguardo
attt
Infelizmente não há como você recuperar.
Caro, Thiago, sinto estar com uma pergunta de apenas duas variaveis:
Demiti minha secretaria que fazia as notas da empresa, na verdade peguei ela roubando. Fui entao emitir uma nota fiscal, ao assinar com um securyto token A3, inseri a senha errada, acredito que ela pos na agenda a senha errada de propósito; tenho como resfazer esta senha sem perder os dados?
Infelizmente não da maneira convencional
eu tenho o sistema de nfe.. sou de sc..
quando eu vou no botão assinar nota fiscal, da um erro informando que nao tenho a aetpkss1.dll
nao sei como instalar novamente esta dll, já pocurei por tudo. podes me ajudar?
Estou tentando emitir ums NFe mas quando mando a silicitacao da nota me da a seguinte mensagem abaixo. O que devo fazer para solucionar esse caso?
estou usando o windows 7 64bits
Exceção no java.lang.UnsatisfiedLinkError thread "main": C: \ Windows \ System32 \ j2pkcs11 . dll: Não é possível carregar IA 32 bits dll em uma plataforma AMD de 64 bits.
Você precisa utilizar uma dll 64 bits ou rodar a aplicação em modo 32 bits.
thiago ve se vc pode me ajudar como faço com o tokem a3 ele não deixa eu exporta a chave privada tem como driblar isso? se sim me ajuda dependo muito para os meus clientes da Área de contabilidade!
Muito Bom este post .. Parabéns !!
Thiago, parabéns pelo artigo. Venho do c# e sou novo no java. Estou precisando de uma solução deste tipo, vc teria ou poderia compartilhar algum tipo de interface gráfica para manipular tokens do exemplo que vc publicou acima? Grato desde já.
Até que é uma boa ideia.. pra fazer é simples. Você acha que faria sucesso?
Concerteza, principalmente para os usuários que não tem tanta afinidade ainda com o java, ajudaria a compreender melhor o funcionamento como um todo da sua idéia. Você tem meu apoio!
Estou envolvido em um desafio onde o que o Sr. Cleiton mencionou, interface gráfica para manipular tokens, seria de suma importância para o sucesso do projeto. Fico no aguardo de possíveis soluções e pode contar com meu apoio também.
Thiago beleza?
A ideia seria a mesma para a manipulação de um safenet? Abraços
Sim
Boa noite Thiago,
Infelizmente, por falta de experiencia eu apaguei os dados do meu Token, você pode me informar se existe uma maneira para eu recuperar os dados?
Desconheço, você sabe qual é o modelo dele?
Olá thiago, eu tenho um certificado A3 com token modelo GD versão G2... esta tudo quase ok, o token informa possuir o certificado nelo, mostra o nome completo data de criação e validade findando em 23/10/2017.... porém quando tento assinar um documento ele informa: NÃO EXISTE CHAVE PRIVADA ASSOCIADA AO CERTIFICADO..... assim acho que de alguma forma apaguei a chave privada de dentro do token....sou recem formado em tecnologia pela UFF e aprendi a linguagem Java.... existe alguma forma de recuperar este arquivo de chave privada dentro do token?? não preciso extrai-lo de lá, só quero que ele volte a funcionar..... mesmo que seja usando programas em java se houver alguma forma agradeço se me ajudar, já tentei recuperadores como easus mais eles não reconhecem o token, apenas o hd da máquina e pen drives... aff.... sem mais agradeço desde já, meu e-mail: cadanderson@hotmail.com, ele tb é facebook..... valeu
Olá Thiago. Tenho uma aplicação em java que se autentica usando o certificado digital e assina documento usando o certificado digital tb. Até ai tudo certo. Mas, uma vez que eu digito a senha do token e assino um documento, ele (o driver, o browser, não sei ) não pede mais a senha. Até que eu remova o token e espete ele de novo ou passe um determinado tempo. Tem como agente fazer com que a senha sempre seja exigida?
Obrigado.
Desconheço, por que é política do browser. Se fosse uma aplicação externa é até possível.
Thiago,
Para fazer um simples uploads/importação de arquivos certificados para um token, é necessário utilizar a PKCS#11 Provider?
Seguindo a partir do exemplo em seu post, o método writeData não seria possível?
Abs,
Não é necessário utilizar o provider.
Olá Tiago,
Tentei fazer a conexão com o token mas está dando o seguinte erro:
The specified procedure could not be found
Você saberia me dizer o que seria ? Pelo que entendi ele encontra a dll mas não consegue ler os métodos dentro dela. Idéias ?
Pode ser a versão da dll. Você tem como me enviar?
terias como me add no skype tecnologia_
Olá Thiago,
Estou tendo um problema e acho ser a DLL esta gerando um
"java.io.IOException: %1 não é um aplicativo Win32 válido."
o que eu faço para resolver
já achando ser um problema da DLL fiz o que você disse em umas das suas respostas colocando a dll dentro da system32, porem não deu nada
Belgrano de Ivanhoé troca de DLL. usa a DLL 64.
Ja tentei de tudo Thiago. Fiz um classe de teste para chamar o ETokenConnection como o código baixo:
conn = new ETokenConnection("pkcs11wrapper.dll", "C:/libs/assinador/pkcs11wrapper.dll");
mas na linha abaixo da o erro "Não foi possível encontrar o procedimento especificado"
pkcs11Module = Module.getInstance(library, path);
Windows 8 64bits, e estou utilizando a versão 1.3 conforme versao disponível no site.
não sei mais o que fazer. 🙁
vi seus posts mas não encontrei nenhuma solução. será uqe estou esquecendo de algo?
subi todos os jars para o path da aplicação:
iaikPkcs11Wrapper.jar
iaik_jce_full.jar and others.
Você tem uma ideia do que pode estar ocorrendo
utilizo o mesmo token mencionado por você da Certising.
Tiago,
Vc poderia me passar um telefone de contato ?
Estou trabalhando em um projeto onde preciso de uma applet java para assinar documentos em PDF com certificado A3.
Pode me ajudar ?
Abraço
Milson
Thiago, você sabe como acessar o token se estiver dando senha inválida? Todos os dados do token não estão perdidos, esqueci a senha e ainda tenho 4 tentativas de senha, então queria saber se dá para entrar no token?
Você precisa recuperar os dados ou a assinatura?
Na verdade eu quero usar o certificado digital que está no token, mas o software eToken que está instalado não está reconhecendo a senha, mas a senha eu não troquei, eu vi que está dando este tipo de problema por aí, com outras pessoas reclamando no Reclame Aqui sobre isso. Tem jeito de entrar? Preciso acessar o site da Receita Federal com ele.
Infelizmente você terá que solicitar outro certificado.
Sera que esta usando teclado ingles ao inves de portugues ou vice-versa, ou ainda maiuscula ao inves de minuscula ou vice-versa. Ja aconteceu algo semelhante comigo
Fala irmão, blz.
gostaria se posso usar esse metodo para ler informações via browser, para ler os dados do token na máquina de que estiver acessando meu site.
Bom dia, gostaria de saber se existe a possibilidade de obter a informação da quantidade de vezes que o token foi utilizado? Assim consigo avisar a pessoa que o token vai ser bloqueado em X tentativas. Obrigado.
Thiago, Boa tarde. Parabéns pela solução. Estou utilizando ele para ler os dados do token, entretanto estou com um problema no momento da leitura. Sempre está retornando null. O que vem a ser o application? Como eu consigo pegar os objetos do token? Aguardo resposta
É possível clonar um token A1 ou A3? Se sim qual aplicativo mais indicado.
A1 é possível... A3 é bem difícil
Olá Thiago,
Primeiramente, parabéns pelo post! Ele me ajudou muito. Além disso, eu gostaria de fazer algumas contribuições para esse ele:
(1) Na linha 73 da primeira classe (ETokenConnection), não seria:
(slots.length > 0) em vez de (slots.length < 0)?
(2) Além disso, nem sempre o primeiro slot está com o certificado digital (eu quebrei a cabeça para descobrir isso). Pelo o que eu pude ver, o certificado pode ficar em outro slot no Alladin eToken. Por exemplo, o certificado que eu estou usando fica no slot 4.
Eu estou reforçando isso, porque o seu segundo código verifica apenas o primeiro slot para saber se conectou corretamente ou não. Se me permite, eu sugiro que o programador imprima todos os slots em vez de verificar apenas o primeiro. Por exemplo:
conn = new ETokenConnection("/usr/lib/libeTPkcs11.so");
Slot[] slots = conn.getAllTokenSlots();
for( int i = 0 ; i < slots.length ; i++ ){
logger.info( "Slot " + i );
logger.info( slots[ i ].getSlotInfo().toString() );
}
Isso vai dar uma melhor noção se está conectado ou não. Além desse método, o programador pode utilizar a ferramenta PKCS11Explorer para descobrir o slot do certificado digital.
obs.: eu entendo que você fez isso para simplificar. Eu coloquei esse texto para as pessoas não passarem pelo mesmo problema que eu.
No mais, o post ficou muito interessante. Parabéns, novamente!
Abs,
Vc está certo! É isso mesmo. Muito obrigado.
Olá Tiago, quero assinar digitalente um documento utilizando a certificação A3, minha aplicação é web e gostaria que meu cliente te assinasse via Android um tablatura com a leitora espetada nele é possível?
Sim.. é possível!
Olá thiago, eu tenho um certificado A3 com token modelo GD versão G2... esta tudo quase ok, o token informa possuir o certificado nelo, mostra o nome completo data de criação e validade findando em 23/10/2017.... porém quando tento assinar um documento ele informa: NÃO EXISTE CHAVE PRIVADA ASSOCIADA AO CERTIFICADO..... assim acho que de alguma forma apaguei a chave privada de dentro do token....sou recem formado em tecnologia pela UFF e aprendi a linguagem Java.... existe alguma forma de recuperar este arquivo de chave privada dentro do token?? não preciso extrai-lo de lá, só quero que ele volte a funcionar..... mesmo que seja usando programas em java se houver alguma forma agradeço se me ajudar, já tentei recuperadores como easus mais eles não reconhecem o token, apenas o hd da máquina e pen drives... aff.... sem mais agradeço desde já, meu e-mail: cadanderson@hotmail.com, ele tb é facebook..... abraços , valeu
Olá Thiago, posso tirar uma informação com você.
Tenho um certificado digital instalado no meu smartcard do tipo A3 e comprei um token GD.
É possível fazer uma cópia desse certificado do SmartCard para o token?
Que "software" é usado para gravar informações dentro de um token?
Gostei muito meu amigo da dica , pois tenho um certificado digital e gostaria de ter uma copia de segurança o processo e o mesmo
Olá Thiago, obrigado pelo artigo, muito interessante. Estou tentando criar uma aplicação simples em java web, onde o login seria através do token A3 da certisign. A lógica a utilizar seria essa mesma que você apresenta no artigo? Se possível me ajudar com algum material, estarei agradecido.
Cara, parabéns! Obrigado por compartilhar seu conhecimento!
Thiago, tenho um token desse com certificado digital da OAB e preciso cloná-lo para utilizar em outra máquina, mas não entendo nada de programação. Me ensina um passo a passo aí para leigos como eu. Meu email é serggiobarata@gmail.com, prefiro.
Abraço.
Clonar token só é possível de maneira simples se o certificado for A1, senão eu creio que seja ilegal.
o meu é A3
boa noite vc tem algum canal no youtube
Tenho mais não coloco nada de programação nele
Estou desenvolvendo uma aplicaçao para trafegar informaçao com certificaçao digital
a aplicaçao funciona perfeito no windows normalmente agora estou querendo apliar o meu negocio para funcionar no linux e trabalhar com mas segurança fazer tambem buscando o token em um servidor pois ele so funciona na maquina onde esta espetado o token
estou querendo ver com voce por onde posso comerça..??
Como você fez no windows? Qual linguagem?
Bom dia como fazer uma aplicação gráfica para manipular tokens no linux.?
É só utilizar essa classe que fiz no artigo e criar uma aplicação gráfica para isso. Fiz algo parecido, mas uma aplicação web para um servidor de tokens e criptografia para uma grande empresa no segmento bancário. Todos os dados delas precisavam ser criptografados com dois tokens dado à indivíduos diferentes com senhas diferentes em uma máquina isolada, mas com acesso à um serviço de criptografia.