private byte[] applyAllSignatures(byte[] pdfBytes, List allSignatures) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int i = 0; i < allSignatures.size(); i++) {
try (PDDocument pdf = Loader.loadPDF(pdfBytes)) {
SignatureInfo signatureInfo = allSignatures.get(i);
boolean isFirstSignature = (i == 0);
boolean isLastSignature = (i == allSignatures.size() - 1);
PDSignatureField signatureField = findSignatureField(pdf, signatureInfo.fieldName());
if (signatureField != null) {
createVisibleSignature.signPDF(
pdf,
buildSignatureImage(signatureInfo.sigFile(), pdf),
baos,
signatureField,
getPageNumber(pdf, signatureField),
isFirstSignature,
isLastSignature
);
pdfBytes = baos.toByteArray();
baos.reset();
}
}
}
return pdfBytes;
}
А ниже показано, как выглядят мои подписи после добавления второй.
Вторая подпись выглядит нормально, но "Поля формы с изменениями свойств" удивляют, как и моя сертификат уже недействителен. Конечно, любой вклад будет принят с благодарностью.
Что интересно, если я вернусь к версии PDFBox 2.0.32 без каких-либо других изменений, обе подписи будут выглядеть именно так, как я ожидал. ; однако они невидимы.
Я пытаюсь подписать документ несколько раз, используя PDFBox 3.0.2. Первый заверил, остальные подписали. [code]/* * Heavily influenced by: * https://github.com/apache/pdfbox/blob/3.0/examples/src/main/java/org/apache/pdfbox/examples/signature/CreateVisibleSignature.java */
// // 3. Adjust signature field size // adjustSignatureFieldSize(pdSignatureField, pdImage);
// 4. Set Visible Sign Designer and known bug check setVisibleSignDesigner(document, pdImage, pageNum);
// 5. Set Document Permissions setDocumentPermissions(document, signature, isFirstSignature, isLastSignature);
// 6. Set Signature Properties setSignatureProperties(signature);
// 7. Build Signature buildSignature(pageNum);
// 8. Add Signing Date signature.setSignDate(Calendar.getInstance());
// 9. Sign the document SignatureOptions signatureOptions = new SignatureOptions(); // TODO make sure getVisibleSignature is not null! signatureOptions.setVisualSignature(visibleSignatureProperties.getVisibleSignature()); signatureOptions.setPage(visibleSignatureProperties.getPage() - 1); document.addSignature(signature, this, signatureOptions);
// 10. Save incremental (Must be done to add multiple signatures) document.saveIncremental(fos); IOUtils.closeQuietly(signatureOptions); }
/* * MDP (Modification Detection and Prevention) Permission Levels: * * 0: No DocMDP transform parameters dictionary exists (document is not certified) * * 1: No changes to the document are permitted * - Most restrictive * - Forbids even adding more signatures * * 2: Allows filling in forms and digitally signing * - Default if /P entry is missing or invalid * - Forbids other modifications (e.g., adding/deleting pages, editing content) * * 3: Allows filling in forms, digitally signing, and adding comments/annotations * - Least restrictive * - Still forbids modifying the document's core content * * Note: Attempting to make changes beyond what's allowed by the permission level will invalidate the certification signature. * At least in theory though, in practice, when I set the permissions, then add another signature, the first in invalidated. */ private void setDocumentPermissions(PDDocument document, PDSignature signature, boolean isFirstSignature, boolean isLastSignature) throws IOException { // The first signatures must be the certification signature, the following signatures must be approval signatures if (document.getVersion() >= 1.5f) { if (isFirstSignature) { if (SigUtils.getMDPPermission(document) == 0) { // See notes above. Maybe we can get away with this until we figure it out SigUtils.setMDPPermission(document, signature,2); } else { throw new IllegalStateException("Document is already certified"); } } } else {
if (!isDocumentCertified(document)) { log.warn("Adding approval signature to an uncertified document"); } } }
private void checkDocumentPermissions(PDDocument document) { // If permissions 1, then no changes are permitted int accessPermissions = SigUtils.getMDPPermission(document); if (accessPermissions == 1) { throw new IllegalStateException("No changes to the document are permitted due to DocMDP transform parameters dictionary"); } }
// Set desired height and calculate corresponding width to maintain aspect ratio float desiredWidth = SIGNATURE_HEIGHT * aspectRatio;
// Set the size and position of the signature image visibleSignDesigner.xAxis(0).yAxis(0).width(desiredWidth).height(SIGNATURE_HEIGHT).adjustForRotation(); }
public void setVisibleSignatureProperties(String name, String location, String reason, int preferredSize, boolean visualSignEnabled) { visibleSignatureProperties.signerName(name).signerLocation(location).signatureReason(reason). preferredSize(preferredSize).visualSignEnabled(visualSignEnabled). setPdVisibleSignature(visibleSignDesigner); }
private PDSignature findExistingSignature(PDDocument doc, PDSignatureField signatureField) { PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm(); if (acroForm == null) { throw new IllegalStateException("Document does not contain an AcroForm"); } PDSignature signature = signatureField.getSignature(); if (signature == null) { signature = new PDSignature(); signatureField.getCOSObject().setItem(COSName.V, signature); } return signature; }
private KeyStore loadKeyStore() throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException { KeyStore ks = KeyStore.getInstance("PKCS12"); try (InputStream is = CreateVisibleSignature.class.getResourceAsStream(keystorePath)) { ks.load(is, pin.toCharArray()); } return ks; } } [/code] С одной подписью все работает как положено. Но когда я добавляю вторую подпись, первая становится недействительной. Ниже я называю SignPDF [code] private byte[] applyAllSignatures(byte[] pdfBytes, List allSignatures) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int i = 0; i < allSignatures.size(); i++) { try (PDDocument pdf = Loader.loadPDF(pdfBytes)) { SignatureInfo signatureInfo = allSignatures.get(i); boolean isFirstSignature = (i == 0); boolean isLastSignature = (i == allSignatures.size() - 1);
if (signatureField != null) { createVisibleSignature.signPDF( pdf, buildSignatureImage(signatureInfo.sigFile(), pdf), baos, signatureField, getPageNumber(pdf, signatureField), isFirstSignature, isLastSignature ); pdfBytes = baos.toByteArray(); baos.reset(); } } } return pdfBytes; } [/code] А ниже показано, как выглядят мои подписи после добавления второй. [img] [/img]
Вторая подпись выглядит нормально, но "Поля формы с изменениями свойств" удивляют, как и моя сертификат уже недействителен. Конечно, любой вклад будет принят с благодарностью. Что интересно, если я вернусь к версии PDFBox 2.0.32 без каких-либо других изменений, обе подписи будут выглядеть именно так, как я ожидал. ; однако они невидимы. [img]https://i.sstatic.net/eEcWW7vI.png[/img]