Spire.PDF is a professional PDF library applied to creating, writing, editing, handling and reading PDF files without any external dependencies. Get free and professional technical support for Spire.PDF for .NET, Java, Android, C++, Python.

Mon Jun 08, 2026 2:05 pm

I'm trying to add a timestamped visible certificate to a PDF.
I'm basing my code on https://cdn.e-iceblue.com/Tutorials/Jav ... -Java.html

When adding visible signature. I have everything, but the viewer say that the Timestamp is from my machine (please see with_cert.png)

Code: Select all
import com.spire.pdf.interactive.digitalsignatures.PdfSignature;
import com.spire.pdf.interactive.digitalsignatures.PdfSignatureAppearance;
...
// Create a signature maker object to apply the digital signature
PdfOrdinarySignatureMaker signatureMaker = new PdfOrdinarySignatureMaker(document, certificat);
// Get the pdf signature and set the sign details
PdfSignature signature = signatureMaker.getSignature();
... adding data to signature
// Create a signature appearance
PdfSignatureAppearance appearance = new PdfSignatureAppearance(signature);
...adding info to appearance
// Get the first page
PdfPageBase firstpage = document.getPages().get(0);

// Add the signature to a specified location of the page
signatureMaker.makeSignature("Signature", firstpage,
   (float) rect.getMinX(), (float) rect.getMinY(),
   (float) rect.getWidth(), (float) rect.getHeight(),
   appearance);
// and save


When trying to add the Timesamp, as shown in the same page, I change the start of the code to

Code: Select all
String timeStampUrl = "https://rfc3161.ai.moda/adobe";
PdfPKCS7Formatter formatter = new PdfPKCS7Formatter(certificat, false);
formatter.setTimestampService(new TSAHttpService(timeStampUrl));

// Create a signature maker object to apply the digital signature
PdfOrdinarySignatureMaker signatureMaker = new PdfOrdinarySignatureMaker(document, formatter);


I only get a field so sign, and the content of PDF is not fully present (please see with_formatter.png)

So how do i make this.
Also, how do you set policies when signing so that no change is allowed ?

Regards
Guillaume PATRY

GuiPATRY
 
Posts: 35
Joined: Wed Feb 17, 2021 10:18 am

Mon Jun 08, 2026 7:59 pm

Additionally, when you are not setting the reason label, it use the whole NameLabel and Label as a label.
Please see "with company label.png" and "without company label.png".
The code change for this example is just the commenting of the ReasonLabel set (see the last image)

Regards
Guillaume

GuiPATRY
 
Posts: 35
Joined: Wed Feb 17, 2021 10:18 am

Tue Jun 09, 2026 6:46 am

Hello,

Thank you for your feedback.

Based on your requirements, please try the following solution.
Code: Select all
 PdfPKCS7Formatter formatter = new PdfPKCS7Formatter(certificate, false);
        String timeStampUrl = "https://rfc3161.ai.moda/adobe";
        formatter.setTimestampService(new TSAHttpService(timeStampUrl));
        formatter.setOCSPService(new OCSPHttpService(null));

        PdfOrdinarySignatureMaker signatureMaker = new PdfOrdinarySignatureMaker(document, formatter);
        signatureMaker.makeSignature("signName");
        PdfSignature signature = signatureMaker.getSignature();
        signature.setName("Gary");
       // signature.setReason("This is the final version.");
        signature.setLocation("U.S.");
        signature.setContactInfo("112554");

        PdfSignatureAppearance appearance = new PdfSignatureAppearance(signature);
        appearance.setNameLabel("Signer: ");
       // appearance.setReasonLabel("Reason: ");
        appearance.setLocationLabel("Location: ");
        appearance.setContactInfoLabel("Phone: ");

        PdfImage image = PdfImage.fromFile(path+"logo.png");
        appearance.setSignatureImage(image);
        appearance.setGraphicMode(GraphicMode.SignImageAndSignDetail);

        Rectangle2D rect = new Rectangle2D.Float();
        rect.setFrame(new Point2D.Float(90, 550), new Dimension(150, 80));

        signatureMaker.makeSignature("Signature", pdfPageBase,
                (float) rect.getMinX(), (float) rect.getMinY(),
                (float) rect.getWidth(), (float) rect.getHeight(),
                appearance);


        String output = "signature.pdf";
        document.saveToFile(path+output, FileFormat.PDF);



Looking forward to hearing about your test results. Please feel free to let us know if you have any further questions.

Sincerely,
Amy
E-iceblue support team
User avatar

amy.zhao
 
Posts: 3011
Joined: Wed Jun 27, 2012 8:50 am

Tue Jun 09, 2026 11:02 am

Hello
sorry, still doesn't work

based on your code :

1 - using a different name in the first and second signatureMaker.makeSignature (as in your code); I have 2 signature (one invisible, and one visible) (see formatter_diff_name.png)
2 - using the same name, I don't get an error, but it says that there is an unsigned *invisible* signature field (formatter_same_name)
3 - using only the second signatureMaker.makeSignature (ie commenting the first one) give me a visible signature field, not filled (see formatter_one_name.png)
4 - using only the first signatureMaker.makeSignature gives a valid invisible signature

Comment
the "MakeSignature" for visible Signature needs a PdfSignatureAppearance, itself based on a PdfSignature... so making a signature is needing a signature, as far as I understand. I get it from the getSignature() but is that ok ? This is working when the PdfOrdinarySignatureMaker is based on certificat, but not when it is based on such a formatter...

GuiPATRY
 
Posts: 35
Joined: Wed Feb 17, 2021 10:18 am

Wed Jun 10, 2026 4:16 am

Hello,

Thank you for your detailed feedback. I sincerely apologize for any inconvenience this issue has caused.

To answer your question: yes, it is perfectly fine to obtain the PdfSignature object using the getSignature() method.

Based on your scenario, I have adjusted the code to create only a single signature. I have verified that this updated code successfully generates a valid visible digital signature. Please refer to the modified code attached. I have also attached the resulting document for your reference.
Code: Select all
String imageFile =path+"logo.png";
        String pfxPath =path+"gary.pfx";
        String outputFile = path+"signWithSignatureMaker.pdf";

        PdfDocument doc = new PdfDocument();
        doc.loadFromFile(path+"sample.pdf");
        PdfPageBase pdfPageBase = doc.getPages().get(0);
        PdfCertificate x509 = new PdfCertificate(pfxPath, "e-iceblue");
        PdfPKCS7Formatter formatter = new PdfPKCS7Formatter(x509, false);
        String timeStampUrl = "https://rfc3161.ai.moda/adobe";
        formatter.setTimestampService(new TSAHttpService(timeStampUrl));
        formatter.setOCSPService(new OCSPHttpService(null));

        PdfOrdinarySignatureMaker signatureMaker = new PdfOrdinarySignatureMaker(doc, formatter);

        PdfSignature signature = signatureMaker.getSignature();
        signature.setName("E-iceblue");
        signature.setContactInfo("028-81705109");
        signature.setLocation("ChengDu");

        PdfSignatureAppearance appearance = new PdfSignatureAppearance(signature);
        appearance.setNameLabel("Signer:");
        appearance.setContactInfoLabel("Phone:");
        appearance.setLocationLabel("Location:");
        appearance.setDateLabel("Date:");

        appearance.setGraphicMode(GraphicMode.SignImageAndSignDetail);
        appearance.setSignatureImage(PdfImage.fromFile(imageFile));

        Rectangle2D rect = new Rectangle2D.Float();
        rect.setFrame(new Point2D.Float(90, 550), new Dimension(180, 80));

        signatureMaker.makeSignature("Signature", pdfPageBase,
                (float) rect.getMinX(), (float) rect.getMinY(),
                (float) rect.getWidth(), (float) rect.getHeight(),
                appearance);

//        for (int i = 0; i < doc.getPages().getCount(); i++) {
//            signatureMaker.makeSignature("signName" + (i + 1), doc.getPages().get(i),
//                    (float) doc.getPages().get(i).getActualSize().getWidth() - 340,
//                    (float) doc.getPages().get(0).getActualSize().getHeight() - 150, 220, 100, appearance);
//        }

        doc.saveToFile(outputFile);
        doc.close();
        doc.dispose();


Should you have any further questions or need additional assistance, please feel free to let me know.

Sincerely,
Amy
E-iceblue support team
User avatar

amy.zhao
 
Posts: 3011
Joined: Wed Jun 27, 2012 8:50 am

Wed Jun 10, 2026 11:35 am

Hello
after copying your code in mine, it did work all the time when there is no signature Image.

When there is a signature Image... the result seems to be random.
Compiling and running the same code twice give different result.
One time it works, some other it doesn't.
I'm trying to find if some process keep handle on the image ?

(please note that we are not currently using the signature image, so the solution is OK)

Otherwise, how do you change what the certificate allow ?
I already changed the security policy, but it still says that modification is allowed...

real thanks for your help
Regards

GuiPATRY
 
Posts: 35
Joined: Wed Feb 17, 2021 10:18 am

Thu Jun 11, 2026 2:50 am

Hello,

Thanks for the feedback.

I just ran a quick test with a signature image (looped 10 times), and all the digital signatures were successful and valid! Since I couldn't see the issue on my end, please let me know if you'd like to share more details so we can troubleshoot it together.

As for the security policy settings, our devs are already on it. The task is tracked under SPIREPDF-8091. I'll inform you once the new version is released.

Sincerely,
Amy
E-iceblue support team
User avatar

amy.zhao
 
Posts: 3011
Joined: Wed Jun 27, 2012 8:50 am

Return to Spire.PDF