|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectorg.faceless.pdf2.FormElement
org.faceless.pdf2.FormSignature
public final class FormSignature
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 the AcrobatSignatureHandlerFactory
, which we recommend using,
as well as the older HANDLER_VERISIGN
and HANDLER_SELFSIGN
factories.
All of these handlers use the standard KeyStore
class
supplied with Java, and do not necessarily need any third party libraries to work.
A feature of PDF is that only a single STATE_PENDING
signature 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.
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.
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
PDFReader
class documentation for more information about revisions). To
verify the signature covers the latest revision, you need to compare the value of
PDF.getNumberOfRevisions()
with the value of getNumberOfRevisionsCovered()
.
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 the
isValidCertificate
method used to perform some basic
validation if you want to check the certificates yourself. Here we use the
verifyCertificates
method 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!"); } } }
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 AcrobatSignatureHandlerFactory
factory.
Prior to Acrobat 6, the situation is more complex - you must create a signature for
a specific handler (typically using HANDLER_SELFSIGN
or 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.
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.
AcrobatSignatureHandlerFactory
,
PKCS7SignatureHandler
Field Summary | |
---|---|
static int |
CERTIFICATION_ALLOWCOMMENTS
A value that can be passed in to setCertificationType(int, java.lang.String) and returned from
getCertificationType() to indicate that the signature will be a certifying
signature that allows only commenting and form fill-in actions on the Document. |
static int |
CERTIFICATION_ALLOWFORMS
A value that can be passed in to setCertificationType(int, java.lang.String) and returned from
getCertificationType() to indicate that the signature will be a certifying
signature that allows only form fill-in actions on the Document. |
static int |
CERTIFICATION_NOCHANGES
A value that can be passed in to setCertificationType(int, java.lang.String) and returned from
getCertificationType() to indicate that the signature will be a certifying
signature that disallows any changes to the Document. |
static int |
CERTIFICATION_UNCERTIFIED
A value that can be passed in to setCertificationType(int, java.lang.String) and returned from
getCertificationType() to indicate that the signature will not be a
certifying signature. |
static SignatureHandlerFactory |
HANDLER_ACROBATSIX
A type of handler representing the general purpose PKI signature plugin supplied with Acrobat 6.0 and later. |
static SignatureHandlerFactory |
HANDLER_SELFSIGN
A type of handler representing the Adobe "self-sign" signature handler supplied with Acrobat 4.x and 5.x. |
static SignatureHandlerFactory |
HANDLER_VERISIGN
A type of handler representing the VeriSign "Document Signer" digital signature handler available for Acrobat 4.x and 5.x. |
static int |
STATE_BLANK
This value is returned from the getState() method if the signature
field has not been completed yet. |
static int |
STATE_PENDING
This value is returned from the getState() 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 int |
STATE_SIGNED
This value is returned from the getState() method if the signature is
"old" - the PDF document that was read in was already signed with this
signature. |
Constructor Summary | |
---|---|
FormSignature()
Create a new blank digital signature field. |
|
FormSignature(KeyStore keystore,
String alias,
char[] password,
SignatureHandlerFactory factory)
Create a new pending digital signature to sign a PDF document. |
Method Summary | |
---|---|
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. |
int |
getCertificationType()
Return the type of "Certification" this signature attests to. |
String |
getContactInfo()
Return the contact information field for this signature if that information is available, or null otherwise. |
String |
getFilter()
Return the name of the digital signature handler used to sign the document. |
static String |
getIssuerField(X509Certificate cert,
String field)
Return the specified X.500 field from the specified X.509 certificates Issuer. |
String |
getLocation()
Return the location where this document was signed if if that information is available, or null otherwise. |
String |
getName()
Get the name of the person or entity that signed this PDF if that information is available, or null otherwise. |
int |
getNumberOfRevisionsCovered()
Return the number of document revisions covered by this signature. |
String |
getReason()
Return the reason this signature was applied to the PDF if that information is available, or null otherwise. |
URI |
getRequiredCertificateFallbackURI()
Return the URI to be used if the "issuers" and "subjects" Certificate restrictions are not met, as set by setRequiredCertificateFallbackURI(java.net.URI) , or null
if none were specified. |
X509Certificate[] |
getRequiredCertificateIssuers()
Return the list of required Issuer certificates as set by setRequiredCertificateIssuers(java.security.cert.X509Certificate[]) , or null if none were specified. |
X509Certificate[] |
getRequiredCertificateSubjects()
Return the list of required Issuer certificates as set by setRequiredCertificateSubjects(java.security.cert.X509Certificate[]) , or null if none were specified. |
String[] |
getRequiredReasons()
Set the list of reasons that must be chosen from when signing, as set by setRequiredReasons(java.lang.String[]) |
URI |
getRequiredTimestampServer()
Get the URI of the TimeStamp server that must be used when signing as set by setRequiredTimestampServer(java.net.URI) , or null
if none is specified |
SignatureHandler |
getSignatureHandler()
Return the SignatureHandler that is used with this Signature,
or null if the signature has not been signed yet (ie. the
state is still STATE_BLANK ) |
Calendar |
getSignDate()
Return the time the signature was applied to the document. |
int |
getState()
Returns the current state of the signature. |
static String |
getSubjectField(X509Certificate cert,
String field)
Return the specified X.500 field from the specified X.509 certificates Subject. |
String |
getValue()
As signatures do not have a "value" as such, this method always returns null. |
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. |
static KeyStore |
loadAKFKeyStore(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 KeyStore |
loadDefaultKeyStore()
Return the default Java keystore to validate keys against. |
static KeyStore |
loadFDFKeyStore(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 KeyStore |
loadPKCS7KeyStore(InputStream in)
Load a list of one or more X.509 certificates from a PKCS#7 file. |
void |
rebuild()
Cause the annotation list to be rebuilt. |
static void |
registerHandlerForVerification(SignatureHandlerFactory factory)
This method must be called to register a new SignatureHandlerFactory
that can be used when verifying signatures, although it's not necessary
for handlers that are only used for signing. |
void |
setCertificationType(int certificationtype,
String attestation)
Causes this signatures be "Certifying" signature when it's signed - also known as an "Author" signature.. |
void |
setContactInfo(String info)
Set the contact information field for this signature. |
void |
setLocation(String location)
Set the location where the signer is signing the PDF document - e.g. |
void |
setName(String name)
Set the name of the person or entity who is applying this signature. |
void |
setReason(String reason)
Set the reason why the the document is being signed - e.g. |
void |
setRequiredCertificateFallbackURI(URI uri)
Set the URI the user is directed to if the conditions set by setRequiredCertificateIssuers(java.security.cert.X509Certificate[])
and setRequiredCertificateSubjects(java.security.cert.X509Certificate[]) are not met. |
void |
setRequiredCertificateIssuers(X509Certificate[] issuers)
Set restrictions on which X.509 Certificates can be used when this (blank) signature is eventually signed. |
void |
setRequiredCertificateSubjects(X509Certificate[] subjects)
Set restrictions on which X.509 Certificates can be used when this (blank) signature is eventually signed. |
void |
setRequiredReasons(String[] validreasons)
Set the list of Reasons from which the user must choose when this (blank) signature is eventually signed. |
void |
setRequiredTimestampServer(URI uri)
Set the URI of the TimeStamp server that must be used when this (blank) signature is eventually signed. |
void |
sign(KeyStore keystore,
String alias,
char[] password,
SignatureHandlerFactory factory)
Sign a STATE_BLANK digital signature. |
String |
toString()
|
boolean |
verify()
Verify a signature by ensuring that the PDF document hasn't been altered since it was signed. |
static X509Certificate |
verifyCertificates(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 |
Methods inherited from class java.lang.Object |
---|
equals, getClass, hashCode, notify, notifyAll, wait, wait, wait |
Field Detail |
---|
public static final int CERTIFICATION_UNCERTIFIED
setCertificationType(int, java.lang.String)
and returned from
getCertificationType()
to indicate that the signature will not be a
certifying signature. This is the default.
public static final int CERTIFICATION_NOCHANGES
setCertificationType(int, java.lang.String)
and returned from
getCertificationType()
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 docment cannot be changed.
public static final int CERTIFICATION_ALLOWFORMS
setCertificationType(int, java.lang.String)
and returned from
getCertificationType()
to indicate that the signature will be a certifying
signature that allows only form fill-in actions on the Document.
A legal attestation is recommended if this type of certification is used.
public static final int CERTIFICATION_ALLOWCOMMENTS
setCertificationType(int, java.lang.String)
and returned from
getCertificationType()
to indicate that the signature will be a certifying
signature that allows only commenting and form fill-in actions on the Document.
A legal attestation is recommended if this type of certification is used.
public static final SignatureHandlerFactory HANDLER_SELFSIGN
A type of handler representing the Adobe "self-sign" signature handler supplied with Acrobat 4.x and 5.x. Keys must use the RSA algorithm and may be any length (we've tested 512, 1024 and 2048-bit keys). Certificates must use the MD5/RSA signature algorithm. Obviously the certificate associated with the key must be self-signed, and Acrobat also insists that the country code, if specified, must be exactly 2 letters long.
Self-sign signatures are limited in that only certificates in the viewing users "Personal Address Book" are considered to be trusted - a Certifying Authority is not used. Certificates may be added to the address book if they're not already there, and provided they are confirmed (by manually checking the serial number with the issuer), this handler does most of what is required of a PKI system.
Documents signed with this handler can be verifed in Acrobat 4, 5 and 6 out of the box.
Note that unless you're specifically targeting Acrobat 5.0 or earlier you should
use HANDLER_ACROBATSIX
instead.
public static final SignatureHandlerFactory HANDLER_VERISIGN
A type of handler representing the VeriSign "Document Signer" digital signature handler available for Acrobat 4.x and 5.x. Keys must use the RSA algorithm and may be any length, but must be signed by a VeriSign CA key or they will be considered invalid by the VeriSign plugin. VeriSign also distribute an "Administrator Tool" which allows you to set your own list of trusted certificates, although we haven't tested this functionality.
The plugin itself is available from the VeriSign website as a free download. Details on how to use and install the plugin are also available from this site.
The VeriSign test certificate we worked with was MD5/RSA, and we expect that all keys that work with this plugin must use this algorithm.
Documents signed with this handler can be verifed in Acrobat 4, 5 with the VeriSign
plugin, and Acrobat 6 out of the box.
Note that unless you're specifically targeting Acrobat 5.0 or earlier you should
use HANDLER_ACROBATSIX
instead.
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.PPKMS") is also known as the "Windows Certificate Security" handler. This handler verifies certificates against the standard Windows Keystore, which is, as best as we can tell, the default behaviour when verifying documents signed with the Acrobat 5.0 "VeriSign" and "Self-Sign" in Acrobat 6.0 anyway. On OS X it verifies against the user's keystore - we've no idea what it does on other platforms.
Documents signed with this handler can only be verifed in Acrobat 6. Unless you're
specifically targetting Acrobat 5.0 or earlier, we recommend always using this
handler instead of HANDLER_SELFSIGN
or HANDLER_VERISIGN
.
Note since 2.7.1 this variable is simple an instance of AcrobatSignatureHandlerFactory
public static final int STATE_SIGNED
getState()
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.
STATE_PENDING
,
STATE_BLANK
,
getState()
,
Constant Field Valuespublic static final int STATE_PENDING
getState()
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.
STATE_SIGNED
,
STATE_BLANK
,
getState()
,
Constant Field Valuespublic static final int STATE_BLANK
getState()
method if the signature
field has not been completed yet. A document may contain more than one blank
signature fields.
STATE_SIGNED
,
STATE_PENDING
,
Constant Field ValuesConstructor Detail |
---|
public FormSignature()
blank
digital signature field. The field
may have a signature applied to it at a later date, either by this library
or by Acrobat
public FormSignature(KeyStore keystore, String alias, char[] password, SignatureHandlerFactory factory) throws GeneralSecurityException, IllegalArgumentException
pending
digital 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);
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_SELFSIGN
or HANDLER_VERISIGN
GeneralSecurityException
- if the keystore, private key, password or certificates are invalid in any way
IllegalArgumentException
- if the arguments are technically correct but will result in an invalid signature for any reason.Method Detail |
---|
public static void registerHandlerForVerification(SignatureHandlerFactory factory)
This method must be called to register a new SignatureHandlerFactory
that 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_SELFSIGN
and HANDLER_ACROBATSIX
factories are the only
three that are registered.
public WidgetAnnotation addAnnotation(PDFPage page, float x1, float y1, float x2, float y2)
SignatureHandler.getLayerAppearance()
method.
Note that Acrobat 9 and later will only support one annotation per signature.
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
public void sign(KeyStore keystore, String alias, char[] password, SignatureHandlerFactory factory) throws GeneralSecurityException, IllegalArgumentException
STATE_BLANK
digital signature. The private key and the
certificates used to sign the PDF are contained in the specified keystore.
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_SELFSIGN
or HANDLER_VERISIGN
GeneralSecurityException
- if the keystore, private key, password or certificates are invalid in any way
IllegalArgumentException
- if the arguments are technically correct but will result in an invalid signature for any reason.public int getState()
STATE_SIGNED
for existing signatures, STATE_PENDING
for new signatures that have been added, or STATE_BLANK
for
empty signature fields
public void setName(String name)
name
- the name of the entity signing the PDF, or null
to clear the current name
IllegalStateException
- if this signature is STATE_BLANK
public String getName()
null
otherwise.
IllegalStateException
- if this signature is STATE_BLANK
public void setReason(String reason)
reason
- the reason the entity is signing the document,
or null
to clear the current reason
IllegalStateException
- if this signature is STATE_BLANK
public String getReason()
null
otherwise.
IllegalStateException
- if this signature is STATE_BLANK
public void setLocation(String location)
location
- the location where the entity is signing the document,
or null
to clear the current location
IllegalStateException
- if this signature is STATE_BLANK
public String getLocation()
null
otherwise.
IllegalStateException
- if this signature is STATE_BLANK
public void setContactInfo(String info)
info
- the contact information for this signature, or null
to clear the current value
IllegalStateException
- if this signature is STATE_BLANK
public String getContactInfo()
null
otherwise.
IllegalStateException
- if this signature is STATE_BLANK
public Calendar getSignDate()
IllegalStateException
- if this signature isn't STATE_SIGNED
public String getFilter()
getSignatureHandler().getFilter()
IllegalStateException
- if this signature is STATE_BLANK
public SignatureHandler getSignatureHandler()
SignatureHandler
that is used with this Signature,
or null
if the signature has not been signed yet (ie. the
state is still STATE_BLANK
)
public boolean verify() throws GeneralSecurityException
Verify a signature by ensuring that the PDF document hasn't been altered
since it was signed. Only signatures with a state of STATE_SIGNED
may 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 the verifyCertificates
method.
true
if the document is unaltered, false
if the document has been altered since signing
IllegalStateException
- if the signature you're verifying isn't
STATE_SIGNED
GeneralSecurityException
- if the specified signing algorithm is
unknown, or the certificate or key are invalidpublic int getNumberOfRevisionsCovered()
PDFReader
class
for more information on document revisions, and the class documentation
for this class for examples of how to validate a signature using this
method.
IllegalArgumentException
- if the signature is not signed yet (ie.
does not have a state of STATE_SIGNED
)public static X509Certificate verifyCertificates(X509Certificate[] certs, KeyStore keystore, CRL crl, Calendar signdate) throws GeneralSecurityException
The X.509 certificate(s) used to sign the document are verified and compared against the certificates in the keystore, which are assumed to be trusted. An optional Certificate Revocation List may be specified with a list of compromised certificates.
The method returns the first certificate specified in the PDF that
cannot be verified. If every certificate in the chain is verified
and the final certificate is signed by a certificate in the specified
keystore, the entire chain is considered valid and this method returns
null
.
The specified keystore may be the result of loadDefaultKeyStore()
,
or a user specified keystore. The CRL may be (and usually is) null
.
Note that self-signed certificates (as created by the Adobe Self-Sign
handler) will generally fail, as they cannot be verified against a trusted
root certificate. The only exception to this is if you're verifying against
a keystore returned from loadAKFKeyStore(java.io.InputStream)
or loadFDFKeyStore(java.io.InputStream)
,
containing a certificate that was exported from Acrobat.
Also note that unless you personally trust every entity (represented by a certificate) in the chain to issue certificates responsibly, verifying the chain integrity is worthless.
We are happy to provide source code to this method - ask if you need it.
certs
- the X509Certificate
list to verify. Usually
this is the return result from PKCS7SignatureHandler.getCertificates()
keystore
- the KeyStore
containing one or more
trusted certificates to verify the certificate chain against.crl
- the Certificate Revocation List to check the
certificates against. May be null
.signdate
- the date the documents was signed. Usually the output of
getSignDate()
null
if all were verified against a
certificate from the keystore.
GeneralSecurityException
- if the KeyStore or any of the
certificates are invalid.PKCS7SignatureHandler.getCertificates()
,
loadAKFKeyStore(java.io.InputStream)
,
loadFDFKeyStore(java.io.InputStream)
,
loadPKCS7KeyStore(java.io.InputStream)
,
loadDefaultKeyStore()
public static boolean isValidCertificate(X509Certificate cert, CRL crl, Date signdate)
try { cert.checkValidity(signdate); return !cert.hasUnsupportedCriticalExtensions() && (crl==null || !crl.isRevoked(cert)); } catch (Exception e) { return false; }
cert
- the X.509 certificate to verifycrl
- the Certificate Revokation List to search - may be null
signdate
- the date the certificate was used for signingpublic static KeyStore loadDefaultKeyStore() throws GeneralSecurityException
GeneralSecurityException
- if the default keystore cannot be loaded - an unlikely situationpublic 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 .akf
suffix) 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 verifyCertificates
method 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 the loadFDFKeyStore(java.io.InputStream)
method.
Please note the InputStream is not closed by this method.
IOException
- if the keystore cannot be parsed or loaded properly
GeneralSecurityException
- if the keystore's contents are cryptographically wrongHANDLER_SELFSIGN
,
verifyCertificates(java.security.cert.X509Certificate[], java.security.KeyStore, java.security.cert.CRL, java.util.Calendar)
,
loadFDFKeyStore(java.io.InputStream)
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 .fdf
suffix) 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 verifyCertificates
method 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 the
loadAKFKeyStore(java.io.InputStream)
method. Acrobat 5.0 can also save keys in a PKCS#7 format,
which can be loaded using the loadPKCS7KeyStore(java.io.InputStream)
method.
Please note the InputStream is not closed by this method.
IOException
- if the keystore cannot be parsed or loaded properly
GeneralSecurityException
- if the keystore's contents are cryptographically wrongHANDLER_SELFSIGN
,
verifyCertificates(java.security.cert.X509Certificate[], java.security.KeyStore, java.security.cert.CRL, java.util.Calendar)
,
loadAKFKeyStore(java.io.InputStream)
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 verifyCertificates
method 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.
IOException
- if the keystore cannot be parsed or loaded properly
GeneralSecurityException
- if the keystore's contents are cryptographically wrongHANDLER_VERISIGN
,
verifyCertificates(java.security.cert.X509Certificate[], java.security.KeyStore, java.security.cert.CRL, java.util.Calendar)
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 Principal
class, 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)
and getSubjectField(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.
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)
null
if the field is not part of
the X.500 name.
CertificateException
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.
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)
null
if the field is not part of
the X.500 name.
CertificateException
public void rebuild()
FormElement
rebuild
in class FormElement
public void setRequiredTimestampServer(URI uri)
uri
- the URI of the TimeStamp server to contact, or null
if none
is required.public void setRequiredReasons(String[] validreasons)
validreasons
- an array of reasons that the user will have to choose from, or
null
to not require a reason to be specified.public void setRequiredCertificateIssuers(X509Certificate[] issuers)
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);
issuers
- an array of X.509 Certificates of valid Certification Authorities, or null
to accept any CA.public void setRequiredCertificateSubjects(X509Certificate[] subjects)
subjects
- an array of X.509 Certificates which are allowed to sign this signature,
or null
to accept a signature from anyone.public void setRequiredCertificateFallbackURI(URI uri)
setRequiredCertificateIssuers(java.security.cert.X509Certificate[])
and setRequiredCertificateSubjects(java.security.cert.X509Certificate[])
are not met.
uri
- a URI to redirect the signing user to if the "issuers" and "subjects" conditions are not met, or null
to disable this option.public String[] getRequiredReasons()
setRequiredReasons(java.lang.String[])
public URI getRequiredTimestampServer()
setRequiredTimestampServer(java.net.URI)
, or null
if none is specified
public X509Certificate[] getRequiredCertificateIssuers()
setRequiredCertificateIssuers(java.security.cert.X509Certificate[])
, or null
if none were specified.
public X509Certificate[] getRequiredCertificateSubjects()
setRequiredCertificateSubjects(java.security.cert.X509Certificate[])
, or null
if none were specified.
public URI getRequiredCertificateFallbackURI()
setRequiredCertificateFallbackURI(java.net.URI)
, or null
if none were specified.
public String getValue()
getValue
in class FormElement
public int getCertificationType()
CERTIFICATION_UNCERTIFIED
, CERTIFICATION_NOCHANGES
,
CERTIFICATION_ALLOWFORMS
or CERTIFICATION_ALLOWCOMMENTS
.
Since 2.13 this method returns the value from
SignatureHandler.getCertificationType()
setCertificationType(int, java.lang.String)
public void setCertificationType(int certificationtype, String attestation)
CERTIFICATION_UNCERTIFIED
(the default),
CERTIFICATION_NOCHANGES
, CERTIFICATION_ALLOWFORMS
or
CERTIFICATION_ALLOWCOMMENTS
.
Certifified signatures require at least Acrobat 7.0 to verify.
certificationtype
- the type of certification to use.attestation
- the Legal Attestation you wish to make about the signature. May be null.getCertificationType()
public String toString()
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |