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.