Biometria básica com o U.are.U 4000B (Digital Persona / Crossmatch)
Escrito por Carlos B. Feitoza Filho | |
Categoria: Artigos | |
Categoria Pai: Addicted 2 Delphi! | |
Acessos: 21041 |
Há algumas semanas atrás eu vi no Delphi Experts alguém com uma dúvida sobre como realizar biometria utilizando um leitor de impressão digital e uma das coisas que me chamou atenção foi que o autor da publicação foi categórico ao dizer que toda leitura gerava dados distintos. Como eu nunca tive contato com esse tipo de equipamento, aquilo me soou estranho. Eu imaginava que o resultado da biometria para uma pessoa sempre era o mesmo, mas eu, claro, estava enganado, bem como algumas das pessoas que responderam tentando ajudar e achavam o mesmo que eu.
Não sei que fim levou a publicação. Não sei se o autor conseguiu resolver seu problema. Eu não tinha um leitor biométrico para testar e sendo assim deixei isso no rol de coisas que eu nunca saberia responder, mas eis que o destino colocou um leitor no meu caminho, claro, a primeira coisa que fiz foi tentar aprender a usá-lo!
Trata-se de um leitor biométrico da Digital Persona (agora conhecida como Crossmatch). O modelo é o U.are.U 4000B e eu já vi esse mesmo leitor em muitos estabelecimentos, portanto eu o considero um leitor bem popular. A Unimed Recife, por exemplo, utiliza esses leitores para autenticar os seus clientes e ele funciona perfeitamente.
Os exemplos e definições encontrados neste artigo levam em conta este leitor específico. Outros leitores podem funcionar de forma diferente, mas imagino que, devido a popularidade deste leitor, os conceitos e exemplos aqui apresentados servirão como base para utilização de qualquer leitor de impressões digitais.
O que é biometria?
Este artigo não tem intenção de ser maçante, expondo definições que podem ser facilmente encontradas na Internet, mas acho que é importante que eu defina este conceito do ponto de vista do programador e não do ponto de vista acadêmico (generalizado). Do ponto de vista do programador, biometria é:
Obtenção de características físicas (dados biológicos) de uma pessoa e que tem por finalidade a identificação e a individualização da mesma
O processo de biometria transforma dados biológicos crus em números, de forma que se possa, posteriormente, utilizando funções estatísticas, definir se um conjunto de dados pertence ou não a uma determinada pessoa. Apesar de a definição parecer complexa a primeira vista, ela fará sentido à medida que você for lendo este artigo. A palavra-chave aqui é estatística. Lembre-se dela sempre que algo parecer estranho e você entenderá.
Register, Verify, Samples & Template
O processo de captura de uma impressão digital com o intuito de cadastro se chama Register (ou registro) e o processo de captura de uma impressão digital com o intuito de verificação apenas se chama Verify. Ambos os processos lêem uma impressão digital a partir do leitor, no entanto, o propósito de registro faz isso 4 vezes em sequência, ou seja, é solicitado que o indivíduo coloque e remova seu dedo do leitor quatro vezes e o motivo disso não é chatear o cliente. Lembra da estatística que eu mencionei anteriormente? A leitura quádrupla tem tudo a ver com ela.
Considere que nosso corpo é uma máquina analógica e como tal é IMPROVÁVEL que o indivíduo consiga posicionar um dedo em um leitor exatamente da mesma forma toda vez, e isso inclui a inclinação do dedo, a pressão na área do leitor, a presença de sujeira ou de alguma lesão na área da digital, dentre outros fatores.
A fim de resolver os problemas decorrentes da impossibilidade de se obter duas leituras de um mesmo dedo exatamente iguais, são feitas 4 leituras sequenciais. Cada leitura se chama sample (amostra) e ao obter a quarta amostra, a API do leitor, utilizando métodos estatísticos (desvio padrão), é capaz de gerar um template (modelo).
Na estatística, quanto mais amostras se tem, mais perto da realidade são os resultados. Considerando que, computacionalmente falando, uma impressão digital gera uma imagem simples, ficou determinado que a obtenção de quatro amostras seria suficiente para que o modelo obtido seja considerado como "a representação básica de minha impressão digital".
Em suma, quatro amostras de dados biométricos se transformam em um dado consolidado chamado modelo (ou template) que é um array de bytes e pode ser salvo juntamente com o registro de um usuário a fim de identificá-lo posteriormente no procedimento de verificação. Toda vez que se faz a leitura quádrupla um modelo diferente é gerado, mesmo que estejamos lendo o mesmo dedo de uma mesma pessoa. Isso acontece por motivos já mencionados anteriormente.
Neste momento você deve estar se perguntando, como então eu posso identificar uma pessoa, se cada leitura de digital gera dados diferentes? A resposta para essa pergunta vai ser reveladora e merece um tópico à parte.
Como é feita a verificação (ou match) de uma impressão digital?
Muita gente, e eu me incluía nesse rol, acredita que ao ler uma impressão digital, uma espécie de hash único e imutável é obtido e que com esse hash eu posso identificar completamente uma pessoa. Sim, isso seria fantástico, mas não é desse jeito que acontece. Como foi dito anteriormente, cada leitura biométrica é diferente por conta de ser improvável que a condição de um dedo seja rigorosamente a mesma entre leituras, em outras palavras, o Template final obtido no Register será sempre diferente da Sample obtida no momento do Verify.
Como se pode observar, nós temos dois dados distintos que precisamos comparar a fim de considerar (ou não) que uma impressão digital seja de uma determinada pessoa. A palavra-chave agora é "considerar", ou seja, não temos como chegar a uma certeza de 100% (0% de erro), mas, utilizando desvio padrão (estatística) é possível determinar que uma impressão digital obtida pertence a uma pessoa específica, com uma precisão aceitável (baixa margem de erro).
É assim que funciona a verificação de uma digital, mas não se preocupe. Você não precisa saber estatística ou conceitos mais complexos a fim de realizar a verificação de uma impressão digital. O SDK do leitor possui bibliotecas (ActiveX/COM) que fazem todo o trabalho de um papiloscopista.
Mão na massa
Vou explicar apenas as partes principais do processo de registro e verificação. Para maiores detalhes, abra o projeto anexado a este artigo. Antes de começar a trabalhar, baixe o SDK do leitor biométrico. O link para o zip contendo os drivers também está anexado a este artigo e dentro dele você vai encontrar, além de uma pasta Docs que contém um PDF com o manual de utilização das bibliotecas ActiveX, duas pastas, uma RTE e outra SDK. Para desenvolver e utilizar o leitor você deve usar o instalador contido na pasta SDK. Nos seus clientes finais você deve usar o instalador contido na pasta RTE (Runtime Environment) o qual vai permitir apenas o uso do leitor biométrico, instalando e registrando as bibliotecas ActiveX necessárias.
Após instalar o SDK você precisaria importar as bibliotecas ActiveX no Delphi, de forma a poder começar a trabalhar com os componentes que servirão para manipular o leitor. Precisaria, porque eu já fiz isso por você, anexando a este artigo o link para um zip contendo um pacote (BPL) que você deve instalar no Delphi. Este pacote foi desenvolvido em Delphi XE5, mas pode ser usado em outros Delphis. Caso seu Delphi seja muito antigo, talvez você precise recriar este pacote de instalação, importando cada uma das bibliotecas ActiveX do leitor e isso foge ao escopo deste artigo, logo, vou considerar que você sabe como instalar componentes e importar bibliotecas ActiveX no Delphi. Caso precise de informações sobre instalação de componentes, você pode ler o artigo "Entendendo a instalação de componentes". Caso precise de ajuda com a importação de bibliotecas ActiveX e Type Libraries, dê uma olhada no artigo "Como validar um XML com um XSD usando o Delphi?". No final dele existe um guia de como fazer a importação da biblioteca MSXML. O procedimento é o mesmo para qualquer biblioteca.
O Registro
Para realizar o cadastro de uma digital, precisamos ativar o leitor no modo (ou propósito) de registro. Ao iniciar neste modo, o leitor vai aguardar um dedo. Quando ele lê um dedo, um evento TDPFPCapture.OnComplete é disparado, indicando que a leitura de uma amostra foi realizada. Veja o código do manipulador do evento TDPFPCapture.OnComplete.
procedure TFormRegister.DPCAComplete(ASender: TObject;
const ReaderSerNum: WideString;
const pSample: IDispatch);
begin
DPFE.CreateFeatureSet(pSample,DataPurposeEnrollment);
DPEN.AddFeatures(DPFE.FeatureSet);
if DPEN.TemplateStatus = TemplateStatusTemplateReady then
begin
FTemplate := SerializeTemplate(DPEN.Template as IDPFPTemplate);
end;
end;
Na linha 5 estamos criando um conjunto de características a partir da amostra obtida (pSample). O propósito está explícito no segundo parâmetro do método TDPFPFeatureExtraction.CreateFeatureSet: DataPurposeEnrollment, isto é, propósito de cadastro (Enrollment = inscrição). Esta linha portanto diz: "crie um conjunto de características a partir da amostra obtida para ser usado no procedimento de cadastro de uma impressão digital".
Na linha 7 estamos adicionando o conjunto de características obtido, usando o método TDPFPEnrollment.AddFeatures. O parâmetro único deste método é o conjunto de características disponíveis em TDPFPFeatureExtraction.FeatureSet. Esta linha diz: "adiciona esse conjunto de características ao componente responsável por criar o template consolidado".
Na linha 9 estamos verificando o status de criação do template consolidado, comparando a propriedade TDPFPEnrollment.TemplateStatus com a constante TemplateStatusTemplateReady. Quando TDPFPEnrollment.TemplateStatus = TemplateStatusTemplateReady, significa que obtivemos amostras suficientes e que o template consolidado está pronto para ser salvo em algum lugar (banco de dados, por exemplo).
Na linha 11 estamos serializando o template consolidado (TDPFPEnrollment.Template). A serialização que eu usei foi simplesmente pegar cada elemento de Template (que é um array de bytes), converter para string e usar como separador o ; (ponto-e-vírgula), o que gera no final algo como 0;11;23;234;250;111... e pode ser facilmente salvo em um banco de dados em um campo blob, clob ou text. Eu não aconselho usar varchar, porque a string serializada é bem extensa e, dependendo do banco de dados, podem haver limitações ao usar varchar, portanto, use um tipo de dado que comporte uma grande quantidade de texto (cerca de 4K). Ao obter o template serializado você já pode salvá-lo no banco de dados, associado ao registro de algum usuário.
A Verificação
O processo de verificação é feito de forma semelhante ao processo de captura para registro de uma digital, a diferença é que não precisamos obter várias amostras e sim, apenas uma, ou seja, repetindo o que já foi dito antes, quando o leitor lê um dedo, um evento TDPFPCapture.OnComplete é disparado, indicando que a leitura de uma amostra foi realizada. Veja o código do manipulador do evento TDPFPCapture.OnComplete:
procedure TFormVerify.DPCAComplete(ASender: TObject;
const ReaderSerNum: WideString;
const pSample: IDispatch);
var
VerificationResult: IDPFPVerificationResult;
begin
DPFE.CreateFeatureSet(pSample,DataPurposeVerification);
DPCA.StopCapture;
VerificationResult := DPVE.Verify(DPFE.FeatureSet, (UnserializeTemplate(FTemplate) as IDispatch)) as IDPFPVerificationResult;
if VerificationResult.Verified then
ShowMessage('Usuário identificado')
else
ShowMessage('Usuário não identificado');
end;
Na linha 7 estamos criando um conjunto de características a partir da amostra obtida (pSample). O propósito está explícito no segundo parâmetro do método TDPFPFeatureExtraction.CreateFeatureSet: DataPurposeVerification, isto é, propósito de Verificação apenas, que instrui o componente de captura a realizar apenas uma captura, e não múltiplas, como acontece no registro. Esta linha portanto diz: "crie um conjunto de características a partir da amostra obtida para ser usado no procedimento de verificação de uma impressão digital".
Na linha 9 estamos desativando o sistema de captura, de forma que, se um usuário remover e recolocar novamente o dedo no leitor o evento TDPFPCapture.OnComplete não seja disparado novamente, pois só precisamos de uma leitura para fazer a verificação.
Na linha 11 fazemos duas coisas. Primeiro estamos desserializando o template que veio do banco de dados. Na nossa etapa de registro o template serializado foi colocado no campo FTemplate e em seguida salvo no banco de dados. Nesta etapa de verificação o processo é inverso. Unserialize(FTemplate) realiza esta tarefa transformando a string contida em FTemplate novamente em um array de bytes. Após obter o array de bytes que representa a impressão digital salva no banco de dados, nós o usamos como segundo parâmetro do método TDPFPVerification.Verify. O primeiro parâmetro deste método é o conjunto de características obtido a partir da amostra que acaba de ser lida (TDPFPFeatureExtraction.FeatureSet) e que foi criado na linha 7. O resultado da verificação realizada é posto na variável VerificationResult. É necessário agora eu abrir um pequeno parêntese para fixação de algo importante.
Antes de realizar a leitura da impressão digital com o intuito de verificação de identidade, precisamos obter a partir do banco de dados o template da impressão digital salvo anteriormente. Esse template será comparado com a amostra obtida na leitura, a qual verificará se aquela pessoa é quem ela diz ser. Em suma, antes de realizar a verificação de uma impressão digital, a pessoa que está tentando validar sua identidade precisará informar quem ela é, por meio de um nome de login, um CPF ou mesmo uma matrícula, assim, o sistema obterá o template do registro do usuário e poderá comparar com a amostra obtida na leitura. Muita gente acha que, por exemplo, para conceder acesso a determinada pessoa, bastaria que essa pessoa colocasse seu dedo no leitor e automaticamente o sistema saberia quem ela é, liberando (ou não) o acesso a algum recurso. Apesar de isso ser perfeitamente possível, é preciso salientar que não há como realizar uma consulta ao banco de dados na forma "select * from usuario where digital = digitalcapturada", pois como eu disse anteriormente, ao menos com este leitor (U.are.U 4000B), uma digital capturada nunca é igual, mesmo que você esteja lendo o mesmo dedo de uma mesma pessoa, ficando a cargo da API do leitor, por meio de comparações estatísticas, verificar se as digitais são da mesma pessoa. O que eu quero dizer com esse bla bla bla todo é que se você pretende realizar uma identificação completa APENAS USANDOAIMPRESSÃO DIGITALIZADA, você terá que varrer o banco de dados e comparar a digital salva em cada registro com a digital lida no momento. Se você tem cerca de 10 usuários para autenticar dessa forma, você pode carregar uma base local com as informações (e as digitais) desses 10 usuários e realizar esse procedimento de forma mais rápida, mas se você tem MUITOS USUÁRIOS, isso pode não ser viável. Fica então esta observação: uma digital substitui apenas a senha de um usuário, pois ele ainda precisa dizer quem é antes de o sistema poder liberar ou não um acesso, mediante comparação de apenas duas digitais, a lida e a salva.
A linha 13 utiliza o valor da propriedade IDPFPVerificationResult.Verified para saber se a digital realmente pertence ao usuário, finalizando o processo de verificação.
Sobre o exemplo anexado a este artigo
Como eu disse no início do artigo eu não possuo um leitor de impressão digital. Ele me foi emprestado por um amigo que precisava de uma solução supersimples para o negócio dele, a fim de capturar as impressões digitais e eu aproveitei para estudar como esse processo funciona para poder explicar para vocês. Eu utilizei neste programa de exemplo, componentes especiais que utilizam imagens PNG para deixar o visual do programa mais suave, estes componentes estão anexados a este artigo e você deve instalá-los, caso queira recompilar o exemplo. Caso seu Delphi seja mais antigo e não tenha suporte nativo a imagens PNG, você deve instalar o outro componente que fornece esse suporte (também anexado a este artigo). Se você não tiver certeza se seu Delphi suporta nativamente imagens PNG, cria uma aplicação vazia, coloca nela um TImage e tenta adicionar um PNG. Se você conseguir, seu Delphi já tem suporte a PNG nativamente, se não conseguir, instale o componente de suporte a PNG.
O exemplo pode parecer estranho e ter algumas coisas que não fazem muito sentido do ponto de vista de dados, mas isso não é culpa minha. Eu tive de seguir o modelo que me foi passado e alterei o programa para que ele, ao invés de salvar em um banco de dados, faça isso na memória (usando TClientDataSet). Eu espero que ele seja suficiente para que todos entendam como o registro e a verificação de biometria funcionam.