Autenticidade e integridade de documentos públicos

Existe uma maneira simples de garantir que um documento digital é autêntico, sem pagar para o cartório (!). É até bem tradicional, mas como não falamos muito da autenticidade de documentos públicos, poucas pessoas acabam de fato tendo consciência da sua relevância para diários oficiais, contratos, normas, estatutos, etc.

Quando falamos de documentos públicos, que estão aí disponíveis para baixar da internet, não precisamos conferir assinatura eletrônica do autor, nem chaves de segurança… Nada disso.

É uma espécie de certificado do documento, sem nenhuma outra “autoridade de certificação”, além do próprio mantenedor do documento. Se você obtém uma cópia e não tem certeza se é o documento original, então gera o mesmo certificado para a sua cópia e confere se bate com o certificado oficial.

O “gerar um certificado”, sem precisar de uma autoridade, é a mágica: fazemos um resuminho do documento, chamado hash… Suponha o documento em formato de imagem, então o tal certificado é simplesmente um número ou código resultante do processo de “resumo” da imagem:

O número final “10000000‑11011110‑…”, binário, pode ser representado de forma compacta como número decimal “128‑222‑…”, ou hexadecimal, “80‑DE‑…”. Esse processo ilustra a geração de um código hash que representa a imagem. (fonte) NOTA: este hash não é criptográfico pois não embaralha, mas ilustra bem.

O algoritmo de certificação, um tipo de função matemática conhecida como função hash critográfica (ou “algoritmo de checksum”), é também público e padronizado.

É um processo simples, centrado no uso do resultado da aplicação da função hash ao documento, apelidado de digest (ou “valor do checksum”). 
 digest = valor_do_checksum = fução_hash(documento)

Esse digest fica registrado em diário oficial ou algo similar que testemunhas possam acessar, com direito de testar e guardar uma cópia de segurança.
O processo é bastante confiável, pois garante que o digest seja único (praticamente sem risco de repetição), tendo se baseando em avanços relativamente recentes (últimas 3 décadas) da Matemática Discreta e da Criptografia Computacional.

Na prática esses são os passos:

  1. O documento oficial (arquivo DOC, PDF, HTML ou outro) é finalizado e registrado, e a função hash(documento) é calculada resultando num digest que também é registrado.
  2. Publica-se no Diário Oficial digital o documento e o seu digest.
  3. As partes interessadas baixam o documento para backup e para conferir, em cálculo independente (auditoria), se o mesmo digest é obtido… Atestando, dentro de certo prazo, o que foi publicado.
  4. Uma vez auditado pela consulta pública, registra-se oficialmente em bancos de dados e papel (ex. cartório) apenas o digest, como recurso adicional e barato de preservação e segurança.

Passado algum tempo, se alguém desconfia que o documento oficial foi adulterado, basta conferir o digest: se não bater significa que, certamente, foi adulterado. O backup (em posse da testemunha do passo 3) que se reclama como fiel, e que apresentar o mesmo digest, será eleito como prova jurídica. Confira no final a “Paródia dos poemas perdidos”, que ilustra esse processo.

Nota: pela legislação brasileira, a prova jurídica fica reforçada quando o DVD contendo os documentos, ou impressão do material, se encontra fisicamente depositado na Fundação Biblioteca Nacional.

Do dígito verificador às hashes criptográficas

Todo mundo já viu nos códigos de documento bancário ou de identidade, um tracinho no final, seguido de um ou dois dígitos. Por exemplo o nosso CPF é um código de 9 dígitos na forma DDDDDDD-DD, onde os primeiros 7 dígitos são o seu número de fato, e os dois últimos 2 são informação redundante, são os chamados dígitos de verificação. Eles são o resultado de um cálculo maluco, também conhecido como soma de verificação (checksum), que embaralha, transforma e sorteia amostras do número, para transformar em algo mais compacto porém representativo.

Antigamente como era frequente a cópia manual, digitando-se o código, os dígitos de verificação permitiam conferir se houve erro durante a digitação.

Posteriormente, na telecomunicação digital, onde pacotes de informação eram transmitidos sob forte ruído, era necessário conferir se não houve falha de transmissão… Se houvesse falha o pacote era ignorado e um novo solicitado. Para conferir usavam estratégia parecida com a do CPF: ao invés de calcular o dígitos de verificação de um número, calculava-se os “dígitos verificadores” de uma mensagem, conhecido em inglês como message digest.

Entre os matemáticos o nome genérico dessas funções malucas que transformam um número enorme, de muitos dígitos, em poucos dígitos; ou uma mensagem inteira, em alguns caracteres; é “função hash”. Na computação, em sistemas de arquivos, é mais conhecida como checksum.

Função hash que mapeia nomes para inteiros de 0 a 15. Existe uma colisão entre as chaves “John Smih” e “Sandra Dee”.

Resumindo: a função hash é uma função que consome certa quantidade de dados (uma palavra, uma mensagem ou um documento), transformando-os em uma representação compacta (digest) daquele dado.

A partir da década 1990 um tipo especial, as chamadas funções hash criptograficas, passaram a ganhar maior atenção e se tornar essenciais para segurança digital. Elas possuem algumas características que tornam as funções hash mais atraentes nas suas aplicações:

  • são muito boas de amostrar e embaralhar: qualquer diferença na mensagem causa uma diferença nas digests resultantes.
  • são boas e grandes suficientes para garantir que não hajam colisões, ou seja, existe baixo risco de que duas mensagens diferentes resultem em mesmo digest.

Padronização das funções hash

Uma das chaves para a garantia de longo prazo e consenso em torno dos certificados baseados em hashes, é a padronização das funções de hash.

Hoje os padrões mais utilizados, cada qual com suas aplicações, são: CRC, MD5, SHA1, família SH2 e família SHA3. Além do algoritmo das funções, 
o tamanho do resultado (tamanho do digest) é também padronizado. 
Os padrões mais conhecidos são 8 bits, 32 bits, 120 bits, 256 bits e 512 bits. No caso das hashes criptográficas, precisando de tamanhos intermediários pode-se truncar no tamanho desejado sem perda das suas propriedades.

Esta lista de hashes-padrão está “sempre” (a cada 5 ou 10 anos) recebendo novas funções, para acompanhar a evolução do poder computacional e do volume de documentos que produzimos. As funções CRC, MD5 e SHA1 ainda são ótimas para correção de erros (ruído) em telecomunicação, mas deixaram de ser válidas para a autenticidade ou criptografia de senhas.


Paródia dos poemas perdidos

Trecho do único pedaço de papel escrito a mão por Carlos.

Carlos D. A. guardava todos os seus poemas em meio digital, no seu precioso HD Maxtor. 
Em papel, de próprio punho, registrou apenas os títulos dos poemas e o código hash de cada um.

Em uma anotação atrás da folha, Carlos indicava qual a função de hash que usou: SHA1 truncada nos primeiros 2 dígitos.

Um belo dia o HD espatifou,

E foi justamente no acidente, quando Carlos morreu.

Tudo que sobrou dos poemas de Carlos, autêntico e de autoria incontestável, foi aquela folha de papel com os títulos e os hashes, mas sem os poemas.

Alguns poemas, que recitara já bêbado nos bares, sobreviveram no boca-a-boca, e circulavam anos depois pela Internet… E, como é de se esperar, diferentes versões do mesmo poema surgiram e reclamaram para si a grife do poeta. Do poema “No meio do caminho” haviam 3 versões bem populares, elas começavam assim:

  • versão 1: No meio do caminho havia uma (…)
  • versão 2: No meio do caminho, tinha uma (…)
  • versão 3: No meio do caminho tinha uma (…)

Qual seria a versão correta, o texto original escrito de fato por Carlos?

Alguém lembrou do caderno com os títulos e os hashes de cada poema, então fez o teste:

Conclusão: a versão original é a v3! Confira na tabela manuscrita dos títulos.


JARGÃO HASH: GLOSSÁRIO DE SINÔNIMOS

Se for buscar pela Internet, vai perceber que há uma certa confusão entre os termos checksum, hash, cryptographic hash, check digit… Talvez por se tratarem de origens históricas diferentes, tratamos da mesma coisa mas com nomes diferentes. Aí vai uma breve tabela de tradução:

  • Função hash: é a “mãe” de tudo, na dúvida fique com ela. 
    Funções padronizadas possuem nome (CRC, XOR8, MD5,etc.) e respectivo algoritmo.
  • Entrada e saída da função hash: nas discussões e aplicações mais comuns, as entradas são mensagens e as saídas são digests das mensagens. Em inglês: input message e message digest (ou simplesmente digest).
  • Função hash criptográfica: é um tipo especial que embaralha o resultado, útil para esconder senhas. Quando eficientes e padronizadas, amostrando uniformemente a mensagem e embaralhando bem, as funções acabam sendo eficientes também na garantia de autenticidade e integridade.
  • Hash da coisa” ou “hash” ou “valor do hash”: sinônimos de digest. 
    É como se fosse uma forma mais abreviada de dizer “valor da função hash aplicada à coisa”.

Esse é o jargão de referência. Aí, pelos mais diversos motivos, o jargão se diversifica… Apesar da justificativa histórica, muitos desses sinônimos foram adotados para também destacar o contexto da aplicação do hash.

  1. Autenticidade e/ou integridade de documentos. O sinônimo mais usual é checksum. “Checksum algorithm” é sinônimo de função hash; “checksum value” sinônimo de digest; “checksum input” é sinônimo de input message. “Checksum do documento” também sinônimo de digest.
  2. Integridade de números ou códigos. Usamos com mais frequência o termo “dígito verificador” (check digit no inglês), é sinônimo popular na década de 1960 para digest. 
    Na dúvida, se o input é pequeno (não um documento inteiro mas um simples número), então pode-se usar o termo.
  3. Correção da mensagem em ambientes com ruído. “Dígito corretor” é sinônimo de digest. Similarmente a dígito verificador, aplica-se a inputs pequenos, pois não se pode corrigir um documento inteiro, é preciso quebrar a mensagem em pequenos blocos de modo que a redundância possa ser aplicada para fins de correção.
  4. Criptografia de senhas, indexação de dados (vetores associativos), etc. Para todos os outros contextos os termos “hash function” e “hash value” são os mais populares. O termo digest é mais comum no contexto de criptografia, mas pode ser usado em outros contextos que os computeiros entendem.