I've been reading the official PDFBox examples to visually sign a PDF document, especifically the example from CreateVisualSignature2.java, which generates an empty document as a template to define the signature appearance and then sets it to the real document by calling SignatureOptions.setVisibleSignature().
In my case, I've been using an HSM service to do the signing for me, so I don't have direct access to private keys or certificates. I send the document hash to this service and it returns a PKCS7 byte array which I add to my document using ExternalSigningSupport.setSignature().
The code, which is based on the PDFBox example linked above, looks like this:
// Read the document and prepare a signature.
PDDocument document = PDDocument.load( "path/to/file.pdf" );
PDSignature signature = new PDSignature();
signature.setFilter( PDSignature.FILTER_ADOBE_PPKLITE );
signature.setSubFilter( PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED );
signature.setReason( "Test" );
InputStream template = createVisualSignatureTemplate( document ); // Implementation defined below.
SignatureOptions options = new SignatureOptions();
options.setVisibleSignature( template );
options.setPage( 0 );
document.addSignature( signature, options );
// Get the content to sign using PDFBox external signing support.
FileOutputStream outputStream = new FileOutputStream();
ExternalSigningSupport externalSigning = document.saveIncrementalForExternalSigning( outputStream );
byte[] content = IOUtils.toByteArray( externalSigning.getContent() );
// Send the content to the HSM service and get the response.
byte[] hash = MessageDigest.getInstance( "SHA-256" ).digest( content );
byte[] pkcs7 = MyHSMService.getSignedHash( hash );
// Add the signature to the PDF.
externalSigning.setSignature( pkcs7 );
document.close();
And my template method, based on the method of the same name in the linked PDFBox example, simplified:
PDDocument emptyDocument = new PDDocument();
emptyDocument.addPage( new PDFPage( document.getPage(0).getMediaBox() ) );
// Create the PDAcroForm, PDSignatureField, PDAppearanceDictionary, etc,
// just like in the official example.
(...)
// Define the content stream of the visual signature.
PDPageContentStream content = new PDPageContentStream( emptyDocument, appearanceStream );
content.beginText();
content.showText( "Signed by: ... " ); // The signer name should be here.
content.newLine();
content.showText( "Date: ..." ); // The signature datetime should be here.
content.endText();
content.close();
// Convert the empty document as an input stream and return it, just like the example.
(...)
This works fine and I can add valid visual signatures without issues. My problem is that I need to add the signer name and sign date in the signature appearance, but since I create the template BEFORE calling my HSM service to sign, I don't have access to that data yet, which is why I need to define the content AFTER signing the document.
Is there a way to achieve this? I'm new to PDF signing, so my understanding of the fundamentals is pretty poor.
Thanks in advance!

