Class FormSignature
- java.lang.Object
-
- org.faceless.pdf2.FormElement
-
- org.faceless.pdf2.FormSignature
-
- All Implemented Interfaces:
Cloneable
public class FormSignature extends FormElement
This class represents a public key "Digital Signature" which can be used to sign a PDF document. Signatures from existing documents can be verified and new signatures can be added.
Signatures may be applied and verified using the full version of Acrobat, but not Acrobat Reader. Verifying or creating a Signature requires a "Handler", both in our library and Acrobat. Acrobat 4 and 5 had "self-signed" signatures, and a plugin from VeriSign was available, but Acrobat 6 and later are supplied with a handler supporting full key management. Signatures targeting this handler can be created using an
AcrobatSignatureHandlerFactory.Since version 2.0, the framework is in place to allow custom signature handlers to be written. This means that with the right
SignatureHandler, the library can be used to create or verify any type of digital signature. The library is distributed with theAcrobatSignatureHandlerFactory, which we recommend using, as well as the older#HANDLER_VERISIGNand#HANDLER_SELFSIGNfactories. All of these handlers use the standardKeyStoreclass supplied with Java, and do not necessarily need any third party libraries to work.A feature of PDF is that only a single
STATE_PENDINGsignature can be applied to a PDF - ie. when saving a document, only a single signature may be applied. If multiple signatures must be applied then another signature may be added and the PDF saved again.So how do you use this class? The following examples show how to sign and verify documents using the supplied signature handlers.
Verifying existing signatures
To verify a document has been signed and not altered since signing, and to be sure of the signatory, three steps are required. These three steps apply to any type of digital signature, not just PKI (Public Key Infrastuction) signatures, but for these examples we'll focus on the PKI signatures only.
- You must verify that content of the document matches the signature
- You must verify that the signature covers the whole document
- You must verify that the key used to sign the document belongs to who it says it does
First, verifying that the signature matches the document content is done using the
verify()method. This can be done like so:PDF pdf = new PDF(new PDFReader(new FileInputStream(args[0]))); Map elements = pdf.getForm().getElements(); for (Iterator i=elements.values().iterator(); i.hasNext();) { FormElement e = (FormElement)i.next(); if (e instanceof FormSignature && ((FormSignature)e).verify()) { System.out.println("Signature from "+sig.getName()+" matches PDF checksum"); } }Second, you must verify that the signature covers the latest revision of the document - otherwise the document could have been altered after signing (see the
PDFReaderclass documentation for more information about revisions). To verify the signature covers the latest revision, you need to compare the value ofPDF.getNumberOfRevisions()with the value ofgetNumberOfRevisionsCovered(). Something like this should do it:int pdfrevision = pdf.getNumberOfRevisions(); int sigrevision = signature.getNumberOfRevisionsCovered(); if (pdfrevision == sigrevision) { System.out.println("Whole document is covered"); }At this point you know the signature covers the whole document, and that the document hasn't been changed since signing. You then need to confirm that the PDF really was signed by the name on the signature. The handlers supplied with this library are all based on PKCS#7, and contain a chain of X.509 certificates which should be verified. A full discussion of Public Key Infrastructure could fill a book in itself, so instead we'll show you how to get the certificates and how to verify them against a keystore.
Each Java distribution comes with a list of CA certificates which are used to verify signed JAR files, but if your signature is signed by one of those CA's we can also use it to verify the signature (if not, you can supply your own keystore with CA certificates - the principle is the same). The certificates are accessed via the
PKCS7SignatureHandler.getCertificates()method, and theisValidCertificatemethod used to perform some basic validation if you want to check the certificates yourself. Here we use theverifyCertificatesmethod to confirm the certificates are valid and signed by a CA:PDF pdf = new PDF(new PDFReader(new FileInputStream(args[0]))); KeyStore ca = FormSignature.loadDefaultKeyStore(); // Load CA certificates for (Iterator i=pdf.getForm().getElements().values().iterator(); i.hasNext();) { FormElement e = (FormElement)i.next(); if (e instanceof FormSignature) { FormSignature sig = (FormSignature)e; if (sig.getSignatureHandler() instanceof PKCS7SignatureHandler) { PKCS7SignatureHandler handler = (PKCS7SignatureHandler)sig.getSignatureHandler(); Calender when = sig.getSignDate(); X509Certificate[] certs = handler.getCertificates(); if (FormSignature.verifyCertificates(certs, ca, null, when) == null) { System.out.println("Certificates for "+sig.getName()+" verified"); } } else { System.out.println("Not a PKCS#7 public-key signature!"); } } }Signing documents
A single signature can be applied to a PDF document by adding the signature to the PDF documents Form. Here's an example:
PDF pdf = new PDF(); pdf.newPage("A4"); KeyStore keystore = loadMyKeyStore(); // Somehow load a keystore String alias = "mykey"; char[] password = "secret".toCharArray(); SignatureHandlerFactory factory = new AcrobatSignatureHandlerFactory(); FormSignature sig = new FormSignature(keystore, alias, password, factory); pdf.getForm().addElement("Test Signature", sig);This slightly oversimplified example demonstrates two things. One, that the private key and its associated certificates used to sign a document must be loaded from a
KeyStore, and two, that you must specify the signature handler that will be used to verify the document in Acrobat.Since Acrobat 6.0, theoretically any PKCS#7 signature can be verified without an external plugin - simply use the
AcrobatSignatureHandlerFactoryfactory. Prior to Acrobat 6, the situation is more complex - you must create a signature for a specific handler (typically using#HANDLER_SELFSIGNor#HANDLER_VERISIGN).Finally to get you started, here is a complete example showing how to create a PDF that can be verified in Acrobat 6.0 or later. Rather than type all this out we suggest you take a look at the "Sign.java" example supplied with the package, which does all this and more.
-
Create a self-signed key using the "keytool" program supplied with the JDK.
The following command will create a 1024-bit RSA key plus certificate in
the file "mykeystore". You'll be prompted for a password.
keytool -genkey -alias mykey -keyalg RSA -sigalg MD5withRSA \ -keystore mykeystore.jks -dname 'C=UK, O=YourOrganization, CN=YourName' -
The following code can be used to create a blank PDF which is digitally signed with this key.
import java.security.KeyStore; import java.io.*; import org.faceless.pdf2.*; public static void TestSign { static final String KEYFILE = "mykeystore.jks"; // Keystore filename static final String KEYALIAS = "mykey"; // Alias for private key static final char[] PASSWORD = "secret".toCharArray(); // Password public static void main(String[] args) throws Exception { PDF pdf = new PDF(); PDFPage page = pdf.newPage("A4"); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(new FileInputStream(KEYFILE), PASSWORD); SignatureHandlerFactory factory = new AcrobatSignatureHandlerFactory(); FormSignature sig = new FormSignature(keystore, KEYALIAS, PASSWORD, factory); pdf.getForm().addElement("Test Signature", sig); pdf.render(new FileOutputStream("Signed.pdf")); } } -
Run the program - it creates "Signed.pdf" which can be verified in Acrobat 6.0 or greater.
java TestSign
More information on digital signatures is available in the userguide.
- Since:
- 1.1.13
- See Also:
AcrobatSignatureHandlerFactory,PKCS7SignatureHandler
-
-
Field Summary
Fields Modifier and Type Field Description static intCERTIFICATION_ALLOWCOMMENTSA value that can be passed in tosetCertificationType(int, java.lang.String)and returned fromgetCertificationType()to indicate that the signature will be a certifying signature that allows only commenting and form fill-in actions on the Document.static intCERTIFICATION_ALLOWFORMSA value that can be passed in tosetCertificationType(int, java.lang.String)and returned fromgetCertificationType()to indicate that the signature will be a certifying signature that allows only form fill-in actions on the Document.static intCERTIFICATION_NOCHANGESA value that can be passed in tosetCertificationType(int, java.lang.String)and returned fromgetCertificationType()to indicate that the signature will be a certifying signature that disallows any changes to the Document.static intCERTIFICATION_UNCERTIFIEDA value that can be passed in tosetCertificationType(int, java.lang.String)and returned fromgetCertificationType()to indicate that the signature will not be a certifying signature.static SignatureHandlerFactoryHANDLER_ACROBATSIXA type of handler representing the general purpose PKI signature plugin supplied with Acrobat 6.0 and later.static intSTATE_BLANKThis value is returned from thegetState()method if the signature field has not been completed yet.static intSTATE_PENDINGThis value is returned from thegetState()method if the signature is "new" - it has been added to the document and is waiting for the document to be completed before it is applied.static intSTATE_SIGNEDThis value is returned from thegetState()method if the signature is "old" - the PDF document that was read in was already signed with this signature.
-
Constructor Summary
Constructors Constructor Description FormSignature()Create a newblankdigital signature field.FormSignature(KeyStore keystore, String alias, char[] password, SignatureHandlerFactory factory)Create a newpendingdigital signature to sign a PDF document.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Deprecated Methods Modifier and Type Method Description WidgetAnnotationaddAnnotation(PDFPage page, float x1, float y1, float x2, float y2)Add an annotation for this Signature to the specified page at the specified location.WidgetAnnotationaddAnnotation(PDFPage page, float x1, float y1, float x2, float y2, PDFCanvas appearance)Add an annotation for this Signature to the specified page at the specified location, with the specified appearance.voidcancelVerify()If a verification is currently running, cancel it.protected Objectclone()static List<Object>findTrustChain(X509Certificate signer, Date date, Collection<X509Certificate> certificates, Collection<KeyStore> keystores, Collection<Object> revoked, Provider provider)Attempt to build a chain of trust from an X.509 Certificate to one or moreKeystoresby stepping through a collection of other certificates.long[]getByteRangeCovered()Return the bytes of the PDF file covered by this signature.intgetCertificationType()Return the type of "Certification" this signature attests to.StringgetContactInfo()Return the contact information field for this signature if that information is available, ornullotherwise.StringgetFilter()Return the name of the digital signature handler used to sign the document.static StringgetIssuerField(X509Certificate cert, String field)Return the specified X.500 field from the specified X.509 certificates Issuer.StringgetLocation()Return the location where this document was signed if if that information is available, ornullotherwise.StringgetName()Get the name of the person or entity that signed this PDF if that information is available, ornullotherwise.intgetNumberOfRevisionsCovered()Return the number of document revisions covered by this signature.StringgetReason()Return the reason this signature was applied to the PDF if that information is available, ornullotherwise.URIgetRequiredCertificateFallbackURI()Return the URI to be used if the "issuers" and "subjects" Certificate restrictions are not met, as set bysetRequiredCertificateFallbackURI(java.net.URI), ornullif none were specified.X509Certificate[]getRequiredCertificateIssuers()Return the list of required Issuer certificates as set bysetRequiredCertificateIssuers(java.security.cert.X509Certificate[]), ornullif none were specified.X509Certificate[]getRequiredCertificateSubjects()Return the list of required Issuer certificates as set bysetRequiredCertificateSubjects(java.security.cert.X509Certificate[]), ornullif none were specified.String[]getRequiredDigestAlgorithms()Return the list of allowable digest algorithms that can be used to sign this signature, ornullif this is not specified.String[]getRequiredReasons()Set the list of reasons that must be chosen from when signing, as set bysetRequiredReasons(java.lang.String[])URIgetRequiredTimestampServer()Get the URI of the TimeStamp server that must be used when signing as set bysetRequiredTimestampServer(java.net.URI), ornullif none is specifiedSignatureHandlergetSignatureHandler()Return theSignatureHandlerthat is used with this Signature, ornullif the signature has not been signed yet (ie. the state is stillSTATE_BLANK).SignaturePolicygetSignaturePolicy()Return theSignaturePolicythat was previously set bysetSignaturePolicy(org.faceless.pdf2.SignaturePolicy)CalendargetSignDate()Return the time the signature was applied to the document.intgetState()Returns the current state of the signature.static StringgetSubjectField(X509Certificate cert, String field)Return the specified X.500 field from the specified X.509 certificates Subject.StringgetValue()As signatures do not have a "value" as such, this method always returns null.static booleanisValidCertificate(X509Certificate cert, CRL crl, Date signdate)Return true if the specified X.509 Certificate is valid for the specified date, has not been revoked and has no unknown critical extensions.booleanisVerifying()Return true if theverify()method is currently running in another thread.static KeyStoreloadAKFKeyStore(InputStream in)Load an X.509 certificate from an "Adobe Key File" keystore, the type exported from the Adobe Self-Sign signature handler in Acrobat 4.0.static KeyStoreloadDefaultKeyStore()Deprecated.call loadTrustedKeyStore("java") instead.static KeyStoreloadFDFKeyStore(InputStream in)Load an X.509 certificate from an "Adobe Self-Sign Key" keystore, the type exported from the Adobe Self-Sign signature handler in Acrobat 5.0.static KeyStoreloadPKCS7KeyStore(InputStream in)Load a list of one or more X.509 certificates from a PKCS#7 file.static KeyStoreloadTrustedKeyStore()Deprecated.call loadTrustedKeyStore("eidas") instead.static KeyStoreloadTrustedKeyStore(String source)Return the specified "trusted"KeyStorewhich is shipped with the API.voidrebuild()Cause the annotation list to be rebuilt.static voidregisterHandlerForVerification(SignatureHandlerFactory factory)This method must be called to register a newSignatureHandlerFactorythat can be used when verifying signatures, although it's not necessary for handlers that are only used for signing.voidsetCertificationType(int certificationtype, String attestation)Causes this signatures be "Certifying" signature when it's signed - also known as an "Author" signature..voidsetContactInfo(String info)Set the contact information field for this signature.voidsetLocation(String location)Set the location where the signer is signing the PDF document - e.g.voidsetName(String name)Set the name of the person or entity who is applying this signature.voidsetReason(String reason)Set the reason why the the document is being signed - e.g.voidsetRequiredCertificateFallbackURI(URI uri)Set the URI the user is directed to if the conditions set bysetRequiredCertificateIssuers(java.security.cert.X509Certificate[])andsetRequiredCertificateSubjects(java.security.cert.X509Certificate[])are not met.voidsetRequiredCertificateIssuers(X509Certificate[] certs)Set restrictions on which X.509 Certificates can be used when this (blank) signature is eventually signed.voidsetRequiredCertificateSubjects(X509Certificate[] certs)Set restrictions on which X.509 Certificates can be used when this (blank) signature is eventually signed.voidsetRequiredDigestAlgorithms(String[] algorithms)Set the list of allowable digest algorithms that can be used to sign this signature, ornullto remove any existing restrictions.voidsetRequiredReasons(String[] validreasons)Set the list of Reasons from which the user must choose when this (blank) signature is eventually signed.voidsetRequiredTimestampServer(URI uri)Set the URI of the TimeStamp server that must be used when this (blank) signature is eventually signed.voidsetSignaturePolicy(SignaturePolicy policy)Set theSignaturePolicythat should be used when validating this Signature.voidsign(KeyStore keystore, String alias, char[] password, SignatureHandlerFactory factory)Sign aSTATE_BLANKdigital signature.StringtoString()booleanverify()Verify a signature by ensuring that the PDF document hasn't been altered since it was signed.static X509CertificateverifyCertificates(X509Certificate[] certs, KeyStore keystore, CRL crl, Calendar signdate)Verify a list of X.509 certificates against a list of trusted certificates.-
Methods inherited from class org.faceless.pdf2.FormElement
addPropertyChangeListener, duplicate, flatten, getAction, getAnnotation, getAnnotations, getDescription, getForm, isReadOnly, isRequired, isSubmitted, removePropertyChangeListener, setAction, setDescription, setReadOnly, setRequired, setSubmitted
-
-
-
-
Field Detail
-
CERTIFICATION_UNCERTIFIED
public static final int CERTIFICATION_UNCERTIFIED
A value that can be passed in tosetCertificationType(int, java.lang.String)and returned fromgetCertificationType()to indicate that the signature will not be a certifying signature. This is the default.- Since:
- 2.7.4
- See Also:
- Constant Field Values
-
CERTIFICATION_NOCHANGES
public static final int CERTIFICATION_NOCHANGES
A value that can be passed in tosetCertificationType(int, java.lang.String)and returned fromgetCertificationType()to indicate that the signature will be a certifying signature that disallows any changes to the Document. No legal attestation is required in this case, as the document cannot be changed.- Since:
- 2.7.4
- See Also:
- Constant Field Values
-
CERTIFICATION_ALLOWFORMS
public static final int CERTIFICATION_ALLOWFORMS
A value that can be passed in tosetCertificationType(int, java.lang.String)and returned fromgetCertificationType()to indicate that the signature will be a certifying signature that allows only form fill-in actions on the Document. Specifically, existing form fields can be modified, but the position of those fields cannot be changed, and no fields can be added or deleted (this includes adding new signatures, although pre-existing blank signature fields can be signed). Other annotations cannot be changed. A legal attestation is recommended if this type of certification is used.- Since:
- 2.7.4
- See Also:
- Constant Field Values
-
CERTIFICATION_ALLOWCOMMENTS
public static final int CERTIFICATION_ALLOWCOMMENTS
A value that can be passed in tosetCertificationType(int, java.lang.String)and returned fromgetCertificationType()to indicate that the signature will be a certifying signature that allows only commenting and form fill-in actions on the Document. Specifically, existing form fields can have their values modified and the position of their annotations can be changed. New signature fields can be added, but other types of field cannot and no fields can be deleted. Other types of annotation can be added or deleted. A legal attestation is recommended if this type of certification is used.- Since:
- 2.7.4
- See Also:
- Constant Field Values
-
HANDLER_ACROBATSIX
public static final SignatureHandlerFactory HANDLER_ACROBATSIX
A type of handler representing the general purpose PKI signature plugin supplied with Acrobat 6.0 and later. This handler (which has the Filter name "Adobe.PPKLite") is an instanceof of
AcrobatSignatureHandlerFactory, and while it can be used, for maximum flexiblity we recommend creating your own instance of that class and setting whichever options you required.- Since:
- 2.0
-
STATE_SIGNED
public static final int STATE_SIGNED
This value is returned from thegetState()method if the signature is "old" - the PDF document that was read in was already signed with this signature. The signature may be validated, but will not be exported again if the document is resaved.- See Also:
STATE_PENDING,STATE_BLANK,getState(), Constant Field Values
-
STATE_PENDING
public static final int STATE_PENDING
This value is returned from thegetState()method if the signature is "new" - it has been added to the document and is waiting for the document to be completed before it is applied. Only one "pending" signature may currently be applied to each document.- See Also:
STATE_SIGNED,STATE_BLANK,getState(), Constant Field Values
-
STATE_BLANK
public static final int STATE_BLANK
This value is returned from thegetState()method if the signature field has not been completed yet. A document may contain more than one blank signature fields.- See Also:
STATE_SIGNED,STATE_PENDING, Constant Field Values
-
-
Constructor Detail
-
FormSignature
public FormSignature()
Create a newblankdigital signature field. The field may have a signature applied to it at a later date, either by this library or by Acrobat- Since:
- 2.0
-
FormSignature
public FormSignature(KeyStore keystore, String alias, char[] password, SignatureHandlerFactory factory) throws GeneralSecurityException, IllegalArgumentException
Create a newpendingdigital signature to sign a PDF document. The private key and the certificates used to sign the PDF are contained in the specified keystore. This constructor is identical to calling:FormSignature sig = new FormSignature(); sig.sign(keystore, alias, password, factory);
- Parameters:
keystore- the KeyStore containing the private key and a list of certificates to sign the document withalias- the alias or "friendly-name" which the private key is stored under in the keystorepassword- the password to unlock the private keyfactory- the digital signature handler that will be used to verify the signature. Probably one of#HANDLER_SELFSIGNor#HANDLER_VERISIGN- Throws:
GeneralSecurityException- if the keystore, private key, password or certificates are invalid in any wayIllegalArgumentException- if the arguments are technically correct but will result in an invalid signature for any reason.- Since:
- 2.0 (prior to 2.0 the last parameter was an integer)
-
-
Method Detail
-
registerHandlerForVerification
public static void registerHandlerForVerification(SignatureHandlerFactory factory)
This method must be called to register a new
SignatureHandlerFactorythat can be used when verifying signatures, although it's not necessary for handlers that are only used for signing.When a signature is verified, the appropriate handler is chosen from the list of registered handlers by matching the "Filter" and "SubFilter" fields in the handler to those in the signature. By default, the
#HANDLER_VERISIGN,#HANDLER_SELFSIGNandHANDLER_ACROBATSIXfactories are the only three that are registered.- Since:
- 2.0
-
addAnnotation
public WidgetAnnotation addAnnotation(PDFPage page, float x1, float y1, float x2, float y2)
Add an annotation for this Signature to the specified page at the specified location. Unlike other form elements, it is not necessary for a signature to have an annotation - those that don't are called "invisible" signatures in Acrobat. The annotation will take on the appearance defined by the
SignatureHandler.getLayerAppearance()method.Note that Acrobat 9 and later will only support one annotation per signature.
- Parameters:
page- the page to place the annotation onx1- the left-most X co-ordinate of the annotationy1- the top-most Y co-ordinate of the annotationx2- the right-most X co-ordinate of the annotationy2- the bottom-most Y co-ordinate of the annotation- Returns:
- a new WidgetAnnotation at the specified location
- Since:
- 2.0
-
addAnnotation
public WidgetAnnotation addAnnotation(PDFPage page, float x1, float y1, float x2, float y2, PDFCanvas appearance)
Add an annotation for this Signature to the specified page at the specified location, with the specified appearance. Unlike other form elements, it is not necessary for a signature to have an annotation - those that don't are called "invisible" signatures in Acrobat.
Note that Acrobat 9 and later will only support one annotation per signature.
- Parameters:
page- the page to place the annotation onx1- the left-most X co-ordinate of the annotationy1- the top-most Y co-ordinate of the annotationx2- the right-most X co-ordinate of the annotationy2- the bottom-most Y co-ordinate of the annotationappearance- the PDFCanvas to use as the primary appearance of the signature.- Returns:
- a new WidgetAnnotation at the specified location
- Since:
- 2.23.5
-
sign
public void sign(KeyStore keystore, String alias, char[] password, SignatureHandlerFactory factory) throws GeneralSecurityException, IllegalArgumentException
Sign aSTATE_BLANKdigital signature. The private key and the certificates used to sign the PDF are contained in the specified keystore.- Parameters:
keystore- the KeyStore containing the private key and a list of certificates to sign the document withalias- the alias or "friendly-name" which the private key is stored under in the keystorepassword- the password to unlock the private keyfactory- the digital signature handler that will be used to verify the signature. Probably one of#HANDLER_SELFSIGNor#HANDLER_VERISIGN- Throws:
GeneralSecurityException- if the keystore, private key, password or certificates are invalid in any wayIllegalArgumentException- if the arguments are technically correct but will result in an invalid signature for any reason.- Since:
- 2.0
-
getState
public int getState()
Returns the current state of the signature. The state is eitherSTATE_SIGNEDfor existing signatures,STATE_PENDINGfor new signatures that have been added, orSTATE_BLANKfor empty signature fields
-
setName
public void setName(String name)
Set the name of the person or entity who is applying this signature. Setting this field is recommended but not necessary - for PKCS#7 signatures, it defaults to the Common Name (CN) of the signing certificate.- Parameters:
name- the name of the entity signing the PDF, ornullto clear the current name- Throws:
IllegalStateException- if this signature isSTATE_BLANK
-
getName
public String getName()
Get the name of the person or entity that signed this PDF if that information is available, ornullotherwise.- Throws:
IllegalStateException- if this signature isSTATE_BLANK
-
setReason
public void setReason(String reason)
Set the reason why the the document is being signed - e.g. "Approved for distribution". This field is optional.- Parameters:
reason- the reason the entity is signing the document, ornullto clear the current reason- Throws:
IllegalStateException- if this signature isSTATE_BLANK
-
getReason
public String getReason()
Return the reason this signature was applied to the PDF if that information is available, ornullotherwise.- Throws:
IllegalStateException- if this signature isSTATE_BLANK
-
setLocation
public void setLocation(String location)
Set the location where the signer is signing the PDF document - e.g. "Head Office". This field is optional.- Parameters:
location- the location where the entity is signing the document, ornullto clear the current location- Throws:
IllegalStateException- if this signature isSTATE_BLANK
-
getLocation
public String getLocation()
Return the location where this document was signed if if that information is available, ornullotherwise.- Throws:
IllegalStateException- if this signature isSTATE_BLANK
-
setContactInfo
public void setContactInfo(String info)
Set the contact information field for this signature. This information would typically be provided by the signer to enable a recipient to contact the signer to verify the signature. This field is optional.- Parameters:
info- the contact information for this signature, ornullto clear the current value- Throws:
IllegalStateException- if this signature isSTATE_BLANK- Since:
- 2.7.1
-
getContactInfo
public String getContactInfo()
Return the contact information field for this signature if that information is available, ornullotherwise.- Throws:
IllegalStateException- if this signature isSTATE_BLANK- Since:
- 2.7.1
-
getSignDate
public Calendar getSignDate()
Return the time the signature was applied to the document. If the signature has been timestamped, this will be the date from the timestamp, otherwise it will be the date from the signature dictionary.- Returns:
- the time the document was signed.
- Throws:
IllegalStateException- if this signature isn'tSTATE_SIGNED
-
getFilter
public String getFilter()
Return the name of the digital signature handler used to sign the document. This is the value of the "Filter" field from the signature handler being used. Values could well be one of "Adobe.PPKLite", "VeriSign.PPKVS", "Entrust.PPKEF", "CICI.SignIt", "Gemtools.GemSign" or "Silanis.ApproveIt". This method is identical to callinggetSignatureHandler().getFilter()- Throws:
IllegalStateException- if this signature isSTATE_BLANK- Since:
- 2.0 (was renamed from "getType" in 1.2.x release)
-
getSignatureHandler
public SignatureHandler getSignatureHandler()
Return theSignatureHandlerthat is used with this Signature, ornullif the signature has not been signed yet (ie. the state is stillSTATE_BLANK).- Since:
- 2.0
-
setSignaturePolicy
public void setSignaturePolicy(SignaturePolicy policy)
Set the
SignaturePolicythat should be used when validating this Signature. The Signature Policy describes the set of conditions that must for the signature to remain valid when the PDF is modified after signing. Setting the policy in the signature changes nothing permanent - it just changes the policy that will be used the next timeverify()is called.By default the policy is
SignaturePolicy.getDefault(), and unless you have a good reason we suggest leaving that unchanged. However if you're trying to reproduce a validation that was made several years ago (ie. at the time of signing), an alternative policy can be used.- Since:
- 2.28
- See Also:
SignaturePolicy
-
getSignaturePolicy
public SignaturePolicy getSignaturePolicy()
Return theSignaturePolicythat was previously set bysetSignaturePolicy(org.faceless.pdf2.SignaturePolicy)- Returns:
- the Signature Policy
- Since:
- 2.28
-
isVerifying
public boolean isVerifying()
Return true if theverify()method is currently running in another thread.verify()is not synchronized (as of 2.28) but can only be run in one thread at a time.- Since:
- 2.28
- See Also:
verify(),cancelVerify()
-
cancelVerify
public void cancelVerify()
If a verification is currently running, cancel it. Theverify()method will throw aRuntimeExceptionwith a cause that is anInterruptedException. If verify is not running this method has no effect.- Since:
- 2.28
- See Also:
verify(),isVerifying()
-
verify
public boolean verify() throws GeneralSecurityExceptionVerify a signature by ensuring that the PDF document hasn't been altered since it was signed. Only signatures with a state of
STATE_SIGNEDmay be verified.Calling this method on a Certified signature causes additional checks to be run to confirm subsequent changes to the signature haven't invalidated the signature - if the signature checksum is valid but a subsequent modification to the file was disallowed, this method will return false.
Note that this only ensures the document matches the checksum included in the signature object. To completely confirm the document is unaltered the signature object must be confirmed to belong to who it says it does. For the supplied handlers, this is done by checking the X.509 certificates returned by
PKCS7SignatureHandler.getCertificates(), either manually or by calling theverifyCertificatesmethod.Verification is synchronized internally, so before calling this method we suggest checking if a verify is already running with
isVerifying(). Verification can be cancelled by callingcancelVerify(). Both these methods are new in 2.28- Returns:
trueif the document is unaltered,falseif the document has been altered since signing- Throws:
IllegalStateException- if the signature you're verifying isn'tSTATE_SIGNED, or if this method is running in another Thread.GeneralSecurityException- if the specified signing algorithm is unknown, or the certificate or key are invalidRuntimeException- wrapping anInterruptedExceptionif thecancelVerify()method was called while verifying.- See Also:
isVerifying(),cancelVerify()
-
getNumberOfRevisionsCovered
public int getNumberOfRevisionsCovered()
Return the number of document revisions covered by this signature. A PDF document can be revised a number of times - for example, filling out a form in Acrobat and saving the document creates a new revision. Every revision of the document must be covered by a signature in order to be sure of the documents contents. See thePDFReaderclass for more information on document revisions, and the class documentation for this class for examples of how to validate a signature using this method.- Returns:
- the number of revisions covered by this signature (always greater than or equal to one since version 2.7 of this library) or zero if the signature doesn't cover any (in which case it should be discounted)
- Throws:
IllegalArgumentException- if the signature is not signed yet (ie. does not have a state ofSTATE_SIGNED)- Since:
- 1.2.1
-
getByteRangeCovered
public long[] getByteRangeCovered()
Return the bytes of the PDF file covered by this signature. The returned array is theoretically any multiple of four, long, but in practice should always be four bytes, with the first byte "0", the second byte the start of the signature block - 1, the third byte the end of the signature block + 1 and the last byte the length of the revision coverered by this signature (for a file with a single revision, this will be the length of the file).
These requirements are verified as part of the
getNumberOfRevisionsCovered()method, which is the method you should call if you're trying to verify the file. It's anticipated that ths method will be more useful for those trying to insert a signature into the PDF after it's been created, asynchronously:long[] range = signature.getByteRangeCovered(); long offset = range[1] + 1; long len = range[2] - range[1]; // insert signature bytes between off and off+len
- Since:
- 2.24.4
-
verifyCertificates
public static X509Certificate verifyCertificates(X509Certificate[] certs, KeyStore keystore, CRL crl, Calendar signdate) throws GeneralSecurityException
Verify a list of X.509 certificates against a list of trusted certificates. Note that while this method does handle cross-signed certificates when given the full list of certificates from the signature, it may not if called in different ways. As of 2.29.4 this method is now a wrapper on the following code:
X509Certificate verifyCertificates(X509Certificate[] certs, KeyStore keystore, CRL crl, Calendar date) throws GeneralSecurityException { Collection<KeyStore> keystores = Collections<KeyStore>singleton(keystore); Collection<Object> revoked = Collections<Object>singleton(crl); List<Object> chain = findTrustChain(certs[0], date.getTime(), Arrays.asList(certs), keystores, revoked, null); if (chain.isEmpty()) { return certs[0]; // signer certificate itself is invalid } Object end = chain.get(chain.size() - 1); return end instanceof X509Certificate ? (X509Certificate)end : null; }- Parameters:
certs- theX509Certificatelist to verify. Usually this is the return result fromPKCS7SignatureHandler.getCertificates()keystore- theKeyStorecontaining one or more trusted certificates to verify the certificate chain against, ornullto fail at the last certificate in the chain.crl- the Certificate Revocation List to check the certificates against. May benull.signdate- the date the documents was signed. Usually the output ofgetSignDate()- Returns:
- the first certificate in the chain that couldn't be * verified, or
nullif all were verified against a certificate from the keystore. - Throws:
GeneralSecurityException- if the KeyStore or any of the certificates are invalid.- Since:
- 2.0
- See Also:
PKCS7SignatureHandler.getCertificates(),loadTrustedKeyStore(java.lang.String)
-
findTrustChain
public static List<Object> findTrustChain(X509Certificate signer, Date date, Collection<X509Certificate> certificates, Collection<KeyStore> keystores, Collection<Object> revoked, Provider provider) throws KeyStoreException
Attempt to build a chain of trust from an X.509 Certificate to one or more
Keystoresby stepping through a collection of other certificates. Functionally the same asverifyCertificates(java.security.cert.X509Certificate[], java.security.KeyStore, java.security.cert.CRL, java.util.Calendar), this method returns information on the whole chain of trust which may be useful when verifying a chain involving cross-signed intermediate certificates. It also handles multiple trusted KeyStores and customProviders. different Providers.If a path is found from the signer Certificate to one of the supplied KeyStores, the shortest path will be returned as a list, starting with the signing certificate, then the certificate that signed that and so on, with the final two items the certificate from the KeyStore, then the KeyStore itself.
If no path is found from the signer Certificate to one of the supplied KeyStores, the longest trust path that can be constructed will be returned, ending in the last Certificate that couldn't be verified - this may be self-signed, or it may simply not exist in one of the KeyStores. If the signer certificate itself is invalid, for example because it wasn't valid on the signing date, this method returns an empty list.
If there are two paths of equal length, which one is returned is undefined.
- Parameters:
signer- the signing cerficate to start from. Required.date- the date the signature was applied. Required. All certificates in the chain must be valid on this date.certificates- a collection of other intermediate certificates included with the signature, in any order (may be null).keystores- a collection of trusted roots to try and reach (may be null, in which case no path will be found).revoked- a collection ofCRLorX509Certicateobjects that will be excluded from any matches (may be null). Collection items other than those types are skipped.provider- an optional Provider to use when verifying the certificate signature (may be null to use any).- Returns:
- a List of zero or more X509Certificates starting with
signed, and possibly ending with a KeyStore. - Throws:
KeyStoreException- Since:
- 2.29.4
-
isValidCertificate
public static boolean isValidCertificate(X509Certificate cert, CRL crl, Date signdate)
Return true if the specified X.509 Certificate is valid for the specified date, has not been revoked and has no unknown critical extensions. The code looks like:try { cert.checkValidity(signdate); return !cert.hasUnsupportedCriticalExtensions() && (crl==null || !crl.isRevoked(cert)); } catch (Exception e) { return false; }- Parameters:
cert- the X.509 certificate to verifycrl- the Certificate Revokation List to search - may benullsigndate- the date the certificate was used for signing
-
loadTrustedKeyStore
public static KeyStore loadTrustedKeyStore(String source) throws GeneralSecurityException
Return the specified "trusted"KeyStorewhich is shipped with the API. The KeyStore is specified as a string, which is a comma-separated list of one or more values from
The value "*" may be used to load a combination of all KeyStores, in the order shown in this table. Some exampleseidas the list of eiDAS root certificates published by EU member states from the master list at https://ec.europa.eu/information_society/policy/esignature/trusted-list/tl-mp.xml. This collection contains only "granted", "accredited" or "recognised at national level" root certificates for signing, seals, timestamping or OCSP responses. It does not include certificates only used for web-site authentication. BFO keeps this list up-to-date; updating the application Jar will get an updated list. aatl A list of root certificates maintained by Adobe, which includes various non-EU national bodies as well as various commercial CAs. Acrobat uses a combination of this list and eidaswhen verifying signatures.eidas-withdrawn As for eidasbut this list includes only "withdrawn" and "deprecated at national level certificates". These root certificates are no longer in use but may be encountered when verifiying older documents. Be careful when using this list as a source of trustextra A list of significant other trusted certificates. BFO maintain this list as a transitional list for national bodies that are not yet in the AATL, such as the Singapore National Root certificate java The list of root certificates that ship with the current release of Java. Many of these will not be used for document signing. This is the list returned from the legacy loadDefaultKeyStore()methodKeyStore keystore = FormSignature.loadTrustedKeyStore("eidas"); // return the EU trust list KeyStore keystore = FormSignature.loadTrustedKeyStore("eidas,aatl"); // return the approximate list used by AcrobatRepeated calls with an identical parameter will return the same object.- Parameters:
source- the list of sources, as described. Must not be null.- Returns:
- a read-only KeyStore containing the specified set of trusted roots
- Throws:
IllegalArgumentException- if the specified KeyStore does not exist.GeneralSecurityException- if the specified KeyStore can not be loaded for security reasons (shouldn't happen)- Since:
- 2.29.4
-
loadDefaultKeyStore
public static KeyStore loadDefaultKeyStore() throws GeneralSecurityException
Deprecated.call loadTrustedKeyStore("java") instead.Return the default Java keystore to validate keys against. Since 2.29.4 this returns value fromloadTrustedKeyStore("java")- Returns:
- the KeyStore
- Throws:
GeneralSecurityException- if the default keystore cannot be loaded - an unlikely situation
-
loadTrustedKeyStore
public static KeyStore loadTrustedKeyStore() throws GeneralSecurityException
Deprecated.call loadTrustedKeyStore("eidas") instead.Return a KeyStore containing various trusted roots that are widely approved by EU national or multi-national bodies. Since 2.29.4 this returns value from
loadTrustedKeyStore("eidas")- Returns:
- the KeyStore
- Throws:
GeneralSecurityException- if the keystore cannot be loaded- Since:
- 2.23.6
-
loadAKFKeyStore
public static KeyStore loadAKFKeyStore(InputStream in) throws IOException, GeneralSecurityException
Load an X.509 certificate from an "Adobe Key File" keystore, the type exported from the Adobe Self-Sign signature handler in Acrobat 4.0. The file (which typically has a
.akfsuffix) contains a self-signed X.509 certificate, which can be used to verify (but not sign) documents created with the Adobe Self-Sign signature handler.The returned KeyStore has a single X.509 certificate, and can be passed to the
verifyCertificatesmethod to fully validate a document signed with the "self-sign" signature handler, acting as the Java equivalent of the "Personal Address Book" in Acrobat 4 terminology.Acrobat 5.0 keystores are saved in a different format - the filename is usually "
CertExchangeName.fdf", where Name is the name of the user. These keystores can be loaded via theloadFDFKeyStore(java.io.InputStream)method.Please note the InputStream is not closed by this method.
- Throws:
IOException- if the keystore cannot be parsed or loaded properlyGeneralSecurityException- if the keystore's contents are cryptographically wrong- See Also:
#HANDLER_SELFSIGN,verifyCertificates(java.security.cert.X509Certificate[], java.security.KeyStore, java.security.cert.CRL, java.util.Calendar),loadFDFKeyStore(java.io.InputStream)
-
loadFDFKeyStore
public static KeyStore loadFDFKeyStore(InputStream in) throws IOException, GeneralSecurityException
Load an X.509 certificate from an "Adobe Self-Sign Key" keystore, the type exported from the Adobe Self-Sign signature handler in Acrobat 5.0. The file (which is exported with a
.fdfsuffix) contains a self-signed X.509 certificate, which can be used to verify (but not sign) documents created with the Adobe Self-Sign signature handler.The returned KeyStore has a single X.509 certificate, and can be passed to the
verifyCertificatesmethod to fully validate a document signed with the "self-sign" signature handler, acting as the Java equivalent of the "Trusted Certificates" in Acrobat 5 terminology.Acrobat 4.0 keystores are saved in a different format - the filename has a suffix of "
.akf". These keystores can be loaded via theloadAKFKeyStore(java.io.InputStream)method. Acrobat 5.0 can also save keys in a PKCS#7 format, which can be loaded using theloadPKCS7KeyStore(java.io.InputStream)method.Please note the InputStream is not closed by this method.
- Throws:
IOException- if the keystore cannot be parsed or loaded properlyGeneralSecurityException- if the keystore's contents are cryptographically wrong- Since:
- 1.2.1
- See Also:
#HANDLER_SELFSIGN,verifyCertificates(java.security.cert.X509Certificate[], java.security.KeyStore, java.security.cert.CRL, java.util.Calendar),loadAKFKeyStore(java.io.InputStream)
-
loadPKCS7KeyStore
public static KeyStore loadPKCS7KeyStore(InputStream in) throws IOException, GeneralSecurityException
Load a list of one or more X.509 certificates from a PKCS#7 file.
The returned KeyStore contains X.509 certificates and can be passed to the
verifyCertificatesmethod to verify (but not sign) the certificates used to sign a PDF document.Note that we provide this method for convenience only. If you're working heavily with PKCS format files, we recommend obtaining a JCE implementation that supports them fully. One that we have tested with some success is provided by The Legion of the Bouncy Castle.
Please note the InputStream is not closed by this method.
- Throws:
IOException- if the keystore cannot be parsed or loaded properlyGeneralSecurityException- if the keystore's contents are cryptographically wrong- See Also:
#HANDLER_VERISIGN,verifyCertificates(java.security.cert.X509Certificate[], java.security.KeyStore, java.security.cert.CRL, java.util.Calendar)
-
getIssuerField
public static String getIssuerField(X509Certificate cert, String field) throws CertificateException
Return the specified X.500 field from the specified X.509 certificates Issuer.
Each X.509 certificate has two entities - a subject and an issuer. These are represented in java by the
Principalclass, but unfortunately that class doesn't allow for extraction of the various elements from the entity - elements like Common Name, Country, Organization etc.The
getIssuerField(java.security.cert.X509Certificate, java.lang.String)andgetSubjectField(java.security.cert.X509Certificate, java.lang.String)methods aren't specific to digital signatures or PKCS#7, but are useful "utility" methods that fill that gap in functionality.- Parameters:
cert- the X.509 certificate to extract the Issuer fromfield- the field to return. Can be one of "C" (country), "CN" (common name), "O" (organization"), "OU" (organization unit), "L" (locale), "ST" (state or province) or "Email" (email address - although technically not part of X.500 this is sometimes included)- Returns:
- the requested field, or
nullif the field is not part of the X.500 name. - Throws:
CertificateException
-
getSubjectField
public static String getSubjectField(X509Certificate cert, String field) throws CertificateException
Return the specified X.500 field from the specified X.509 certificates Subject. See the
getIssuerField(java.security.cert.X509Certificate, java.lang.String)method for more information.- Parameters:
cert- the X.509 certificate to extract the Issuer fromfield- the field to return. Can be one of "C" (country), "CN" (common name), "O" (organization"), "OU" (organization unit), "L" (locale), "ST" (state or province) or "Email" (email address - although technically not part of X.500 this is sometimes included)- Returns:
- the requested field, or
nullif the field is not part of the X.500 name. - Throws:
CertificateException
-
rebuild
public void rebuild()
Description copied from class:FormElementCause the annotation list to be rebuilt. Unless you're rendering the annotation using the viewer, it's not necessary to call this method.- Overrides:
rebuildin classFormElement
-
setRequiredTimestampServer
public void setRequiredTimestampServer(URI uri)
Set the URI of the TimeStamp server that must be used when this (blank) signature is eventually signed.- Parameters:
uri- the URI of the TimeStamp server to contact, ornullif none is required.- Since:
- 2.11.14
-
setRequiredReasons
public void setRequiredReasons(String[] validreasons)
Set the list of Reasons from which the user must choose when this (blank) signature is eventually signed.- Parameters:
validreasons- an array of reasons that the user will have to choose from, ornullto not require a reason to be specified.- Since:
- 2.11.14
-
setRequiredCertificateIssuers
public void setRequiredCertificateIssuers(X509Certificate[] certs)
Set restrictions on which X.509 Certificates can be used when this (blank) signature is eventually signed. This method can be used to ensure that the identity used when signing was issued by a particular Certification Authority.
For example, to ensure that a user was signing the PDF with an identity from your own in-house Certification Authority, you could use code like the following. The file "myca.cer" contains the X.509 Certificate of your CA.
InputStream certstream = new FileInputSteram("myca.cer"); CertificateFactory factory = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate)factory.generateCertificate(certstream); sig.setRequiredCertificateIssuers(new X509Certificate[] { cert }); URI uri = new URI("http://security.yourcompany.com/createnewidentity"); sig.setRequiredCertificateFallbackURI(uri);- Parameters:
certs- an array of X.509 Certificates of valid Certification Authorities, ornullto accept any CA.- Since:
- 2.11.14
-
setRequiredCertificateSubjects
public void setRequiredCertificateSubjects(X509Certificate[] certs)
Set restrictions on which X.509 Certificates can be used when this (blank) signature is eventually signed. This method can be used to ensure that only certain identities can be used when signing.- Parameters:
subjects- an array of X.509 Certificates which are allowed to sign this signature, ornullto accept a signature from anyone.- Since:
- 2.11.14
-
setRequiredCertificateFallbackURI
public void setRequiredCertificateFallbackURI(URI uri)
Set the URI the user is directed to if the conditions set bysetRequiredCertificateIssuers(java.security.cert.X509Certificate[])andsetRequiredCertificateSubjects(java.security.cert.X509Certificate[])are not met.- Parameters:
uri- a URI to redirect the signing user to if the "issuers" and "subjects" conditions are not met, ornullto disable this option.- Since:
- 2.11.14
-
setRequiredDigestAlgorithms
public void setRequiredDigestAlgorithms(String[] algorithms)
Set the list of allowable digest algorithms that can be used to sign this signature, ornullto remove any existing restrictions.- Parameters:
algorithms- an array of 1 or more names of digest algorithms, eg "SHA256", "SHA512"- Since:
- 2.20.1
- See Also:
getRequiredDigestAlgorithms()
-
getRequiredDigestAlgorithms
public String[] getRequiredDigestAlgorithms()
Return the list of allowable digest algorithms that can be used to sign this signature, ornullif this is not specified.- Since:
- 2.20.1
- See Also:
setRequiredDigestAlgorithms(java.lang.String[])
-
getRequiredReasons
public String[] getRequiredReasons()
Set the list of reasons that must be chosen from when signing, as set bysetRequiredReasons(java.lang.String[])- Since:
- 2.11.14
-
getRequiredTimestampServer
public URI getRequiredTimestampServer()
Get the URI of the TimeStamp server that must be used when signing as set bysetRequiredTimestampServer(java.net.URI), ornullif none is specified- Since:
- 2.11.14
-
getRequiredCertificateIssuers
public X509Certificate[] getRequiredCertificateIssuers()
Return the list of required Issuer certificates as set bysetRequiredCertificateIssuers(java.security.cert.X509Certificate[]), ornullif none were specified.- Since:
- 2.11.14
-
getRequiredCertificateSubjects
public X509Certificate[] getRequiredCertificateSubjects()
Return the list of required Issuer certificates as set bysetRequiredCertificateSubjects(java.security.cert.X509Certificate[]), ornullif none were specified.- Since:
- 2.11.14
-
getRequiredCertificateFallbackURI
public URI getRequiredCertificateFallbackURI()
Return the URI to be used if the "issuers" and "subjects" Certificate restrictions are not met, as set bysetRequiredCertificateFallbackURI(java.net.URI), ornullif none were specified.- Since:
- 2.11.14
-
getValue
public String getValue()
As signatures do not have a "value" as such, this method always returns null.- Specified by:
getValuein classFormElement
-
getCertificationType
public int getCertificationType()
Return the type of "Certification" this signature attests to. One ofCERTIFICATION_UNCERTIFIED,CERTIFICATION_NOCHANGES,CERTIFICATION_ALLOWFORMSorCERTIFICATION_ALLOWCOMMENTS. Since 2.13 this method returns the value fromSignatureHandler.getCertificationType()- Since:
- 2.7.4
- See Also:
setCertificationType(int, java.lang.String)
-
setCertificationType
public void setCertificationType(int certificationtype, String attestation)Causes this signatures be "Certifying" signature when it's signed - also known as an "Author" signature.. The parameter must be one ofCERTIFICATION_UNCERTIFIED(the default),CERTIFICATION_NOCHANGES,CERTIFICATION_ALLOWFORMSorCERTIFICATION_ALLOWCOMMENTS. Certifified signatures require at least Acrobat 7.0 to verify.- Parameters:
certificationtype- the type of certification to use.attestation- the Legal Attestation you wish to make about the signature. May be null.- Since:
- 2.7.4
- See Also:
getCertificationType()
-
toString
public String toString()
-
-