Assinatura múltipla de PDFBox fornecendo assinatura inválida Java
Eu tinha alguns requisitos de fluxo de trabalho de multi-assinatura em PDF Neste pdf será assinado várias vezes sem alterações no documento, digamos que 2 ou mais pessoas podem assinar o mesmo documento. Estou tentando adicionar as assinaturas em pdf duas vezes, mas depois de assinar o pdf pela segunda vez, a primeira assinatura fica inválida. Usei o PDFBox Java API para a criação de assinaturas em PDF.
Etapas de criação de PDF:
- PDF criado adicionando nomes de campos de assinatura vazios: [email protected] e [email protected] usando hello.pdf original out put nome de arquivo hello_tag.pdf run program> TagPDFSignatureFields.java
- Assinatura pela primeira vez buscando o campo de assinatura [email protected] do arquivo hello_tag.pdf, o nome do arquivo de saída é hello_signed.pdf execute o programa> SignAndIdentifySignatureFields.java
- Assinatura pela segunda vez obtendo o campo de assinatura [email protected] do arquivo hello_signed.pdf, o nome do arquivo de saída é hello_singed2.pdf run program> Sign2.java
Na 2ª etapa, o pdf é assinado corretamente, mas após a 3ª etapa, a versão assinada da 2ª etapa é invalidada e a assinatura da 3ª etapa mostra tudo certo no acrobat reader.
Encontre o código-fonte Java do link e um exemplo de pdf para referência. Link do Google Drive pdf_multi_signs_pdfbox_java
Qualquer ajuda seria apreciada.
Respostas
Resumindo, há uma série de problemas em seu código. O problema que faz com que o Adobe Reader marque sua primeira assinatura como inválida após adicionar uma segunda assinatura, na verdade, já está na etapa de preparação, TagPDFSignatureFields
onde você cria uma entrada inválida na árvore de páginas duplicadas. Os outros problemas também devem ser corrigidos, embora o Adobe Reader atualmente não reclame.
Os problemas em detalhes ...
Entrada de página duplicada
Em TagPDFSignatureFields
seu método addEmptySignField
começa assim:
private void addEmptySignField(String[] args) throws Exception, IOException {
// Create a new document with an empty page.
try (PDDocument document = PDDocument.load(new File(args[0]));)
{
PDPage page = document.getPage(0);
document.addPage(page);
Aqui você recupera a primeira página de document
e imediatamente adiciona essa página document
novamente. Isso faz com que o nó da árvore raiz das páginas em seu arquivo hello_tag.pdf
fique assim:
2 0 obj
<<
/Type /Pages
/Count 2
/Kids [6 0 R 6 0 R]
>>
endobj
Ou seja, a árvore de páginas contém o mesmo objeto de página duas vezes que o Adobe Reader não aceita, mas repara nos bastidores. Para os documentos assinados, o Adobe Reader avisa sobre isso de forma vaga:

E nas versões atuais (por exemplo, 2020.013.20066) Adobe Reader no arquivo assinado duas vezes até marca a primeira assinatura como quebrada. Em versões anteriores (por exemplo, 2019.012.20040), isso não acontecia. Provavelmente, isso é um efeito do endurecimento do código de validação após a publicação dos Shadow Attacks.
À parte: se você tiver uma situação em que manipular um documento assinado (preenchimento de formulário, assinar novamente, ...) quebra as assinaturas antigas, sempre verifique também se o documento original já pode ter problemas. A verificação se alterações aplicadas a um documento assinado são permitidas, são bastante sensíveis a erros que de outra forma são corrigidos sob o capô e, portanto, não visíveis.
Nomes de campos parciais inválidos
Você usa endereços de e-mail como nomes de campo [email protected]
e , [email protected]
no caso do seu exemplo:
signatureField.setPartialName("[email protected]");
...
signatureField1.setPartialName("[email protected]");
( TagPDFSignatureFields
método addEmptySignField
)
Esses nomes de campos parciais são inválidos, os nomes de campos parciais não devem conter caracteres de ponto ('.').
O PDFBox em versões futuras tentará evitar isso, consulte PDFBOX-5028 .
Definindo os recursos padrão e as aparências padrão na assinatura
Durante a assinatura, você define os recursos padrão e a aparência padrão do dicionário AcroForm :
acroForm.setDefaultResources(resources);
...
acroForm.setDefaultAppearance(defaultAppearanceString);
( SignAndIdentifySignatureFields
e Sign2
método addEmptySignField
)
Por si só, isso não é uma coisa ruim, mas cuidado, se você fizer isso com um arquivo assinado anteriormente que já contém essas entradas e configurá-los com valores diferentes dos anteriores, isso pode invalidar a assinatura anterior , consulte o problema respondido aqui .
Configurando a versão PDF sem necessidade
Você tenta alterar a versão PDF reivindicada do documento:
document.setVersion(1.0f);
( SignAndIdentifySignatureFields
método addEmptySignField
)
document.setVersion(2.0f);
( Sign2
método addEmptySignField
)
A primeira instrução é ignorada porque o próprio documento já requer uma versão de pelo menos 1.5, mas a segunda instrução realmente define a versão do PDF do documento para 2.0, o que pode causar problemas com visualizadores mais antigos.
...
É bem provável que haja mais problemas. Eu simplesmente identifiquei esses problemas pela primeira vez antes de reconhecer que já consertando o único primeiro, a entrada de página duplicada, foi suficiente para curar a primeira assinatura ...