Wielokrotny podpis PDFBox z nieprawidłowym podpisem Java
Miałem wymagania dotyczące przepływu pracy z wieloma podpisami PDF. W tym pliku PDF zostanie podpisany wiele razy bez zmian w dokumencie, powiedzmy, że 2 lub więcej osób może podpisać ten sam dokument. Próbuję dwukrotnie dodać podpisy w pdf, ale po drugim podpisaniu pdf pierwszy podpis jest nieważny. Użyłem API PDFBox Java do tworzenia podpisów PDF.
Kroki tworzenia PDF:
- Utworzono plik PDF przez dodanie nazw pustych pól podpisu: [email protected] i [email protected] przy użyciu oryginalnego pliku hello.pdf, wyślij nazwę pliku hello_tag.pdf uruchom program> TagPDFSignatureFields.java
- Pierwsze podpisywanie przez pobranie pola podpisu [email protected] z pliku hello_tag.pdf, nazwa pliku to hello_signed.pdf uruchom program> SignAndIdentifySignatureFields.java
- Podpisywanie po raz drugi przez pobranie pola podpisu [email protected] z pliku hello_signed.pdf, nazwa pliku to hello_singed2.pdf uruchom program> Sign2.java
W drugim kroku plik PDF jest poprawnie podpisywany, ale po trzecim kroku podpisana wersja w drugim kroku zostaje unieważniona, a podpis w trzecim kroku jest w porządku w programie Acrobat Reader.
Proszę znaleźć link do kodu źródłowego Java i przykładowego pliku PDF w celach informacyjnych. Link do dysku Google pdf_multi_signs_pdfbox_java
Każda pomoc będzie mile widziana.
Odpowiedzi
Krótko mówiąc, w kodzie występuje wiele problemów. Problem powodujący, że program Adobe Reader oznaczył Twój pierwszy podpis jako nieważny po dodaniu drugiego podpisu, w rzeczywistości jest już na etapie przygotowań, TagPDFSignatureFields
podczas którego tworzysz nieprawidłowy wpis w drzewie zduplikowanych stron. Pozostałe problemy również powinny zostać naprawione, mimo że Adobe Reader obecnie nie narzeka.
Szczegółowe zagadnienia ...
Duplikat wpisu strony
W TagPDFSignatureFields
twojej metodzie addEmptySignField
zaczyna się tak:
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);
Tutaj pobierasz pierwszą stronę document
i natychmiast dodajesz tę stronę document
ponownie. To powoduje, że węzeł drzewa głównego stron w pliku hello_tag.pdf
wygląda następująco:
2 0 obj
<<
/Type /Pages
/Count 2
/Kids [6 0 R 6 0 R]
>>
endobj
To znaczy drzewo stron zawiera dwa razy ten sam obiekt strony, którego Adobe Reader nie akceptuje, ale naprawia pod maską. W przypadku podpisanych dokumentów Adobe Reader ostrzega o tym w sposób niejasny:

A w aktualnych wersjach (np. 2020.013.20066) Adobe Reader w dwukrotnie podpisanym pliku oznacza nawet pierwszy podpis jako uszkodzony. We wcześniejszych wersjach (np. 2019.012.20040) tak się nie stało. Prawdopodobnie jest to efekt utwardzenia kodu walidacyjnego po opublikowaniu Shadow Attacks.
Na marginesie: jeśli masz sytuację, w której manipulowanie podpisanym dokumentem (wypełnianie formularzy, ponowne podpisywanie ...) zrywa stare podpisy, zawsze sprawdź również, czy oryginalny dokument może już mieć problemy. Sprawdzenie, czy zmiany zastosowane w podpisanym dokumencie są dozwolone, są dość wrażliwe na błędy, które w przeciwnym razie są naprawiane pod maską, a zatem niewidoczne.
Nieprawidłowe częściowe nazwy pól
Używasz adresów e-mail jako nazw pól, [email protected]
a [email protected]
na przykład:
signatureField.setPartialName("[email protected]");
...
signatureField1.setPartialName("[email protected]");
( TagPDFSignatureFields
metoda addEmptySignField
)
Te częściowe nazwy pól są nieprawidłowe, częściowe nazwy pól nie mogą zawierać znaków kropki („.”).
PDFBox w przyszłych wersjach będzie próbował temu zapobiec, patrz PDFBOX-5028 .
Ustawianie domyślnych zasobów i domyślnych wyglądów po podpisaniu
Podczas podpisywania ustawiasz domyślne zasoby i domyślny wygląd słownika AcroForm :
acroForm.setDefaultResources(resources);
...
acroForm.setDefaultAppearance(defaultAppearanceString);
( SignAndIdentifySignatureFields
i Sign2
metoda addEmptySignField
)
Samo w sobie nie jest to złe, ale uważaj, jeśli zrobisz to na wcześniej podpisanym pliku, który ma już takie wpisy i ustawisz je na inne wartości niż wcześniej, może to unieważnić poprzedni podpis , zobacz odpowiedź tutaj .
Ustawianie wersji PDF bez potrzeby
Próbujesz zmienić zgłoszoną wersję PDF dokumentu:
document.setVersion(1.0f);
( SignAndIdentifySignatureFields
metoda addEmptySignField
)
document.setVersion(2.0f);
( Sign2
metoda addEmptySignField
)
Pierwsza instrukcja jest ignorowana, ponieważ sam dokument wymaga już wersji co najmniej 1.5, ale druga instrukcja rzeczywiście ustawia wersję dokumentu PDF na 2.0, co może powodować problemy w starszych przeglądarkach.
...
Prawdopodobnie jest więcej problemów. Po raz pierwszy zauważyłem te problemy, zanim zdałem sobie sprawę, że już naprawienie jedynego pierwszego, Duplicate Page Entry, wystarczyło, aby naprawić pierwszy podpis ...