Certa vez eu precisei construir um mecanismo de autenticação usando certificados digitais. Em especial, certificados no padrão ICP-Brasil (Infraestrutura de Chaves Públicas Brasileira). Esse padrão estabelece um conjunto de normas, procedimentos e entidades que garantem a criação e validação de identidades digitais seguras, utilizando criptografia de chaves públicas. Por meio dessa infraestrutura, é possível assegurar a autenticidade das partes envolvidas em uma transação, a integridade das informações e a validade jurídica de documentos assinados digitalmente.
A própria segurança das informações transmistidas na internet é muito baseada em certificados digitais. Qualquer site que acessamos com HTTPs, as transações bancárias com PIX, a foto enviada para o instagram ou a mensagem recebida no WhatsApp, tudo isso usa em algum nível certificados digitais para garantir a segurança. Isso está bastante encrustado no dia a dia e a maioria das pessoas não percebe. Elas simplesmente fazem o que tem fazer, e toda segurança acontece.
E voltando ao ICP-Brasil, dentro desse padrão temos o e-CPF e o e-CNPJ, que servem para identificar pessoas e empresas, respectivamente. Podem ser usados para uma série de tarefas e sistemas que implementam bem oferecem grande facilidade para os usuários. Dentro do e-CNPJ há também a informação da pessoal responsável por arque certificado, alguém com vínculo com a empresa em questão. Advogados usam muito os certificados digitais para se identificar nos sistemas da Justiça Brasileira, empresas usam para emitir nota fiscal, dentre várias outras funcionalidades.
Essa troca de informações com e-CPF/CNPJ, muitas vezes, acontece de uma maneira muito parecida com o processo usado para um banco garantir que você pode fazer um PIX de maneira segura. Uma diferença imediata é que, no caso do PIX, você não precisa apresentar seu certificado e, geralmente, coloca sua senha no aplicativo para o banco saber que você, é você. Mas para o aplicativo do banco no seu celular saber que realmente está comunicando com os sistemas do banco, o banco manda o certificado, e lá tem as informações que garantem que o banco é o banco. Advogados e empresas emissoras de notas fiscais, como mencionei, usam certificados para se identificar, e nesse caso, é uma troca mútua de certificados.
Tecnicamente falando, os certificados seguem o padrão X.509 é uma especificação internacional que define o formato dos certificados digitais usados em criptografia de chave pública e privada. Ele é a base da ICP-Brasil e de praticamente toda a segurança na internet, HTTPS (repetindo), TLS e assinaturas digitais. Tudo isso é feito com operações matemáticas feitas com números extremamente grandes. Uma chave pública consegue embaralhar uma informação, mas somente a chave privada consegue desembaralhar.
Para tudo isso funcionar, a chave privada deve ser mantida em segurança. Agora, imagine que você embaralha uma informação com sua chave privada e então manda essa informação para alguém. Apenas a chave pública consegue desembaralhar aquela informação. Logo, quem tiver sua chave pública vai ter certeza que a informação veio de você. Agora imagine que alguém quer enviar uma informação que apenas você pode ler. Basta essa pessoa embaralhar a informação com a chave pública, pois ela sabe que sómente a sua chave privada vai conseguir abrir a mensagem e, como só você tem a chave privada, é garantido que a mensagem vai chegar somente em você. Isso é muito bonito na teoria, mas existem algum problemas nesses processos que não vou detalhar aqui (por exemplo, como eu sei que a chave pública que eu tenho realmente identifica você?).
Em essência, o padrão X.509 define como uma identidade digital é representada e assinada. Um certificado X.509 vincula uma chave pública a uma entidade (pessoa, empresa ou computador na Internet), permitindo verificar que aquela chave realmente pertence ao titular identificado. Assim, os certificados não são apenas arquivos com campos arbitrários, mas estruturas rigorosamente padronizadas. Essas estruturas são descritas usando ASN.1 (Abstract Syntax Notation One) e normalmente codificadas no formato DER (Distinguished Encoding Rules), uma representação binária padronizada que garante que diferentes sistemas interpretem exatamente os mesmos dados. Se fóssemos comparar com um prédio, o X.509 é o projeto estrutual, enquanto o ANS.1 é a linguagem técnica utilizada para descrever esse projeto, e o DER diz como ele vai ser executado.
Na mminha tarefa (lembra?), e peço perdão pelo textão até aqui, pois me empolguei, usei Java. É lugar comum falar que não preciso implementar todo padrão X.509 do zero. Uma boa biblioteca pra isso é a Bouncy Castle, totalmente integrada com o Java Cryptography Architecture e Java Cryptography Extension. Bastar adicionar ao projeto, carregar o certificado e extrair as informações para fazer as validações nos campos necessários. Com um ajuste ou outro, tudo se resolve.
Depois de implementar e testar, o negócio foi para produção e funcionou muito bem para todos nossos cenários. Basicamente, eu precisei pegar o CPF da pessoa e autenticar ela dentro do sistema, considerando que toda etapa de confiar no certificado digital já havia sido superada. Por exemplo, toda etapa de troca de informações, como o sistema enviar uma informação embaralhada para a pessoa usando a chave pública, a pessoa desembaralhar usando a chave privada, daí a pessoa devolve a informação embaralhando com a chave pública do sistema, e o sistema desembaralhando com a chave privada… Resumindo, todo mundo fez o cara/crachá e existe confia mútua nas informações trocadas. Tirando o detalhe que o CPF fica em locais distintos no e-CPF e e-CNPJ, o Bouncy Castle resolve toda burocracia de converter os valores codificados em DER e ASN.1. Para a aplicação, tudo era string. Em uma dessas strings, lá pela metade dela, estava o CPF. Bastava um substring e pronto.
Embora o padrão ICP-Brasil estabeleça uma série de requisitos, e a maneira como o arquivo é codificado seja regida pelo X.509, vários outros detalhes técnicos são abertos. Por exemplo, a informação do CPF fica em um local identificado com o ID 2.16.76.1.3.1, tecnicamente falando. Basta ir nesse local, pegar a string e extrair o CPF. Acontece que essa string pode estar codificada de diferentes formatos DER, e ainda estar de acordo com o qualquer um desses padrões mencionados. No exemplo do prédio, é como o projeto falar que um local precisa suportar 12 toneladas, mas não indicar se a estrutura deve ser feita somente de aço ou pode ter concreto também.
Supus que a conficação da string seria de um formato DER específico, compatível com todos os certificados que usei durante o desenvolvimento. Depois de um tempo, já com a aplicação em produção, um Senhor Fulano autenticou no sistema e aparecia o nome da Senhora Fulana. Foi um dos problemas mas sinistros que eu já tive de investigar. Depois de muito apavoro, descobri que a string era codificada de uma maneira diferente e, ao pegar o conteúdo dela, o que vinha eram os caracteres hexadecimais da informação real. E pior, muito pior, quando eu pegava a substring no local onde deveria estar o CPF, aqueles valores hexadecimas davam um CPF válido. Pasmem. O CPF da Senhora Fulana! Daí atualizei o sistema, fiz alguns updates na base de produção e a vida seguiu. Coincidências.