Class AcrobatSignatureHandlerFactory
- java.lang.Object
-
- org.faceless.pdf2.AcrobatSignatureHandlerFactory
-
- All Implemented Interfaces:
SignatureHandlerFactory
public class AcrobatSignatureHandlerFactory extends java.lang.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 theFormSignature
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(); factory.setDigestAlgorithm("SHA-256"); factory.setPAdES(true); ...
To ensure a signature meets the requirements for PAdES part 4 (long-term validation), the following conditions need to be met:
- An RFC3161 TimeStamp server must be set by calling
setTimeStampServer(java.net.URL)
- OCSP and CRL revocation checking must be peformed on signing by calling
setValidateCertificatesOnSigning(boolean)
- The "Signing Certificate" attribute must be set by calling
setUseSigningCertificateAttribute(boolean)
. This is the default. - The PAdES identifier should be set by calling
setPAdES(boolean)
. Slightly ironically, this is recommended but not required - 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 theKeyStore
supplied to theFormSignature.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.setPAdES(true); factory.setValidateCertificatesOnSigning(true); factory.setTimeStampServer(new URL("http://timestamp.entrust.net/TSS/RFC3161sha1TS")); pdf.getForm().getElements().put("sig", sig); sig.sign(keystore, "myalias", password, factory); pdf.render(new FileOutputStream("output.pdf"));
- Since:
- 2.7.1
- See Also:
TimeStampHandlerFactory
-
-
Constructor Summary
Constructors Constructor Description AcrobatSignatureHandlerFactory()
Create a new SignatureHandlerFactory
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description PKCS7SignatureHandler.SigningEngine
createSigningEngine(java.security.KeyStore keystore, java.lang.String alias, char[] password, java.lang.String subfilter)
Return the actual object that will do the signing.int
getContentSize()
Return the anticipated content size, as set bysetContentSize(int)
java.lang.String
getDigestAlgorithm()
Return the Digest Algorithm, as set bysetDigestAlgorithm(java.lang.String)
SignatureHandler
getHandler()
Return a handler created by this factoryjava.net.URL
getTimeStampServer()
Return the first TimeStamp Server, as set bysetTimeStampServers(java.util.Collection<java.net.URL>)
, or null if none are set.java.util.List<java.net.URL>
getTimeStampServers()
Return the TimeStamp Servers, as set bysetTimeStampServers(java.util.Collection<java.net.URL>)
.void
setContentSize(int size)
This method can be called to fix the space allocated for the "Contents" variable, which contains the encoded signature.void
setCRLs(java.util.List<java.security.cert.X509CRL> crls)
Set the list of CRLs that should be consulteed before requesting new ones from the internet.void
setCustomAppearance(PDFCanvas canvas, float x1, float y1, float x2, float y2)
Set a custom appearance for this signature.void
setDigestAlgorithm(java.lang.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 ISO32001extension
to PDF 2.0.void
setOCSPResponses(java.util.List<PKCS7SignatureHandler.OCSPResponse> ocspResponses)
Set the list of OCSP responses that should be consulteed before requesting new ones from the internet.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.void
setProvider(java.security.Provider provider)
Set theProvider
to be used for any signature operations created by this factory.void
setSSLSocketFactory(javax.net.ssl.SSLSocketFactory factory)
Set theSSLSocketFactory
to be used for any HTTPS connections that need to be made during signing or verifying, such as for timestamping or OCSP queries.void
setTimeStampServer(java.net.URL server)
Specify the URL of an RFC3161 Timestamp Server.void
setTimeStampServers(java.util.Collection<java.net.URL> servers)
Specify the URL of one or more RFC3161 Timestamp Server.void
setUseSigningCertificateAttribute(boolean use)
Specifies whether the PKCS#7 object should be generated with theid-aa-signingCertificateV2
(1.2.840.113549.1.9.16.2) attribute, as defined in RFC5035.void
setValidateCertificatesOnSigning(boolean check)
Specifies whether the certificates used during signing should be verified with their OCSP or CRL responders, if available.
-
-
-
Method Detail
-
setDigestAlgorithm
public void setDigestAlgorithm(java.lang.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).
- Parameters:
algorithm
- the message-digest algorithm to use.- See Also:
FormSignature.setRequiredDigestAlgorithms(java.lang.String[])
-
setTimeStampServer
public void setTimeStampServer(java.net.URL server)
Specify the URL of an RFC3161 Timestamp Server. Since 2.24.4 simply callssetTimeStampServers(java.util.Collection<java.net.URL>)
.- Parameters:
server
- The server to contact for the TimeStamp. May benull
to turn off timestamping (the default). If a username/password are required they may be specified in the URL, eg "http://user:password@server.com".- Since:
- 2.7.1
- See Also:
setTimeStampServers(java.util.Collection<java.net.URL>)
-
setTimeStampServers
public void setTimeStampServers(java.util.Collection<java.net.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 aGeneralSecurityException
. RFC3161 Timestamps can be verified in Acrobat 7 or later, and with this class via the various "TimeStamp" methods.- Parameters:
servers
- The list of one or more servers to contact for the TimeStamp. May be empty ornull
to turn off timestamping (the default). If a username/password are required they may be specified in the URL, eg "http://user:password@server.com".- Since:
- 2.24.4
- See Also:
FormSignature.getSignDate()
,PKCS7SignatureHandler.getTimeStampCertificates()
-
getTimeStampServer
public java.net.URL getTimeStampServer()
Return the first TimeStamp Server, as set bysetTimeStampServers(java.util.Collection<java.net.URL>)
, or null if none are set.- Since:
- 2.22
-
getTimeStampServers
public java.util.List<java.net.URL> getTimeStampServers()
Return the TimeStamp Servers, as set bysetTimeStampServers(java.util.Collection<java.net.URL>)
. If none are set, return an empty list- Since:
- 2.24.2
-
getDigestAlgorithm
public java.lang.String getDigestAlgorithm()
Return the Digest Algorithm, as set bysetDigestAlgorithm(java.lang.String)
- Since:
- 2.22
-
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.
- Since:
- 2.15.2
-
setUseSigningCertificateAttribute
public void setUseSigningCertificateAttribute(boolean use)
Specifies whether the PKCS#7 object should be generated with theid-aa-signingCertificateV2
(1.2.840.113549.1.9.16.2) 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- 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);
- 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 texty1
- the bottom-most Y co-ordinate to place the (optional) certificate textx2
- the right-most X co-ordinate to place the (optional) certificate texty2
- the top-most Y co-ordinate to place the (optional) certificate text- Since:
- 2.7.3
-
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 callsetContentSize(-100)
, this will result in a call ofgetEstimatedContentSize(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 wasspecified
, you could pass in a value of "-1000" to this method to reserve 1000 bytes in the PKCS#7 object for the TimeStamp token.- Parameters:
size
- the size of the Contents string in bytes, or <= 0 to determine automatically.- Since:
- 2.7.6
-
getContentSize
public int getContentSize()
Return the anticipated content size, as set bysetContentSize(int)
- Since:
- 2.28
-
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.- Parameters:
pades
- if true, use the PAdES standard, otherwise create regular Acrobat signatures.- Since:
- 2.15.2
-
setProvider
public void setProvider(java.security.Provider provider)
Set theProvider
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 theKeyStore
passed in toFormSignature.sign()
, which can also be used to set the Provider.- Parameters:
provider
- the Provider- Since:
- 2.18.3
-
setSSLSocketFactory
public void setSSLSocketFactory(javax.net.ssl.SSLSocketFactory factory)
Set theSSLSocketFactory
to be used for any HTTPS connections that need to be made during signing or verifying, such as for timestamping or OCSP queries.- Parameters:
factory
- the SSLSocketFactory, or null to use the default- Since:
- 2.28.4
-
setOCSPResponses
public void setOCSPResponses(java.util.List<PKCS7SignatureHandler.OCSPResponse> ocspResponses)
Set the list of OCSP responses that should be consulteed before requesting new ones from the internet.- Parameters:
ocspResponses
- the list of pre-retrieved OCSP responses, or null- Since:
- 2.28
-
setCRLs
public void setCRLs(java.util.List<java.security.cert.X509CRL> crls)
Set the list of CRLs that should be consulteed before requesting new ones from the internet.- Parameters:
crls
- the list of pre-retrieved CRLs, or null- Since:
- 2.28
-
createSigningEngine
public PKCS7SignatureHandler.SigningEngine createSigningEngine(java.security.KeyStore keystore, java.lang.String alias, char[] password, java.lang.String subfilter) throws java.security.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.- Parameters:
keystore
- the KeyStore supplied to the sign methodalias
- the alias supplied to the sign methodpassword
- the password supplied to the sign methodsubfilter
- the subfilter- Throws:
java.security.GeneralSecurityException
- Since:
- 2.22
-
getHandler
public SignatureHandler getHandler()
Description copied from interface:SignatureHandlerFactory
Return a handler created by this factory- Specified by:
getHandler
in interfaceSignatureHandlerFactory
-
-