Class PKCS7SignatureHandler
- java.lang.Object
-
- org.faceless.pdf2.SignatureHandler
-
- org.faceless.pdf2.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
andTimeStampHandlerFactory
.- See Also:
AcrobatSignatureHandlerFactory
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
PKCS7SignatureHandler.OCSPResponse
An OCSP response relating to the validity of a digital signature.static interface
PKCS7SignatureHandler.SigningEngine
This interface defines the engine used to actually sign a PDF.class
PKCS7SignatureHandler.ValidationInformation
This class represents long-term validation information, as described in PAdES part 4.-
Nested classes/interfaces inherited from class org.faceless.pdf2.SignatureHandler
SignatureHandler.Placeholder
-
-
Constructor Summary
Constructors Modifier Constructor Description protected
PKCS7SignatureHandler()
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Concrete Methods Modifier and Type Method Description boolean
addValidationInformation(java.security.KeyStore keystore)
Add Long Term Validation information for this signature to the PDF.boolean
addValidationInformation(java.security.KeyStore keystore, java.util.List<PKCS7SignatureHandler.OCSPResponse> ocspResponses, java.util.List<java.security.cert.X509CRL> crls)
Add Long Term Validation information for this signature to the PDF.java.security.cert.X509Certificate[]
getCertificates()
Return the list of certificates included in this signature.java.lang.String
getDefaultName()
Returns an optional default value that can be used to initializeFormSignature.setName(java.lang.String)
, ornull
if no such name is available.int
getEstimatedContentSize(int additional)
Return the estimated size of the signature object to be embedded, or <= 0 if this cannot be determined.java.lang.String
getFilter()
Return the name of the filter, eg "Adobe.PPKLite".java.lang.String
getHandlerName()
The handler name for aDocument TimeStamp
is "ETSI.RFC3161", otherwise it is "PKCS7"java.lang.String
getHashAlgorithm()
Return the Hash algorithm used by the PKCS#7 object when signing.PDFCanvas
getLayerAppearance(java.lang.String layername, PDFStyle textstyle)
Return aPDFCanvas
for the specified layer.java.lang.String[]
getLayerNames()
Return the list of appearance layer names used by this Signature Handler to create a visible appearance on the page, in the order they should be drawn.java.security.MessageDigest
getMessageDigest()
Return a MessageDigest that will be used to calculate the digest of the PDF for signing.java.security.Provider
getProvider()
Return theProvider
to be used by all operations in this class, or null to use the default.javax.net.ssl.SSLSocketFactory
getSSLSocketFactory()
Return theSSLSocketFactory
to be used by all network connections to HTTPS URLs from this class, or null to use the default.abstract java.lang.String
getSubFilter()
Return the SubFilter field, which determines how the PKCS#7 object is encoded.java.security.cert.X509Certificate[]
getTimeStampCertificates()
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.java.util.List<PKCS7SignatureHandler.ValidationInformation>
getValidationInformation()
Returns the long-term validation details for the signature that are embedded in the PDF.protected void
prepareToSign(java.security.KeyStore keystore, java.lang.String alias, char[] password)
This method initialized the handler using the specified values into a state where it's ready to sign.static byte[]
queryTimeStampResponse(java.net.URL url, byte[] digest, java.lang.String hashAlgorithm, int timeout, javax.net.ssl.SSLSocketFactory sslSocketFactory)
This is a helper method that can be called by those implementing their own customPKCS7SignatureHandler.SigningEngine
objects, and who need to create a timestamped signature.void
setCustomAppearance(PDFCanvas canvas, float x1, float y1, float x2, float y2)
Set a custom appearance for this signature.byte[]
sign()
Finish the digest calculation on the digest returned fromSignatureHandler.getMessageDigest()
and return a signature token the signs it.boolean
verify(java.io.InputStream in)
Return a boolean indicating whether or not the signature handler can verify the specifiedInputStream
.-
Methods inherited from class org.faceless.pdf2.SignatureHandler
containsKey, getArrayValueSize, getBooleanValue, getCertificationType, getDictionaryValueKeys, getFormSignature, getNameValue, getNumericValue, getStreamValue, getStringValue, getTextStringValue, getVariables, preDigest, putArrayValue, putBooleanValue, putDictionaryValue, putNameValue, putNumericValue, putStreamValue, putStringValue, putTextStringValue
-
-
-
-
Method Detail
-
getHashAlgorithm
public java.lang.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
-
getFilter
public java.lang.String getFilter()
Description copied from class:SignatureHandler
Return the name of the filter, eg "Adobe.PPKLite".- Specified by:
getFilter
in classSignatureHandler
-
getSubFilter
public abstract java.lang.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"
-
getHandlerName
public java.lang.String getHandlerName()
The handler name for aDocument TimeStamp
is "ETSI.RFC3161", otherwise it is "PKCS7"- Overrides:
getHandlerName
in classSignatureHandler
- Since:
- 2.18.2
-
getProvider
public java.security.Provider getProvider()
Return theProvider
to be used by all operations in this class, or null to use the default. Note that default will always be used as a fallback if the selected provider is unable to provide a resource (such as a digest algorithm). The default isnull
- Since:
- 2.18.3
- See Also:
AcrobatSignatureHandlerFactory.setProvider(java.security.Provider)
-
getSSLSocketFactory
public javax.net.ssl.SSLSocketFactory getSSLSocketFactory()
Return theSSLSocketFactory
to be used by all network connections to HTTPS URLs from this class, or null to use the default. The default isnull
- Since:
- 2.28.4
-
prepareToSign
protected void prepareToSign(java.security.KeyStore keystore, java.lang.String alias, char[] password) throws java.security.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 classSignatureHandler
- Parameters:
keystore
- the KeyStorealias
- which key to usepassword
- the password to use to decode the key- Throws:
java.security.GeneralSecurityException
-
getEstimatedContentSize
public int getEstimatedContentSize(int additional)
Description copied from class:SignatureHandler
Return the estimated size of the signature object to be embedded, or <= 0 if this cannot be determined. The default implementation returns 0.- Overrides:
getEstimatedContentSize
in classSignatureHandler
- Parameters:
additional
- the negation of any value previously passed intoSignatureHandler.setContentSize(int)
-
getMessageDigest
public java.security.MessageDigest getMessageDigest()
Description copied from class:SignatureHandler
Return a MessageDigest that will be used to calculate the digest of the PDF for signing. This message will be called beforeSignatureHandler.sign()
- see the API docs for that method for more details.- Specified by:
getMessageDigest
in classSignatureHandler
-
sign
public byte[] sign() throws java.security.GeneralSecurityException, java.io.IOException
Description copied from class:SignatureHandler
Finish the digest calculation on the digest returned from
SignatureHandler.getMessageDigest()
and return a signature token the signs it. The returned byte array will be stored as the "Contents" value of the Signature dictionary.As well as being called to perform the actual signing, the default behaviour of the
SignatureHandler.getVariables()
method is also to call this method with an empty digest, to determine the size of the token to store in the PDF (theSignatureHandler.getMessageDigest()
method is called twice as well). This can be overridden, by callingAcrobatSignatureHandlerFactory.setContentSize(int)
for handlers created by that factory or, if you're implementing a custom signature handler, by writing your ownSignatureHandler.getVariables()
method.- Overrides:
sign
in classSignatureHandler
- Returns:
- a byte array representing the signature token
- Throws:
java.security.GeneralSecurityException
- if the signature cannot be applied for some cryptographic reasonjava.io.IOException
- if the InputStream cannot be read
-
verify
public final boolean verify(java.io.InputStream in) throws java.security.GeneralSecurityException, java.io.IOException
Description copied from class:SignatureHandler
Return a boolean indicating whether or not the signature handler can verify the specifiedInputStream
.- Specified by:
verify
in classSignatureHandler
- Returns:
- true if the signature matches the specified InputStream
- Throws:
java.security.GeneralSecurityException
- if the signature cannot be verified for some cryptographic reasonjava.io.IOException
- if the InputStream cannot be read
-
getCertificates
public java.security.cert.X509Certificate[] getCertificates() throws java.security.cert.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:
java.security.cert.CertificateException
-
getLayerNames
public java.lang.String[] getLayerNames()
Description copied from class:SignatureHandler
Return the list of appearance layer names used by this Signature Handler to create a visible appearance on the page, in the order they should be drawn. This method is called internally by the
FormSignature
class when drawing the signature annotations on the page. For more information see the document "Digital Signature Appearances for Public-Key Interoperability", from Adobes website.As an example, both the Verisign and the SelfSign handlers return the array
[ "n0", "n1", "n2", "n3" ]
.- Specified by:
getLayerNames
in classSignatureHandler
- Returns:
- the ordered list of layer names that should to used to create a visible representation of this signature on a page.
- See Also:
SignatureHandler.getLayerAppearance(java.lang.String, org.faceless.pdf2.PDFStyle)
-
getLayerAppearance
public PDFCanvas getLayerAppearance(java.lang.String layername, PDFStyle textstyle)
Description copied from class:SignatureHandler
Return aPDFCanvas
for the specified layer. This method is called internally by theFormSignature
class when drawing the signature annotations on the page. For more information see the document "Digital Signature Appearances for Public-Key Interoperability", from Adobes website.- Specified by:
getLayerAppearance
in classSignatureHandler
- Parameters:
layername
- the layer to create (from the list returned bySignatureHandler.getLayerNames()
)textstyle
- the style in which to draw the text, if any- Returns:
- a new
PDFCanvas
of any size containing the specified layer. - See Also:
SignatureHandler.getLayerNames()
-
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 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.0
-
getTimeStampCertificates
public java.security.cert.X509Certificate[] getTimeStampCertificates() throws java.security.GeneralSecurityException, java.io.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 aIOException
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 asgetCertificates()
- Returns:
- an array of
X509Certificate
objects that authorized the timestamp, ornull
if there isn't a timestamp. - Throws:
java.security.GeneralSecurityException
- if the TimeStamp is invalidjava.io.IOException
- if the TimeStamp is corrupt or can't be parsed- Since:
- 2.7.1
-
getDefaultName
public java.lang.String getDefaultName()
Description copied from class:SignatureHandler
Returns an optional default value that can be used to initializeFormSignature.setName(java.lang.String)
, ornull
if no such name is available.- Overrides:
getDefaultName
in classSignatureHandler
-
addValidationInformation
public boolean addValidationInformation(java.security.KeyStore keystore) throws java.security.GeneralSecurityException, java.io.IOException
Add Long Term Validation information for this signature to the PDF. CallsaddValidationInformation(keystore, null, null)
- 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 information could be added up to a trusted root, or false if some of the links in the chain could not be verified.
- Throws:
java.security.GeneralSecurityException
java.io.IOException
- Since:
- 2.18.2
- See Also:
getValidationInformation()
,TimeStampHandlerFactory
-
addValidationInformation
public boolean addValidationInformation(java.security.KeyStore keystore, java.util.List<PKCS7SignatureHandler.OCSPResponse> ocspResponses, java.util.List<java.security.cert.X509CRL> crls) throws java.security.GeneralSecurityException, java.io.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 byFormSignature.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
andverified
, otherwise anIllegalStateException
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.ocspResponses
- an optional list of pre-existing OCSP responses which should be checked before requesting one. May benull
crls
- an optional list of CRLs which should be checked before requesting one. May benull
- Returns:
- true if all the required validation information could be added up to a trusted root, or false if some of the links in the chain could not be verified.
- Throws:
java.security.GeneralSecurityException
java.io.IOException
- Since:
- 2.28
- See Also:
getValidationInformation()
,TimeStampHandlerFactory
,AcrobatSignatureHandlerFactory
-
getValidationInformation
public java.util.List<PKCS7SignatureHandler.ValidationInformation> getValidationInformation() throws java.security.GeneralSecurityException, java.io.IOException
Returns the long-term validation details for the signature that are embedded in the PDF. Validation may be applied at the time of signing, by making OCSP and CRL requests for the certificates used during signing and embedding that information into the signed document. Or, it may be added after the PDF is signed, by performing the same steps and embedding the information into the PDF as a subsequent revision (with our API, this is done with theaddValidationInformation(java.security.KeyStore)
method). If LTV information is available from either of these stores, then this method returns a List of one or morePKCS7SignatureHandler.ValidationInformation
objects with the details. If no long-term details are included, this method returnsnull
.- Throws:
java.lang.IllegalStateException
- if the associated signature is notFormSignature.STATE_SIGNED
java.security.GeneralSecurityException
- if a signature or certificate exception is encountered while extracting this informationjava.io.IOException
- if the object embedded in the PDF that contain this data are malformed and can't be parsed.- Since:
- 2.18.2
-
queryTimeStampResponse
public static byte[] queryTimeStampResponse(java.net.URL url, byte[] digest, java.lang.String hashAlgorithm, int timeout, javax.net.ssl.SSLSocketFactory sslSocketFactory) throws java.io.IOException, java.security.GeneralSecurityException
This is a helper method that can be called by those implementing their own customPKCS7SignatureHandler.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 fromPKCS7SignatureHandler.SigningEngine.getTimeStampResp(byte[])
.- Parameters:
url
- the URL of the RFC3161 time-stamp server to querydigest
- the digest to signhashAlgorithm
- 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 IOExceptionsslSocketFactory
- 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:
java.io.IOException
java.security.GeneralSecurityException
- Since:
- 2.25.1
-
-