Class SignatureHandler
- java.lang.Object
-
- org.faceless.pdf2.SignatureHandler
-
- Direct Known Subclasses:
EGIZSignatureHandler
,PKCS7SignatureHandler
public abstract class SignatureHandler extends java.lang.Object
This class is the baseline handler for all digital signatures - it could theoretically be used for any type of signature, using biometrics, public/private key and so on. The main implementation is the one returned by
AcrobatSignatureHandlerFactory
. Typically an object of this type will be aPKCS7SignatureHandler
.For 99% of users, it is enough to look at the examples in the
FormSignature
API documentation, which details how to sign and verify documents using the standard handlers. For those wanting to write their own signature handlers however, read on.The SignatureHandler class has several methods which need to be implemented by concrete implementations of this class. They are at a minimum
getFilter()
, theverify()
method (if the handler is to be used to verify signatures), and/or theprepareToSign()
,getMessageDigest()
andsign()
methods if the handler is to be used to sign signatures. In addition, when signing if the signature is to have a visible appearance on the page, something useful should be returned fromgetLayerNames()
andgetLayerAppearance()
.The idea behind the handler is that when signing, first any annotations associated with the signature are created and filled using the values returned from the
getLayerAppearance()
method. Then theprepareToSign()
method is called, which should set all the values in the "V" dictionary and generally do everything required to set up the signature in preparation for signing. Finally thesign()
method is called, it's return value is stored in the "Contents" field.The SignatureHandler works in a similar way to the
EncryptionHandler
class. There are a number ofget...Value
andput...Value
methods which can be used to get/set values in the "V" dictionary of the Signature dictionary. See the discussion in theEncryptionHandler
class documentation for details on how these methods work. As an example, the SelfSign handler includes the following lines in it'sprepareToSign()
method:putNameValue("Filter", "Adobe.PPKLite"); putNameValue("SubFilter", "adbe.x509.rsa_sha1"); putNumericValue("R", 65539); putStringValue("Cert", certificatebytearray);
As a slightly more complicated example, to add
/MyArray [ 100 << /Type /MyHandler >> ]
to the "V" dictionary, just do:putArrayValue("MyArray"); putNumericValue("MyArray.0", 100); putDictionaryValue("MyArray.1"); putNameValue("MyArray.1.Type", "MyHandler");
The
getFilter()
method should return an appropriate value - so again, the SelfSign handler will return the string "Adobe.PPKLite".For a concrete example of a working, if somewhat brain-dead signature handler, see the
DummySignatureHandler.java
example, supplied with the download package.- Since:
- 2.0
- See Also:
FormSignature
,SignatureHandlerFactory
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
SignatureHandler.Placeholder
A Placeholder can be used to mark a point in the PDF which needs to be updated after the signature has been applied
-
Constructor Summary
Constructors Constructor Description SignatureHandler()
-
Method Summary
All Methods Instance Methods Abstract Methods Concrete Methods Modifier and Type Method Description protected boolean
containsKey(java.lang.String key)
Return true if theV
dictionary contains the specified keyprotected int
getArrayValueSize(java.lang.String key)
Return the size of the specified Array from theV
dictionary, or-1
if no such field existsprotected boolean
getBooleanValue(java.lang.String key)
Return a Boolean from theV
dictionary as a boolean orfalse
if no such field existsint
getCertificationType()
Return the type of "Certification" the previously-signed signature this handler is attached to (seegetFormSignature()
attests to.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.protected java.util.Set<java.lang.String>
getDictionaryValueKeys(java.lang.String key)
Return the Set of keys of the specified Dictionary from theV
dictionary, ornull
if no such field exists.int
getEstimatedContentSize(int contentsize)
Return the estimated size of the signature object to be embedded, or <= 0 if this cannot be determined.abstract java.lang.String
getFilter()
Return the name of the filter, eg "Adobe.PPKLite".FormSignature
getFormSignature()
Get theFormSignature
this handler is attaached tojava.lang.String
getHandlerName()
Return the human-readable name of this handlerabstract PDFCanvas
getLayerAppearance(java.lang.String layername, PDFStyle style)
Return aPDFCanvas
for the specified layer.abstract 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.protected abstract java.security.MessageDigest
getMessageDigest()
Return a MessageDigest that will be used to calculate the digest of the PDF for signing.protected java.lang.String
getNameValue(java.lang.String key)
Return a Name from theV
dictionary as a String ornull
if no such field existsprotected float
getNumericValue(java.lang.String key)
Return a Number from theV
dictionary as a float orFloat.NaN
if no such field existsprotected java.io.InputStream
getStreamValue(java.lang.String key)
Return the contents of a Stream from theV
dictionary, orfalse
if no such field existsprotected byte[]
getStringValue(java.lang.String key)
Return a String from theV
dictionary as a byte array ornull
if no such field existsprotected java.lang.String
getTextStringValue(java.lang.String key)
Return a Text String from theV
dictionary as a String ornull
if no such field existsjava.util.Map<java.lang.String,SignatureHandler.Placeholder>
getVariables()
Return the list of "variables" which will be set by the handler after the PDF is rendered.protected void
postDigest(long filelength, java.util.Map<java.lang.String,SignatureHandler.Placeholder> variables)
Update any Variables that need to be updated after the Digest is calculated (eg Contents).protected void
preDigest(long filelength, java.util.Map<java.lang.String,SignatureHandler.Placeholder> variables)
Update any Variables that need to be updated before the Digest is calculated (eg ByteRange).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.protected void
putArrayValue(java.lang.String key)
Add (or replace) an Array to theV
dictionary.protected void
putBooleanValue(java.lang.String key, boolean val)
Add (or replace) a Boolean to theV
dictionary.protected void
putDictionaryValue(java.lang.String key)
Add (or replace) a Dictionary to theV
dictionary.protected void
putNameValue(java.lang.String key, java.lang.String val)
Add (or replace) a Name to theV
dictionary.protected void
putNumericValue(java.lang.String key, float val)
Add (or replace) a Number to theV
dictionary.protected void
putStreamValue(java.lang.String key, byte[] val)
Add (or replace) the contents of a Stream in theV
dictionary.protected void
putStringValue(java.lang.String key, byte[] val)
Add (or replace) a String to theV
dictionary.protected void
putTextStringValue(java.lang.String key, java.lang.String val)
Add (or replace) a Text String to theV
dictionary.protected byte[]
sign()
Finish the digest calculation on the digest returned fromgetMessageDigest()
and return a signature token the signs it.protected abstract boolean
verify(java.io.InputStream in)
Return a boolean indicating whether or not the signature handler can verify the specifiedInputStream
.
-
-
-
Method Detail
-
containsKey
protected boolean containsKey(java.lang.String key)
Return true if theV
dictionary contains the specified key
-
getStringValue
protected final byte[] getStringValue(java.lang.String key)
Return a String from theV
dictionary as a byte array ornull
if no such field exists
-
getTextStringValue
protected final java.lang.String getTextStringValue(java.lang.String key)
Return a Text String from theV
dictionary as a String ornull
if no such field exists
-
getNameValue
protected final java.lang.String getNameValue(java.lang.String key)
Return a Name from theV
dictionary as a String ornull
if no such field exists
-
getNumericValue
protected final float getNumericValue(java.lang.String key)
Return a Number from theV
dictionary as a float orFloat.NaN
if no such field exists
-
getBooleanValue
protected final boolean getBooleanValue(java.lang.String key)
Return a Boolean from theV
dictionary as a boolean orfalse
if no such field exists
-
getArrayValueSize
protected final int getArrayValueSize(java.lang.String key)
Return the size of the specified Array from theV
dictionary, or-1
if no such field exists
-
getDictionaryValueKeys
protected final java.util.Set<java.lang.String> getDictionaryValueKeys(java.lang.String key)
Return the Set of keys of the specified Dictionary from theV
dictionary, ornull
if no such field exists.
-
getStreamValue
protected final java.io.InputStream getStreamValue(java.lang.String key)
Return the contents of a Stream from theV
dictionary, orfalse
if no such field exists- Since:
- 2.6.5
-
putStringValue
protected final void putStringValue(java.lang.String key, byte[] val)
Add (or replace) a String to theV
dictionary. A value ofnull
removes the entry.
-
putTextStringValue
protected final void putTextStringValue(java.lang.String key, java.lang.String val)
Add (or replace) a Text String to theV
dictionary. A value ofnull
removes the entry
-
putNumericValue
protected final void putNumericValue(java.lang.String key, float val)
Add (or replace) a Number to theV
dictionary. A value ofFloat.NaN
removes the entry.
-
putNameValue
protected final void putNameValue(java.lang.String key, java.lang.String val)
Add (or replace) a Name to theV
dictionary. A value ofnull
removes the entry.
-
putBooleanValue
protected final void putBooleanValue(java.lang.String key, boolean val)
Add (or replace) a Boolean to theV
dictionary.
-
putArrayValue
protected final void putArrayValue(java.lang.String key)
Add (or replace) an Array to theV
dictionary.
-
putDictionaryValue
protected final void putDictionaryValue(java.lang.String key)
Add (or replace) a Dictionary to theV
dictionary.
-
putStreamValue
protected final void putStreamValue(java.lang.String key, byte[] val)
Add (or replace) the contents of a Stream in theV
dictionary.- Since:
- 2.6.5
-
getHandlerName
public java.lang.String getHandlerName()
Return the human-readable name of this handler- Since:
- 2.18.2
-
getVariables
public java.util.Map<java.lang.String,SignatureHandler.Placeholder> getVariables() throws java.security.GeneralSecurityException
Return the list of "variables" which will be set by the handler after the PDF is rendered. Entries in the returned map should have a
String
as a key and aSignatureHandler.Placeholder
as a value. These placeholders will be inserted into the PDF at the correct points.For most SignatureHandlers, the only variables are the "ByteRange" and "Contents" array containing the signature token, which is what this method returns (it may be overridden if more variables are required).
This method was updated for a new signing architecture in release 2.11.12.
- Returns:
- a Map containing the variables to be substituted into the PDF during signing
- Throws:
java.security.GeneralSecurityException
- Since:
- 2.3
- See Also:
AcrobatSignatureHandlerFactory.setContentSize(int)
-
getEstimatedContentSize
public int getEstimatedContentSize(int contentsize)
Return the estimated size of the signature object to be embedded, or <= 0 if this cannot be determined. The default implementation returns 0.- Parameters:
contentsize
- the negation of any value previously passed intosetContentSize(int)
- Since:
- 2.11.21
-
getFilter
public abstract java.lang.String getFilter()
Return the name of the filter, eg "Adobe.PPKLite".
-
preDigest
protected void preDigest(long filelength, java.util.Map<java.lang.String,SignatureHandler.Placeholder> variables) throws java.lang.Exception
Update any Variables that need to be updated before the Digest is calculated (eg ByteRange).- Parameters:
filelength
- the length of the PDF file, in bytesvariables
- the Map of variables, ordered by their position in the file.- Throws:
java.lang.Exception
- Since:
- 2.11.12
-
postDigest
protected void postDigest(long filelength, java.util.Map<java.lang.String,SignatureHandler.Placeholder> variables) throws java.lang.Exception
Update any Variables that need to be updated after the Digest is calculated (eg Contents).- Parameters:
filelength
- the length of the PDF file, in bytesvariables
- the Map of variables, ordered by their position in the file.- Throws:
java.lang.Exception
- Since:
- 2.11.12
-
sign
protected byte[] sign() throws java.security.GeneralSecurityException, java.io.IOException
Finish the digest calculation on the digest returned from
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
getVariables()
method is also to call this method with an empty digest, to determine the size of the token to store in the PDF (thegetMessageDigest()
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 owngetVariables()
method.- 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- Since:
- 2.10 (this method existed earlier but took an InputStream as a parameter, and was required to create the digest now returned from
getMessageDigest()
internally)
-
getMessageDigest
protected abstract java.security.MessageDigest getMessageDigest()
Return a MessageDigest that will be used to calculate the digest of the PDF for signing. This message will be called beforesign()
- see the API docs for that method for more details.- Since:
- 2.10
-
verify
protected abstract boolean verify(java.io.InputStream in) throws java.security.GeneralSecurityException, java.io.IOException
Return a boolean indicating whether or not the signature handler can verify the specifiedInputStream
.- 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
-
prepareToSign
protected void prepareToSign(java.security.KeyStore keystore, java.lang.String alias, char[] password) throws java.security.GeneralSecurityException
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.- Parameters:
keystore
- the KeyStorealias
- which key to usepassword
- the password to use to decode the key- Throws:
java.security.GeneralSecurityException
-
getLayerNames
public abstract 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. 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" ]
.- Returns:
- the ordered list of layer names that should to used to create a visible representation of this signature on a page.
- See Also:
getLayerAppearance(java.lang.String, org.faceless.pdf2.PDFStyle)
-
getLayerAppearance
public abstract PDFCanvas getLayerAppearance(java.lang.String layername, PDFStyle style)
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.- Parameters:
layername
- the layer to create (from the list returned bygetLayerNames()
)style
- the style in which to draw the text, if any- Returns:
- a new
PDFCanvas
of any size containing the specified layer. - See Also:
getLayerNames()
-
getDefaultName
public 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.- Since:
- 2.11
-
getFormSignature
public FormSignature getFormSignature()
Get theFormSignature
this handler is attaached to- Since:
- 2.11.12
-
getCertificationType
public int getCertificationType()
Return the type of "Certification" the previously-signed signature this handler is attached to (seegetFormSignature()
attests to. One ofFormSignature.CERTIFICATION_UNCERTIFIED
,FormSignature.CERTIFICATION_NOCHANGES
,FormSignature.CERTIFICATION_ALLOWFORMS
orFormSignature.CERTIFICATION_ALLOWCOMMENTS
. By default this method returns the certification from the standard PDF Signature certification dictionary, but subclasses can return their own restriction if necessary by overriding this method.- Since:
- 2.13
- See Also:
FormSignature.getCertificationType()
,FormSignature.setCertificationType(int, java.lang.String)
-
-