Class AcrobatSignatureHandlerFactory

  • All Implemented Interfaces:

    public class AcrobatSignatureHandlerFactory
    extends Object
    implements SignatureHandlerFactory

    An implementation of SignatureHandlerFactory that returns handlers suitable for signing documents for use with Acrobat 6.0 or later.

    For basic use it's quite acceptable to use the FormSignature.HANDLER_ACROBATSIX which is an instance of this factory. If advanced options need to be set (such as setting a TimeStamp server or changing the hash algorithm) then you can create an instance of this factory and set the options on that before passing it in to the FormSignature constructor.

    Since 2.15.2 this class's factories can create PAdES signatures. This stands for "PDF Advanced Electronic Signatures", and it's defined in both ETSI TR 102 923 and in PDF 2.0. It's a particular application of CAdES signatures, which are the modern variation of the standard PKCS#7 signatures used by Acrobat.

    For our purposes the terms PAdES and CAdES are interchangeable, and when verifying a digital signature with the BFO API the two are not distinguished. When signing, to create a signature marked as PAdES you can call the setPAdES(boolean) method on this factory:

     AcrobatSignatureHandlerFactory factory = new AcrobatSignatureHandlerFactory();

    To ensure a signature meets the requirements for PAdES part 4 (long-term validation), the following conditions need to be met:

    1. An RFC3161 TimeStamp server must be set by calling setTimeStampServer(
    2. OCSP and CRL revocation checking must be peformed on signing by calling setValidateCertificatesOnSigning(boolean)
    3. The "Signing Certificate" attribute must be set by calling setUseSigningCertificateAttribute(boolean). This is the default.
    4. The PAdES identifier should be set by calling setPAdES(boolean). Slightly ironically, this is recommended but not required
    5. The entire certificate chain up to and including a trusted root must be available when signing

    This last point needs further explaining. For a signature to be considered long-term validated, the entire signature chain, up to and including any trusted root certificates, must be embedded in the PDF. This includes the the certificates certifying any OCSP or CRL responses obtained as part of the valdation. The root certificates may not be included as part of these responses, or it may not be included as an explicit part of the certificate-chain for the PrivateKey entry used when signing. However, so long as all the required root certificates can be found somewhere in the KeyStore supplied to the FormSignature.sign() method, then they will be embedded in the signed object. If they are not available (or if the OCSP or CRL requests fail for any reason), then a "PK3" warning will be emitted during signing with details of the break in the certificate chain. The signature will still be valid, but will not be considered "long-term" valid.

    Here's an example showing how to apply a PAdES long-term valid signature to a PDF. The KeyStore supplied is assumed to have all the required root-certificates

     KeyStore keystore = KeyStore.getInstance("JKS");
     keystore.load(new FileInputStream("keystore.jks"), password);
     PDF pdf = new PDF(new PDFReader(new File("input.pdf")));
     FormSignature sig = new FormSignature();
     AcrobatSignatureHandlerFactory factory = new AcrobatSignatureHandlerFactory();
     factory.setTimeStampServer(new URL(""));
     pdf.getForm().getElements().put("sig", sig);
     sig.sign(keystore, "myalias", password, factory);
     pdf.render(new FileOutputStream("output.pdf"));
    See Also:
    • Constructor Detail

      • AcrobatSignatureHandlerFactory

        public AcrobatSignatureHandlerFactory()
        Create a new SignatureHandlerFactory
    • Method Detail

      • setDigestAlgorithm

        public void setDigestAlgorithm​(String algorithm)

        Set the message digest algorithm to use - one of "MD5", "SHA1", "SHA-256", "SHA-384", "SHA-512" or "RIPEMD160" for core PDF up to 2.0, or "SHA3-256", "SHA3-384", "SHA3-512" and "SHAKE256" which are defined in the ISO32001 extension to PDF 2.0.

        The default since 2.20 is SHA256 - prior to that release it was SHA1.

        Note that algorithms other than MD5 or SHA1 require Acrobat 8.0 or later, and may require a non-standard or more recent JCE provider (for instance, SHA-256 was only added to the Sun JCE in version 1.6, and SHAKE256 is not in the default JCE as of Java 17 so will require a third-party procider such as BouncyCastle).

        algorithm - the message-digest algorithm to use.
        See Also:
      • setTimeStampServers

        public void setTimeStampServers​(Collection<URL> servers)
        Specify the URL of one or more RFC3161 Timestamp Server. If at least one server is specified, when the PDF is signed it will be contacted and the Signature timestamped. If the first server does not return a valid timestamp for any reason, the second will be tried and so on. If at least one TimeStamp server was specified and valid timestamp can be obtained, signing will faili with a GeneralSecurityException. RFC3161 Timestamps can be verified in Acrobat 7 or later, and with this class via the various "TimeStamp" methods.
        servers - The list of one or more servers to contact for the TimeStamp. May be empty or null to turn off timestamping (the default). If a username/password are required they may be specified in the URL, eg "".
        See Also:
        FormSignature.getSignDate(), PKCS7SignatureHandler.getTimeStampCertificates()
      • setValidateCertificatesOnSigning

        public void setValidateCertificatesOnSigning​(boolean check)

        Specifies whether the certificates used during signing should be verified with their OCSP or CRL responders, if available. The responses are included in the signature using the adbe-RevocationInfoArchival (1.2.840.113583.1.1.8) attribute, which will certify that the Certificates used to sign the PDF were valid at the time of signing. This is required for documents which need to meet the PAdES LTV (Long-Term Validation) specification.

        Setting this value to true may result in 1 or more network requests during signing.

      • setUseSigningCertificateAttribute

        public void setUseSigningCertificateAttribute​(boolean use)
        Specifies whether the PKCS#7 object should be generated with the id-aa-signingCertificateV2 (1.2.840.113549. attribute, as defined in RFC5035. This is recommended for all signatures and required for PAdES signatures, and is on by default since 2.15.2
      • setCustomAppearance

        public void setCustomAppearance​(PDFCanvas canvas,
                                        float x1,
                                        float y1,
                                        float x2,
                                        float y2)

        Set a custom appearance for this signature. This method allows you to add a signature, thumbprint, logo or any other form of custom image to your signature annotations (technically, this method sets the "n2" layer of the annotation). The canvas may be of any size, and will be scaled to fit the annotation on the page.

        Care needs to be taken when setting this value. It's not recommended to use a canvas containing a bitmap image with an opaque background, as this may mask any layers behind this one. In particular, a "?" is typically used on a layer below this one to indicate the signature has not been verified. Specifying an opaque image may result in this being obscured.

        As a optional convenience, by specifying non-zero coordinates for the x1,y1,x2 and y2 values, some text describing the signing certificate will be added to the canvas at the specified location. The format for this is fixed, but as it doesn't have to be included, the developer is free to add his or her own text if they don't like the result, simply by setting all four values to zero.

        As an example, the default PKCS7 appearance is set with the following code which loads a pre-defined pattern from a resources file:

           setCustomAppearance(new PDFCanvas("logo.Adobe", 1), 0, 35, 100, 65);
        canvas - the canvas to display as the "n2" layer of the signature appearance.
        x1 - the left-most X co-ordinate to place the (optional) certificate text
        y1 - the bottom-most Y co-ordinate to place the (optional) certificate text
        x2 - the right-most X co-ordinate to place the (optional) certificate text
        y2 - the top-most Y co-ordinate to place the (optional) certificate text
      • setContentSize

        public void setContentSize​(int size)

        This method can be called to fix the space allocated for the "Contents" variable, which contains the encoded signature. If a value > 0 is supplied then the Contents variable will have that much space allocated for it. If a value of <= 0 is supplied then the SignatureHandler.getEstimatedContentSize(int) method will be called with the negative of this value (so if you call setContentSize(-100), this will result in a call of getEstimatedContentSize(100).

        The intention of this is to allocate space in the Contents variable for external objects, such as TimeStamps from a remote server. For instance, if you were using a PKCS7SignatureHandler to digitally sign and an RFC3161 TimeStamp server was specified, you could pass in a value of "-1000" to this method to reserve 1000 bytes in the PKCS#7 object for the TimeStamp token.

        size - the size of the Contents string in bytes, or <= 0 to determine automatically.
      • getContentSize

        public int getContentSize()
        Return the anticipated content size, as set by setContentSize(int)
      • setPAdES

        public void setPAdES​(boolean pades)
        Set whether the factory should use the PAdES signature idenfifier, as specified in PDF 2.0 and supported in Acrobat X and later.
        pades - if true, use the PAdES standard, otherwise create regular Acrobat signatures.
      • setProvider

        public void setProvider​(Provider provider)
        Set the Provider to be used for any signature operations created by this factory. If set the Provider will be asked first for any resource, but if it is unable to provide one the default provider will be used as a fallback. This will override the Provider of the KeyStore passed in to FormSignature.sign(), which can also be used to set the Provider.
        provider - the Provider
      • setSSLSocketFactory

        public void setSSLSocketFactory​(SSLSocketFactory factory)
        Set the SSLSocketFactory to be used for any HTTPS connections that need to be made during signing or verifying, such as for timestamping or OCSP queries.
        factory - the SSLSocketFactory, or null to use the default
      • setOCSPResponses

        public void setOCSPResponses​(List<PKCS7SignatureHandler.OCSPResponse> ocspResponses)
        Set the list of OCSP responses that should be consulteed before requesting new ones from the internet.
        ocspResponses - the list of pre-retrieved OCSP responses, or null
      • setCRLs

        public void setCRLs​(List<X509CRL> crls)
        Set the list of CRLs that should be consulteed before requesting new ones from the internet.
        crls - the list of pre-retrieved CRLs, or null
      • createSigningEngine

        public PKCS7SignatureHandler.SigningEngine createSigningEngine​(KeyStore keystore,
                                                                       String alias,
                                                                       char[] password,
                                                                       String subfilter)
                                                                throws GeneralSecurityException
        Return the actual object that will do the signing. This can be overridden if a custom implementation demands it, e.g. for remote signing.
        keystore - the KeyStore supplied to the sign method
        alias - the alias supplied to the sign method
        password - the password supplied to the sign method
        subfilter - the subfilter