0

I have client-server architecture where server handles all the PDF related stuff and the client is doing actual signing. Server doesn't have access to a private key, only certificate.

I am having a hard time writing this with PDFbox. I already have a working solution in iText but I am trying to write similar thing with PDFbox. Here is the iText code so you have an insight into what am I trying to achieve.

         //before signing on client
            StampingProperties stampingProperties = new StampingProperties();
            stampingProperties.preserveEncryption();
            stampingProperties.useAppendMode();
            PdfSigner signer = new PdfSigner(reader, os, stampingProperties);
            signer.getDocument().getCatalog().setModified();
            X509Certificate[] cert = CertificateHelper.createCertificate(signatureInfo.getCert());
            PreSignContainer external = new PreSignContainer(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached);
            signer.signExternalContainer(external, 8192);
            byte[] hash = external.getHash();
            PdfPKCS7 sgn = new PdfPKCS7(null, cert, "SHA256", null, new BouncyCastleDigest(), true);
            byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, PdfSigner.CryptoStandard.CMS, null, null);
         //send sh to client for signing

         //after signing on client
    try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
            PdfPKCS7 sgn = new PdfPKCS7(null, cert, "SHA256", null, new BouncyCastleDigest(), true);
            sgn.setExternalDigest(signature, null, "RSA");
            byte[] signaturePkcs7 = sgn.getEncodedPKCS7(hash, PdfSigner.CryptoStandard.CMS, getTsaClient(), null, null);
            PostSignContainer externalSignatureContainer = new PostSignContainer(signaturePkcs7);
            PdfDocument pdfDocument = new PdfDocument(new PdfReader(new ByteArrayInputStream(preSignaturePdf)));
            PdfSigner.signDeferred(pdfDocument, storedSignatureInfo.getFieldName(), os, externalSignatureContainer);
            byte[] signedPdf = os.toByteArray();
        } 

This is what I have with PDFbox:

    //before signing on client
            PDSignature signature = new PDSignature();
            signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
            signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
            signature.setLocation(signatureInfo.getLocation());
            signature.setReason(signatureInfo.getReason());
            signature.setSignDate(Calendar.getInstance());
            PDDocument document = PDDocument.load(pdf);
            document.addSignature(signature);
            ExternalSigningSupport externalSigning = document.saveIncrementalForExternalSigning(os);
            byte[] content = externalSigning.getContent().readAllBytes();
            byte[] hash = MessageDigest.getInstance("SHA-256", new BouncyCastleProvider()).digest(content);
            externalSigning.setSignature(new byte[0]);

  //after signing on client 
            PDDocument pdf = PDDocument.load(preSignaturePdf);
            PDSignature lastSignature = pdf.getLastSignatureDictionary();
            int offset = lastSignature.getByteRange()[1] + 1;       
            try (RandomAccessBuffer raf = new RandomAccessBuffer(preSignaturePdf)) {
                raf.seek(offset);
                raf.write(Hex.getBytes(signature));
            }
  • If you are looking for browser side extension for signing from modern browsers, you may refer to https://stackoverflow.com/a/55676351/9659885 On server side, you may use any component depending on support for detached pdf signature... – Bharat Vasant Jun 10 '20 at 05:18
  • If this is about signing remotely, here is a person who did it: https://github.com/crs2195/signature/tree/master/RemoteSignature-%20PDFBox – Tilman Hausherr Jun 10 '20 at 09:35

0 Answers0