Blog

Como provar que um documento não mudou desde a emissão.

O pedido chega assim: “quero garantir que o certificado que a gente emite não seja adulterado”.

A primeira implementação é sempre a mesma. Gera o PDF, calcula o SHA-256, guarda numa coluna. Se alguém contestar, você recalcula e compara.

Funciona contra alteração acidental. Contra o caso que motivou o pedido, não faz nada.

O buraco

O documento e o hash estão no mesmo banco, sob o mesmo controle. Quem consegue trocar um consegue recalcular o outro.

Isso não é hipótese remota. Basta uma pessoa com acesso ao banco, um script mal escrito ou uma restauração de backup errada. E, do ponto de vista de quem recebe o documento, o argumento é ainda mais fraco: por que confiar num hash que a própria empresa emissora guarda?

A pergunta que resolve o desenho, e que vale pra qualquer sistema de rastreabilidade: quem precisa verificar, e essa pessoa confia em você?

Nível 1: hash guardado

Detecta corrupção acidental e erro de processo. Verificação interna. Adversário: nenhum.

Barato e suficiente pra muita coisa. Só não venda como “à prova de fraude”, porque não é.

Nível 2: assinatura digital

Aqui entra a diferença entre integridade e autenticidade.

Hash responde “esse conteúdo mudou?”. Assinatura responde “quem produziu isso?”.

import { createSign, createVerify } from "node:crypto";

const sign = createSign("SHA256");
sign.update(canonicalBytes);
const signature = sign.sign(privateKeyPem, "base64");

A chave privada precisa estar em KMS ou HSM, nunca em variável de ambiente e jamais no repositório. O ponto inteiro do mecanismo é que só uma entidade consegue assinar, e uma chave que vaza destrói tudo retroativamente.

Com assinatura, quem recebe o documento verifica com a chave pública sem precisar chamar a sua API. Isso é um salto grande: a verificação deixa de depender de você estar no ar e de você estar sendo honesto.

O que a assinatura ainda não resolve: quando. Você pode assinar hoje um documento e dizer que ele é de ontem.

Nível 3: carimbo de tempo

Se a anterioridade importa, é preciso um terceiro que ateste o momento.

A opção formal é uma autoridade de carimbo de tempo, no padrão RFC 3161. Você manda o hash, ela devolve o hash assinado junto com a data, usando a chave dela. Em contexto onde o documento vira prova, esse é o caminho, e no Brasil ele se conecta à infraestrutura de chaves públicas oficial.

A opção barata é âncora pública: publicar periodicamente a raiz de uma Merkle tree dos documentos daquele dia em algum lugar que você não controla e que é datado por natureza. Um repositório público, um serviço de log transparente, qualquer meio com registro temporal independente.

Custo: um job de madrugada e trinta e dois bytes por dia. Ganho: qualquer pessoa confere que aquele documento existia naquela data, sem confiar no seu relógio.

O detalhe que estraga tudo

O que exatamente é hasheado.

Um PDF não é estável. Muitas bibliotecas embutem data de geração, identificador do documento e metadados que mudam a cada emissão. Regerar o mesmo certificado produz bytes diferentes, e a verificação acusa adulteração onde não houve nenhuma.

Duas saídas.

Congele os bytes: guarde o arquivo exato que foi entregue, e hasheie ele. Simples, e exige guardar o binário pra sempre.

Ou hasheie o conteúdo, não o arquivo: uma forma canônica dos dados que geraram o documento, com campos e ordem fixos, versionada. Aí o PDF vira uma renderização, e o que se prova é a informação.

A segunda é mais robusta e é a que eu escolho na maioria dos casos. Escrevi sobre a construção dessa forma canônica em system design de rastreabilidade com hash único.

O endpoint que muda o produto

Nada disso vale se a verificação for difícil.

GET /verificar/cert_2026W38_7f3a9c2e

{
  "valid": true,
  "issued_at": "2026-09-18T10:22:41.109Z",
  "anchored_at": "2026-09-19T03:00:00.000Z",
  "anchor": { "type": "public_log", "reference": "..." },
  "hash_version": "v2",
  "subject_summary": "Certificado de conclusão — turma 2026/2"
}

Um QR no rodapé do documento apontando pra essa URL transforma o mecanismo em funcionalidade visível. Quem recebe o certificado confere em cinco segundos, sem entender nada de criptografia.

Cuidado com o que a resposta revela: confirmar validade não deve expor o conteúdo do documento a quem só tem o identificador. Resuma, não detalhe.

Revogação

A parte que quase todo mundo esquece.

Documento emitido por engano, aluno que teve o certificado cancelado, contrato rescindido. O documento continua íntegro e assinado, e não deveria mais valer.

Integridade e validade são coisas diferentes. Você precisa de uma lista de revogação consultada pelo endpoint de verificação, e o resultado passa a ter três estados: válido, inválido por integridade, e revogado com data e motivo.

Sistema que só responde válido ou inválido não consegue representar o caso mais comum de todos.

O que eu decidiria primeiro

Antes de escolher biblioteca, responda três coisas por escrito.

Quem verifica: você, o titular, ou um terceiro hostil.

O que acontece se a verificação falhar: é aviso, é bloqueio, ou é disputa jurídica.

E por quanto tempo isso precisa valer: dois anos ou trinta.

A última muda tudo, porque algoritmo envelhece. Um documento que precisa ser verificável em 2050 exige plano de recarimbo com algoritmo novo antes que o atual enfraqueça. Isso não é exagero: é exatamente o que aconteceu com quem carimbou documento com SHA-1.

← Voltar pro blog