Class PKCS7SignatureHandler


  • public abstract class PKCS7SignatureHandler
    extends SignatureHandler

    This class represents the subclass of digital signatures that rely on Public/Private key pairs and that meet the requirements laid down in the document "PDF Public-Key Digital Signature and Encryption Specification", published by Adobe. As of 2016 almost all security handlers used by Acrobat will be an instance of this class: it works with signatures created by the Adobe.PPKMS and Adobe.PPKLite engines in Acrobat, as well as Document level timestamps introduced in PDF 2.0, and many older, legacy public-key based signature handlers as well.

    Instances of this class are created by both the AcrobatSignatureHandlerFactory and TimeStampHandlerFactory.

    See Also:
    AcrobatSignatureHandlerFactory
    • Constructor Detail

      • PKCS7SignatureHandler

        protected PKCS7SignatureHandler()
    • Method Detail

      • getHashAlgorithm

        public String getHashAlgorithm()
        Return the Hash algorithm used by the PKCS#7 object when signing. Valid values are currently SHA1, SHA-256, SHA-384, SHA-512 or MD5
        Since:
        2.18.2
      • getSubFilter

        public abstract String getSubFilter()
        Return the SubFilter field, which determines how the PKCS#7 object is encoded. Valid values are "adbe.pkcs7.detached", "adbe.pkcs7.sha1" "adbe.x509.rsa_sha1" or "ETSI.CAdES.detached"
      • prepareToSign

        protected void prepareToSign​(KeyStore keystore,
                                     String alias,
                                     char[] password)
                              throws GeneralSecurityException
        Description copied from class: SignatureHandler

        This method initialized the handler using the specified values into a state where it's ready to sign. This method should be used to set any additional fields in the Signature dictionary, for example "Certs" for the Self-Sign handler.

        Those overriding this method must call super.prepareToSign() before doing anything else.

        Overrides:
        prepareToSign in class SignatureHandler
        Parameters:
        keystore - the KeyStore
        alias - which key to use
        password - the password to use to decode the key
        Throws:
        GeneralSecurityException
      • getCertificates

        public X509Certificate[] getCertificates()
                                          throws CertificateException
        Return the list of certificates included in this signature. The first certificate is the X.509 certificate used to sign the PDF, and the optional additional certificates are those used to validate the earlier certificates, in no particular order.
        Returns:
        a list of one or more X.509 Certificates
        Throws:
        CertificateException
      • setCustomAppearance

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

        Set a custom appearance for this signature. See the AcrobatSignatureHandlerFactory.setCustomAppearance(org.faceless.pdf2.PDFCanvas, float, float, float, float) method for more details - unless you're manually overriding this class, that's the method you should be calling.

        Parameters:
        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
        Since:
        2.0
      • getTimeStampCertificates

        public X509Certificate[] getTimeStampCertificates()
                                                   throws GeneralSecurityException,
                                                          IOException

        If the PKCS#7 object was digitally time-stamped using an RFC3161 time-stamp server, this method verifies and returns the list of X.509 certificates that verify the timestamp, with the actual signing certificate first and the rest in no particular order. If this method succeeds, then the date returned by FormSignature.getSignDate() is the date guaranteed by the time-stamp.

        If the signature was time-stamped but the timestamp is corrupt or invalid, thie method will throw either a GeneralSecurityException or a IOException detailing why.

        If the signature was not timestamped, this method returns null.

        If the signature is, in itself, an RFC 3161 document-level TimeStamp as would be created by TimeStampHandlerFactory, then this method return the same list as getCertificates()

        Returns:
        an array of X509Certificate objects that authorized the timestamp, or null if there isn't a timestamp.
        Throws:
        GeneralSecurityException - if the TimeStamp is invalid
        IOException - if the TimeStamp is corrupt or can't be parsed
        Since:
        2.7.1
      • addValidationInformation

        public boolean addValidationInformation​(KeyStore keystore)
                                         throws GeneralSecurityException,
                                                IOException

        Add Long Term Validation information for this signature to the PDF. This will perform an OCSP check on the signature, and add the response to the PDF (and, therefore, to the list of responses included in getValidationInformation()). It may be called on any previously signed PKCS#7 signature, including document-level Timestamps. Validation information will be ignored in Acrobat prior to Acrobat XI.

        For validation information to be considered complete, the entire certificate chain, including any trusted roots, must be embedded in the PDF. The trusted root certificates are often not included with the original signature, so if a KeyStore is supplied it will be searched for any missing root certificates to be embedded in the PDF. A suitable KeyStore for this purpose is the one returned by FormSignature.loadDefaultKeyStore(). As of 2.23.6, any Certificates still not found to complete the chain will be downloaded from the URL specified in the "CA Issuers" field of the subject Certificate.

        The signature must be signed and verified, otherwise an IllegalStateException will be thrown.

        Here's an example showing how to add validation information to all the signatures in a PDF.

         PDF pdf = new PDF(new PDFReader(new File("input.pdf")));
         KeyStore rootkeystore = FormSignature.loadDefaultKeyStore();
         for (FormElement elt : pdf.getForm().getElements().values()) {
           if (elt instanceof FormSignature) {
             FormSignature sig = (FormSignature)elt;
             if (sig.getSignatureHandler() instanceof PKCS7SignatureHandler) {
               PKCS7SignatureHandler handler = (PKCS7SignatureHandler)sig.getSignatureHandler();
               handler.addValidationInformation(rootkeystore);
             }
           }
         }
         pdf.render(new FileOutputStream("output.pdf"));
         
        Parameters:
        keystore - the KeyStore to query for any additional root certificates, or null to not perform this step.
        Returns:
        true if all the required validation informaion could be added up to a trusted root, or false if some of the links in the chain could not be verified.
        Throws:
        GeneralSecurityException
        IOException
        Since:
        2.18.2
        See Also:
        getValidationInformation(), TimeStampHandlerFactory, AcrobatSignatureHandlerFactory
      • queryTimeStampResponse

        public static byte[] queryTimeStampResponse​(URL url,
                                                    byte[] digest,
                                                    String hashAlgorithm,
                                                    int timeout,
                                                    SSLSocketFactory sslfactory)
                                             throws IOException,
                                                    GeneralSecurityException
        This is a helper method that can be called by those implementing their own custom PKCS7SignatureHandler.SigningEngine objects, and who need to create a timestamped signature. This method will generate a time-stamp Request and query the supplied URL, returning a DER-encoded time-stamp Response which can be returned from PKCS7SignatureHandler.SigningEngine.getTimeStampResp(byte[]).
        Parameters:
        url - the URL of the RFC3161 time-stamp server to query
        digest - the digest to sign
        hashAlgorithm - the algorithm to use, for example "SHA256"
        timeout - how long to wait for a connection to or response from the server, in milliseconds, before throwing an IOException
        sslfactory - if not null and the URL is an HTTPS URL, this SSLSocketFactory will be used for the connection. If this value is null the default SSLSocketFactory is used for the connection, which is usually all that's required.
        Throws:
        IOException
        GeneralSecurityException
        Since:
        2.25.1