Como saber se um PDF foi editado

O que um PDF registra sobre o próprio histórico, onde ler isso e o que cada achado prova — e o que não prova.

Um PDF não é uma fotografia de um documento. É um contêiner que só cresce por acréscimo e que guarda recibos: quando foi gravado, o que o gravou, quantas vezes foi salvo e quais objetos um salvamento posterior substituiu. A maior parte disso sobrevive à edição, porque a maioria dos editores não se dá ao trabalho de limpar. Esta página percorre as verificações à mão e depois mostra a versão automatizada.

A linguagem importa aqui. Nenhuma dessas verificações prova fraude. Elas estabelecem fatos — "este arquivo foi gravado duas vezes", "duas ferramentas diferentes mexeram nos metadados" — e fatos têm explicações legítimas além das maliciosas. A Tamperlens reporta sinais de risco, não veredictos, e você deveria fazer o mesmo ao relatar isso para alguém.

1. Leia as propriedades do documento

A verificação mais barata, disponível em qualquer leitor de PDF. No Acrobat fica em Arquivo → Propriedades; no Preview, Ferramentas → Mostrar Inspetor; num visualizador de navegador, geralmente em Propriedades do documento no menu da barra de ferramentas. Você está olhando quatro campos do dicionário Info do arquivo: /Producer, /Creator, /CreationDate e /ModDate.

/Producer é o campo interessante. Ele nomeia a biblioteca ou o aplicativo que fisicamente gravou os bytes. Um extrato bancário produzido por um sistema central de banco normalmente carrega a string de uma biblioteca de servidor — uma variante de iText, PDFlib, Prawn, wkhtmltopdf, ReportLab ou Quartz. Se em vez disso ele diz iLovePDF, Smallpdf, Sejda, PDFescape, Adobe Photoshop ou Microsoft: Print To PDF, o arquivo passou por uma ferramenta cujo propósito é alterar o conteúdo das páginas. Isso não é prova de nada, mas é um fato que merece explicação.

A ressalva óbvia: esses campos são strings. Qualquer pessoa capaz de editar um PDF pode editá-los, e alguns editores os removem por completo. Um Producer ausente já é levemente interessante por si só — geradores automáticos quase sempre se identificam —, mas sozinho é evidência fraca. Metadados são a primeira verificação, nunca a última; veja o tratamento mais profundo em forense de metadados de PDF (em inglês).

2. Compare o dicionário Info com o XMP

Quase todo PDF moderno carrega metadados duas vezes: uma no dicionário Info do trailer e outra num pacote XMP embutido — um bloco XML, geralmente armazenado sem compressão, que dá para ler num editor de texto. Uma única ferramenta gravando o arquivo uma única vez preenche os dois repositórios de forma consistente. Editores de consumo, com muita frequência, atualizam um e deixam o outro desatualizado.

Encontre o pacote XMP

strings statement.pdf | grep -A40 '<x:xmpmeta'

Depois compare, campo a campo: pdf:Producer com o /Producer do Info, xmp:CreatorTool com o /Creator, xmp:CreateDate com o /CreationDate, xmp:ModifyDate com o /ModDate. Uma divergência significa que ao menos um dos repositórios foi gravado por uma ferramenta diferente da que gravou o outro.

A versão mais forte desse achado é quando os dois repositórios discordam sobre qual ferramenta tocou o arquivo e apenas um deles nomeia um editor. O outro repositório não registrou nada, então a divergência é o único motivo pelo qual aquela ferramenta é visível. Pipelines de publicação em múltiplas etapas (app de design → distiller → pós-processador) produzem divergência simples de forma legítima e rotineira, então trate um simples descompasso como uma pergunta, não como uma resposta.

3. Interprete CreationDate e ModDate corretamente

Datas de PDF se parecem com D:20260104100200+01'00' — ano, mês, dia, hora, minuto, segundo e, por fim, um deslocamento UTC com sinal. Três coisas valem a conferência, e nenhuma delas é "o ModDate é posterior ao CreationDate", que é o caso normal de qualquer arquivo salvo.

  • ModDate anterior ao CreationDate. Impossível num gerador funcionando corretamente. Significa que os timestamps foram definidos por algo que não é o pipeline que gravou o documento, ou editados diretamente.
  • Datas no futuro. Desvio de relógio explica minutos, não meses.
  • Um deslocamento UTC impossível. Nenhum fuso horário real passa de ±14:00. Um deslocamento +25'00' é uma string digitada à mão.

Também vale notar: um documento com /ModDate mas apenas uma revisão foi reescrito por inteiro, não atualizado incrementalmente. Ambos são edições; apenas deixam rastros diferentes. A ausência de um ModDate não prova nada — ele é trivialmente removível.

4. Conte as revisões

Esta é a verificação que não depende de nenhuma string que um falsificador possa redigitar, e é o motivo pelo qual a forense de PDF funciona. O PDF suporta atualização incremental: em vez de reescrever um arquivo, uma ferramenta pode anexar ao final novos objetos, uma nova seção de referência cruzada, um novo trailer e um novo %%EOF. Os bytes antigos ficam onde estavam. Um arquivo salvo três vezes pode literalmente conter as três versões.

Conte os marcadores de fim de arquivo e os ponteiros de referência cruzada

$ grep -c '%%EOF' statement.pdf
2
$ grep -abo 'startxref' statement.pdf
118842:startxref
184102:startxref

Um único %%EOF significa que o arquivo foi gravado uma vez — na origem, ou salvo de novo por inteiro por uma ferramenta que achatou o histórico. Dois ou mais significam que bytes foram anexados depois que o documento foi concluído pela primeira vez. Cada trailer anexado carrega uma chave /Prev apontando de volta para a seção de referência cruzada anterior, então as revisões formam uma cadeia que dá para percorrer de trás para frente até o original.

Causas legítimas, e há muitas: aplicar uma assinatura digital é, por definição, uma atualização incremental. Preencher um AcroForm também é, assim como adicionar uma anotação ou comentário, ou um passe de linearização de algumas ferramentas. É por isso que a contagem de revisões, sozinha, é um sinal de força média — a pergunta útil é o que a revisão posterior alterou. Se uma segunda revisão reescreve um número de objeto que já existia na primeira e esse objeto guarda dados de página, de fluxo de conteúdo ou de imagem, a aparência renderizada do documento mudou depois de ele ter sido gerado. Isso é um achado bem mais forte do que "foi salvo duas vezes".

5. Leia o par /ID do trailer

O trailer costuma conter um array /ID com duas strings de bytes. A especificação é explícita sobre os papéis: a primeira é um identificador permanente atribuído quando o documento foi criado e nunca deve mudar; a segunda é atualizada pelo aplicativo produtor a cada salvamento.

Olhe o final do arquivo

$ tail -c 400 statement.pdf
trailer
<< /Size 41 /Root 1 0 R /Info 9 0 R
   /ID [<8f2c...a91b> <41de...77c0>] >>
startxref
184102
%%EOF

Dois valores diferentes são o registro do próprio formato PDF de que o arquivo foi salvo de novo depois de criado. É um marcador limpo, definido na especificação, que não custa nada ler. Suas fraquezas: alguns geradores minimalistas omitem o /ID por completo (o que remove a verificação em vez de provar algo), e uma ferramenta que reescreve o arquivo inteiro pode definir os dois elementos com o mesmo valor novo, apagando o rastro.

6. Procure um segundo subconjunto da mesma fonte

Fontes incorporadas em PDFs geralmente entram como subconjuntos (subsets): só os glifos que o documento realmente usa são incluídos, e o nome da fonte ganha um prefixo de seis letras maiúsculas mais um sinal de adição, como ABCDEF+Helvetica. O prefixo é arbitrário; o que importa é que um gerador que grava um documento uma única vez reúne todos os glifos de que precisa para um tipo em um subconjunto.

Liste os nomes das fontes incorporadas

$ strings statement.pdf | grep -o '/BaseFont *[^ /]*' | sort -u
/BaseFont /ABCDEF+Helvetica
/BaseFont /QWERTY+Helvetica

Dois prefixos para um mesmo tipo significam que glifos daquele tipo foram incorporados em duas ocasiões distintas. Esse é o rastro deixado quando texto é adicionado ou substituído num PDF existente por uma ferramenta diferente da que o criou — a assinatura clássica de "mudaram os números", que sobrevive mesmo quando os metadados foram apagados.

Causas legítimas: um documento montado pela fusão de PDFs de fontes diferentes carrega legitimamente múltiplos subconjuntos de um tipo comum, assim como um arquivo em que uma anotação de assinatura ou de carimbo trouxe a própria fonte. Leia este sinal junto com o histórico de revisões.

7. Se estiver assinado, verifique o que a assinatura cobre

O /ByteRange de um campo de assinatura é um array de pares deslocamento/comprimento que nomeia exatamente quais bytes do arquivo a assinatura protege — normalmente tudo, exceto o buraco onde a própria assinatura fica. Se o último byte coberto não é o último byte do arquivo, a diferença foi anexada depois da assinatura e não está protegida por ela.

Este é o achado estrutural isolado mais forte disponível num PDF, e é legível sem nenhuma criptografia: você compara dois números. Note as duas perguntas separadas. "A matemática da assinatura valida?" exige o certificado e um repositório de confiança. "Existem bytes fora do intervalo assinado?" exige apenas o arquivo. Um visualizador pode alegremente reportar uma assinatura válida enquanto exibe conteúdo que a assinatura nunca cobriu — é por isso que alguns visualizadores mostram "assinado, com alterações posteriores" e os usuários clicam sem ler.

O que a verificação manual não pega

As verificações acima são reais e, para um único arquivo suspeito, muitas vezes bastam. O que elas não conseguem fazer:

  • Correlacionar. Individualmente, cada achado é fraco. O sinal que merece ação é um editor de consumo na cadeia de ferramentas e uma segunda revisão e uma imagem rasterizada de página inteira. Correlacionar à mão trinta extratos por dia não é um trabalho que alguém faça bem.
  • Enxergar dentro de estruturas comprimidas. Streams de referência cruzada e streams de objetos (PDF 1.5+) são comprimidos com Flate. O grep não consegue lê-los, então uma contagem ingênua de %%EOF é apenas um piso para o número real de revisões.
  • Analisar o conteúdo da página. Saber se uma página é um escaneamento de página inteira com um punhado de glifos vetoriais visíveis desenhados por cima — em oposição a uma camada de OCR invisível, que é normal — exige percorrer o fluxo de conteúdo e ler os modos de renderização de texto.
  • Ser consistente. Dois analistas chegam a duas conclusões. Uma ferramenta determinística dá a mesma resposta para os mesmos bytes, e é isso que torna uma trilha de auditoria defensável.

Automatizando

A Tamperlens faz exatamente as verificações desta página, mais as que exigem um parser de verdade, e as devolve em JSON. Ela analisa os bytes brutos por conta própria, em vez de se apoiar numa biblioteca de PDF de alto nível, porque bibliotecas normalizam justamente a evidência que importa — carregue e salve de novo um arquivo com a maioria delas e o histórico de revisões desaparece.

Dez famílias de sinais rodam em todo documento: atualizações incrementais, divergência de metadados, anomalias de data, rastro do Producer, inconsistência de /ID, anomalias de fontes, páginas híbridas, conteúdo ativo, cobertura da assinatura e avisos de estrutura. Cada uma retorna uma severidade, um detalhe em linguagem clara e evidência legível por máquina (deslocamentos, números de objeto, as strings de fato observadas). Todas estão documentadas — com as respectivas causas legítimas — no guia de campo.

Os documentos são analisados em memória e nunca gravados em disco. O motor usa só CPU, não chama nenhum serviço de terceiros e é determinístico: os mesmos bytes produzem o mesmo relatório, então dá para fazer testes de regressão contra ele.

Verifique um PDF agora, grátis

Arraste um arquivo para o verificador na página inicial — sem conta, nada é armazenado, relatório completo. Quando quiser isso no seu pipeline, uma chave de API com 25 documentos por mês é grátis: veja o guia rápido da API ou crie uma conta.

A Tamperlens reporta sinais de risco, não veredictos de autenticidade. Sinais podem ter causas legítimas; combine-os com a sua própria lógica de decisão.

Leitura relacionada