Como adicionar assinaturas de segurança PDF em Python
Aspose.PDF FOSS para Python inclui um detector de comprometimento de assinatura que inspeciona um PDF já assinado em busca de um padrão específico de adulteração: bytes significativos adicionados após o intervalo de bytes assinado da assinatura, um risco exclusivo de arquivos PDF atualizados incrementalmente. Este guia adiciona essa verificação a um fluxo de trabalho Python usando as classes SignaturesCompromiseDetector e CompromiseCheckResult. Criar ou aplicar novas assinaturas digitais é uma parte separada da biblioteca e não está coberta aqui. A biblioteca é instalada com o comando abaixo.
Guia passo a passo
Etapa 1: Instalar o Pacote
Instale o pacote FOSS Aspose.PDF:
git clone https://github.com/aspose-pdf-foss/Aspose-PDF-FOSS-for-Python.git
cd Aspose-PDF-FOSS-for-Python
pip install -e .Verifique a instalação importando SignaturesCompromiseDetector e imprimindo uma mensagem de confirmação:
from aspose_pdf import SignaturesCompromiseDetector
print("aspose-pdf-foss-for-python is ready.")Etapa 2: Importar Classes Necessárias
from aspose_pdf import CompromiseCheckResult, SignaturesCompromiseDetectorEtapa 3: Preparar um Objeto que Exponha uma Lista de Assinaturas
SignaturesCompromiseDetector não analisa um PDF por si só — seu construtor aceita qualquer objeto que exponha um atributo signatures: uma lista de entradas de assinatura, cada uma contendo valid, byte_range e reference_data. PdfSignature — uma classe simples, diretamente instanciável — corresponde a essa estrutura, portanto é útil para ver como a verificação se comporta antes de conectá-la ao seu próprio objeto de documento:
from types import SimpleNamespace
from aspose_pdf import PdfSignature
with open("signed.pdf", "rb") as handle:
pdf_bytes = handle.read()
signature = PdfSignature(
name="Signature1",
contents=b"...", # PKCS#7 signed-data blob from the signature dictionary
byte_range=[0, 1024, 1040, len(pdf_bytes) - 1040],
reference_data=pdf_bytes,
)
signed_document = SimpleNamespace(signatures=[signature])Substitua signed_document pelo seu próprio objeto de documento assim que ele expuser uma lista signatures na mesma estrutura — qualquer objeto com esse atributo funciona.
Etapa 4: Executar a Verificação de Comprometimento
from aspose_pdf import SignaturesCompromiseDetector
detector = SignaturesCompromiseDetector(signed_document)
result = detector.check()
print(result.compromised) # bool
print(result.has_compromised_signatures) # bool -- same value as compromised
print(result.signatures_coverage) # int -- number of signatures inspected
print(result.reasons) # list[str] -- human-readable findingscheck() percorre cada assinatura em signed_document.signatures, procurando por conteúdo não assinado anexado após o intervalo de bytes assinado de cada assinatura. Um CompromiseCheckResult resume o resultado: compromised e has_compromised_signatures reportam o mesmo booleano sob dois nomes, signatures_coverage indica quantas assinaturas foram examinadas e reasons lista uma explicação legível para cada problema encontrado.
Etapa 5: Lidar com um Documento Sem Assinaturas
Uma lista signatures vazia ou ausente não é uma condição de erro — ela é relatada da mesma forma que um documento sem nada a ser verificado:
from types import SimpleNamespace
from aspose_pdf import SignaturesCompromiseDetector
unsigned_document = SimpleNamespace(signatures=[])
detector = SignaturesCompromiseDetector(unsigned_document)
result = detector.check()
print(result.compromised) # False
print(result.reasons) # ["unsigned document"]Passar SignaturesCompromiseDetector(None) — o padrão do construtor — tem o mesmo comportamento.
Problemas Comuns e Correções
compromised is False para um PDF que você sabe que foi editado após a assinatura
SignaturesCompromiseDetector procura especificamente por bytes não assinados acrescentados após o intervalo de bytes assinados de uma assinatura — um padrão típico de adulteração ingênua por atualização incremental. Não realiza a verificação completa de assinatura criptográfica. Para isso, chame validate() no objeto PdfSignature individual.
compromised and has_compromised_signatures parecem redundantes
Eles têm o mesmo valor: compromised é uma propriedade calculada que devolve has_compromised_signatures. Use o nome que ficar melhor no seu código.
Nenhuma exceção é lançada quando o documento não tem signatures atributo algum
SignaturesCompromiseDetector trata um documento sem o atributo signatures, ou document=None, da mesma forma que um documento não assinado — check() devolve um resultado com has_compromised_signatures=False e reasons=["unsigned document"] ao invés de gerar erro.
Um malformado PdfSignature não é sinalizado
check() ignora qualquer assinatura cujo byte_range não seja uma lista de 4 elementos, ou cujo reference_data não seja bytes/bytearray, ao invés de gerar erro ou relatá-la como comprometida. Uma assinatura construída com a forma errada é silenciosamente excluída da verificação, não sinalizada.
Confundindo este detector com a criação de assinatura
SignaturesCompromiseDetector e CompromiseCheckResult apenas inspecionam assinaturas que já existem em um documento — não possuem método para criar, aplicar ou incorporar uma nova assinatura.
Perguntas Frequentes
O que exatamente conta como “comprometido” aqui?
Bytes significativos, não-brancos, anexados ao PDF após a faixa de bytes assinada de uma assinatura — com duas exceções que o detector já considera: uma assinatura ou carimbo de tempo posterior que também cobre esses bytes, e uma atualização incremental que apenas adiciona material de validação (como um /DSS) sem sobrepor novo conteúdo como anotações.
Isso verifica a validade criptográfica da própria assinatura?
Não. SignaturesCompromiseDetector verifica padrões de adulteração ao redor do intervalo de bytes assinado. A validade criptográfica é uma verificação separada, disponível através de PdfSignature.validate().
O que signatures_coverage me informa?
O número de assinaturas que a verificação realmente examinou no documento fornecido — útil para confirmar que o detector viu as assinaturas que você esperava antes de confiar em um resultado limpo.
Posso verificar um documento com várias assinaturas de uma só vez?
Sim. check() itera cada entrada em signed_document.signatures e retorna um CompromiseCheckResult agregado que cobre todas elas.
Preciso criar objetos PdfSignature eu mesmo no uso normal?
Não — a construção de PdfSignature da Etapa 3 serve para explorar o comportamento do detector diretamente. Em um fluxo de trabalho real, passe qualquer objeto que seu código de carregamento de documento já produza, contanto que ele exponha uma lista signatures de entradas com formato PdfSignature.