PDFBox firma múltiple que proporciona una firma no válida Java
Tenía algunos requisitos de flujo de trabajo de firma múltiple en PDF. En este pdf se firmará varias veces sin cambios en el documento, digamos que 2 o más personas pueden firmar el mismo documento. Estoy tratando de agregar las firmas en pdf dos veces, pero después de firmar el pdf por segunda vez, la primera firma no es válida. He usado PDFBox Java api para la creación de firmas en PDF.
Pasos para la creación de PDF:
- PDF creado agregando nombres de campos de firma vacíos: [email protected] y [email protected] usando hello.pdf original, poner nombre de archivo hello_tag.pdf ejecutar programa> TagPDFSignatureFields.java
- Firma por primera vez obteniendo el campo de firma [email protected] del archivo hello_tag.pdf, el nombre del archivo es hello_signed.pdf, ejecute el programa> SignAndIdentifySignatureFields.java
- Firma por segunda vez obteniendo el campo de firma [email protected] del archivo hello_signed.pdf, el nombre del archivo es hello_singed2.pdf ejecutar programa> Sign2.java
En el segundo paso, el pdf se firma correctamente, pero después del tercer paso, la versión firmada del segundo paso se invalida y la firma del tercer paso se muestra bien en Acrobat Reader.
Por favor, busque el código fuente de Java y la muestra en pdf del enlace como referencia. Enlace de Google Drive pdf_multi_signs_pdfbox_java
Cualquier ayuda sería apreciada.
Respuestas
En resumen, hay una serie de problemas en su código. El problema que hace que Adobe Reader marque su primera firma como inválida después de agregar una segunda firma ya está en su paso de preparación TagPDFSignatureFields
donde crea una entrada de árbol de páginas duplicadas inválida. Los otros problemas también deben solucionarse, aunque Adobe Reader no se queja actualmente.
Los problemas en detalle ...
Entrada de página duplicada
En TagPDFSignatureFields
su método addEmptySignField
comienza así:
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);
Aquí recupera la primera página de document
e inmediatamente agrega esa página document
nuevamente. Esto hace que el nodo del árbol raíz de las páginas en su archivo se hello_tag.pdf
vea así:
2 0 obj
<<
/Type /Pages
/Count 2
/Kids [6 0 R 6 0 R]
>>
endobj
Es decir, el árbol de páginas contiene el mismo objeto de página dos veces que Adobe Reader no acepta pero repara bajo el capó. Para los documentos firmados, Adobe Reader advierte sobre esto de manera vaga:

Y en las versiones actuales (por ejemplo, 2020.013.20066), Adobe Reader en el archivo firmado dos veces incluso marca la primera firma como rota. En versiones anteriores (por ejemplo, 2019.012.20040) no lo hizo. Probablemente este sea un efecto del endurecimiento del código de validación después de que se publicaron los Shadow Attacks.
Como nota al margen: si tienes una situación en la que manipular un documento firmado (rellenar formularios, volver a firmar, ...) rompe las firmas antiguas, comprueba siempre también si el documento original ya puede tener problemas. La verificación de si los cambios aplicados a un documento firmado están permitidos, son bastante sensibles a errores que de otra manera se corrigen bajo el capó y, por lo tanto, no son visibles.
Nombres de campos parciales no válidos
Utiliza direcciones de correo electrónico como nombres de campo [email protected]
y , [email protected]
en el caso de su ejemplo:
signatureField.setPartialName("[email protected]");
...
signatureField1.setPartialName("[email protected]");
( TagPDFSignatureFields
método addEmptySignField
)
Estos nombres de campos parciales no son válidos, los nombres de campos parciales no deben contener puntos ('.').
PDFBox en futuras versiones intentará evitar esto, consulte PDFBOX-5028 .
Configurar los recursos predeterminados y las apariencias predeterminadas al firmar
Durante la firma, establece los recursos predeterminados y la apariencia predeterminada del diccionario AcroForm :
acroForm.setDefaultResources(resources);
...
acroForm.setDefaultAppearance(defaultAppearanceString);
( SignAndIdentifySignatureFields
y Sign2
método addEmptySignField
)
En sí mismo, esto no es algo malo, pero tenga cuidado, si hace esto en un archivo previamente firmado que ya tiene dichas entradas y las establece en valores diferentes a los anteriores, esto puede invalidar la firma anterior , vea la respuesta al problema aquí .
Configuración de la versión PDF sin necesidad
Intenta cambiar la versión en PDF reclamada del documento:
document.setVersion(1.0f);
( SignAndIdentifySignatureFields
método addEmptySignField
)
document.setVersion(2.0f);
( Sign2
método addEmptySignField
)
La primera instrucción se ignora ya que el documento en sí ya requiere una versión de al menos 1.5, pero la segunda instrucción establece la versión PDF del documento en 2.0, lo que puede causar problemas con los lectores mayores.
...
Es muy probable que haya más problemas. Simplemente descubrí estos problemas antes de reconocer que ya arreglar el único primero, la Entrada de página duplicada, era suficiente para curar la primera firma ...