⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 formsignature.java

📁 Java生成PDF Java生成PDF Java生成PDF
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
// $Id: FormSignature.java,v 1.4 2003/11/03 14:03:51 mike Exp $package org.faceless.pdf;import java.io.*;import java.util.*;import java.security.*;import java.security.cert.*;import java.security.spec.*;/** * <p> * 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 not based around a * Public Key crypto system are not supported. * </p><p> * Signatures may be applied and verified using either the full version of * Adobe Acrobat&trade; or Adobe Approval, <b>not</b> the free Acrobat Reader. * Acrobat comes with a "digital signature handler" called the Self-Sign * handler, which allows a limited form of verification, and additional handlers * are available as plugins for Acrobat. Several are supplied on the Acrobat CD. * </p><p> * The signatures used in PDF documents are X.509 certificates, which are * already handled by the <code>java.security</code> packages supplied with * J2SE 1.2 and later. No additional Java classes are required. * </p><p> * An important point to remember is that the signatures on an existing * document are <b>not preserved</b> if that document is loaded then saved. * This is because the document structure is irreversably changed by this * process, which renders the signature invalid. Another key point is that in * the current version of this library only a single {@link #STATE_PENDING} * signature can be applied to a PDF. * </p><p> * So how do you use this class? First we'll cover how to verify signatures * on an existing document. * </p> * * <h3>Verifying existing signatures</h3> * <p> * To verify a document has been signed and not altered since signing, and * to be sure of the signatory, three steps are required: * <ol> * <li>You must verify that content of the document matches the signature</li> * <li>You must verify that the signature covers the whole document</li> * <li>You must verify that the key used to sign the document belongs to who it says it does</li> * </ol> * First, verifying that the signature matches the document content is done * using the {@link #verify} method. This can be done like so: * </p> * <pre> *    PDF pdf = new PDF(new PDFReader(new FileInputStream(args[0]))); *    <b>Map elements = pdf.getForm().getElements();</b> * *    for (Iterator i=elements.keySet().iterator(); i.hasNext();) { *        String name = (String)i.next(); *        if (elements.get(name) instanceof FormSignature) { *            <b>FormSignature sig = (FormSignature)elements.get(name); *            if (sig.verify()) {</b> *                System.out.println("Signature from "+sig.getName()+" matches"); *            } *        } *    } * </pre> * <p> * 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 * {@link PDFReader} class documentation for more information about revisions. To * verify the signature covers the latest revision, you need to compare the value of * {@link PDF#getNumberOfRevisions} with the value of {@link #getNumberOfRevisionsCovered}. * Something like this should do it: * </p> * <pre> *    int pdfrevision = pdf.getNumberOfRevisions(); *    int sigrevision = signature.getNumberOfRevisionsCovered(); *    if (pdfrevision==sigrevision) System.out.println("Whole document is covered"); * </pre> * <p> * At this point you know the signature covers the whole document, and that the * document hasn't been changed since signing. However, this is only half the * story. Although the signature matches the content, in order to be 100% sure the * document is unaltered you need to check the certificates used to sign the * document - otherwise anyone could create a certificate with any name they choose. * A full discussion of PKI could fill a book in itself, but generally speaking a * key is signed by a "chain" of certificates, with the certificate at the end of the * chain considered to be "trusted". * </p><p> * Each Java distribution comes with a list of trusted top-level certificates, * which are used to verify signed JAR files. One of these top-level certificates * is usually at the end of every certificate chain. Here's how to verify the * certificates used against that list, called a "KeyStore". * </p> * <pre> *    <b>KeyStore trusted = FormSignature.loadDefaultKeyStore();</b> * *    PDF pdf = new PDF(new PDFReader(new FileInputStream(args[0]))); *    <b>Map elements = pdf.getForm().getElements();</b> * *    for (Iterator i=elements.keySet().iterator(); i.hasNext();) { *        String name = (String)i.next(); *        if (elements.get(name) instanceof FormSignature) { *            <b>FormSignature sig = (FormSignature)elements.get(name); *            if (sig.verifyCertificates(trusted,null)==null) {</b> *                System.out.println("Certificates for "+sig.getName()+" verified"); *            } *        } *    } * </pre> * <p> * As any cryptographer will tell you, there is much more to key management * than we've described here. It's hard not to sound paranoid when discussing * cryptography, because you must always remember when verifying certificates * that you are trusting every entity in the certificate chain. Their certificate * is the only guarantee you've got that the certificates they've signed * belong to the entities those certificates represent. The certificate chain can be accessed * via the {@link #getCertificates} method, and the * <code>isValidCertificate</code> method used to perform some basic validation * if you want to check the certificates yourself. * </p> * * <h3>Signing documents</h3> * <p> * A single signature can be applied to a PDF document by adding the signature * to the PDF documents Form. Although the PDF library supports reading documents * with multiple revisions, it doesn't support writing them, which is why only a * single signature can be used. Here's an example. * </p> * <pre> *   PDF pdf = new PDF(); *   // Create pdf document here * *   KeyStore keystore = loadMyKeyStore();  // Somehow load a keystore *  *   <b>FormSignature sig = new FormSignature(keystore, "mykey", *                                         "secret".toCharArray(), *                                         FormSignature.HANDLER_VERISIGN);</b> *   <b>pdf.getForm().addElement("Test Signature", sig);</b> * </pre> * <p> * 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 {@link KeyStore}, and two, that a digital signature must * be verified by a specified digital signature handler. * </p><p> * Although in theory all PKI signature handlers should be interoperable (Adobe recommend * this in their <a href=http://partners.adobe.com/asn/developer/acrosdk/docs/ppk_pdfspec.pdf>specification</a>, * and this library can verify all signatures that meet those requirements), * at least Acrobat 4.0 doesn't allow a signature created with the Self-Sign handler * to be verified by the VeriSign handler, and vice-versa. This means before applying a * digital signature you need to know which handlers are available to your audience. * </p><p> * Here are the handlers we know about with the level of support we offer. * </p><p> * <table border=1> * <tr><td><b>Adobe "Self Sign" handler</b></td><td>Can read/write signatures. See {@link #HANDLER_SELFSIGN}</td></tr> * <tr><td nowrap><b>VeriSign Document Signer</b></td><td>Can read/write signatures. See {@link #HANDLER_VERISIGN}</td></tr> * <tr><td nowrap><b>Entrust PPKEF architecture</b></td><td>Currently unsupported. We hope to support the Entrust architecture in the not-so-distant future.</td></tr> * <tr><td><b>CIC "Sign-It" handler</b></td><td>Not a public/private key handler, uses custom "written" signatures instead. Unsupported.</td></tr> * </table> * <p> * Finally to get you started, here is a complete example showing how to create * a PDF signed with the Adobe "self-sign" signature handler. 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. * </p> * <ol> * <li> * <p> * 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. * </p> * <pre> *    keytool -genkey -alias mykey -keyalg RSA -sigalg MD5withRSA \ *            -keystore mykeystore -dname 'C=UK, O=BigFaceless, CN=BFO' * </pre> * </li> * <li> * <p> * The following code can be used to create a blank PDF which is digitally * signed with this key. * </p><pre> * import java.security.KeyStore; * import java.io.*; * import org.faceless.pdf.*; * * public static void TestSign * { *     static final String KEYFILE = "mykeystore";  // Name of keystore file *     static final String KEYALIAS = "mykey";      // Alias for private key *     static final char[] PASSWORD = "secret".toCharArray(); // Password *     static final String OUTFILE = "signed.pdf";  // File to write to. * *     public static void main(String[] args) throws Exception *     { *         // Load the keystore *         // *         KeyStore keystore = KeyStore.getInstance("JKS"); *         keystore.load(new FileInputStream(KEYFILE), PASSWORD); * *         // Create the PDF (with 1 blank page to keep Acrobat happy). *         // *         PDF pdf = new PDF(); *         PDFPage page = pdf.newPage(PDF.PAGESIZE_A4); * *         // Create the digital signature object *         // *         FormSignature sig = new FormSignature(keystore, KEYALIAS, PASSWORD, *                                               FormSignature.HANDLER_SELFSIGN); *         pdf.getForm().addElement("Test Signature", sig); * *         // Write it out *         pdf.render(new FileOutputStream(OUTFILE)); *     } * } * </pre> * </li><li> * <p> * Run the program. This creates a file "signed.pdf", whose integrity can be * verified in Adobe Acrobat 4.0 or greater. * </p><pre> *   java TestSign * </pre> * </li></ol> * <p> * More information on digital signatures is available in the userguide. * </p> * * @since 1.1.13 * @version $Revision: 1.4 $ */public final class FormSignature extends FormElement{    FormSignature(org.faceless.pdf2.FormSignature b)    {        super(b);    }    /**     * <p>     * A type of handler representing the Adobe "self-sign" signature handler     * supplied with every version of Acrobat. 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.     * </p><p>     * 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.     * </p>     */    public static final int HANDLER_SELFSIGN = 0;    /**     * <p>     * A type of handler representing the VeriSign "Document Signer" digital signature handler.     * Keys must use the RSA algorithm and may be any length, but <i>must</i>     * be signed by a VeriSign CA key or they will be considered invalid by the     * VeriSign plugin. Having said that, VeriSign also distribute an "Administrator Tool"     * which allows you to set your own list of trusted certificates, although we haven't     * tested this functionality.     * </p><p>     * The plugin itself is distributed on the Acrobat CD or available from the     * <a href="http://www.verisign.com/products/acrobat">VeriSign website</a>     * as a free download. Details on how to use and install the plugin are also     * available from this site.     * </p><p>     * 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.     * </p>     */    public static final int HANDLER_VERISIGN = 1;    /**     * This value is returned from the {@link #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.     * @see #STATE_PENDING     * @see #getState     */    public static final int STATE_SIGNED = 0;    /**     * This value is returned from the {@link #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.     * @see #STATE_SIGNED     * @see #getState     */    public static final int STATE_PENDING = 1;    private org.faceless.pdf2.FormSignature sig;    /**     * <p>     * Create a new digital signature to sign a PDF document. The private key and     * the certificates used to sign the PDF are contained in the specified     * keystore.     * </p>     * @param keystore the KeyStore containing the private key and a list of certificates     * to sign the document with     * @param alias the alias or "friendly-name" which the private key is stored under     * in the keystore     * @param password the password to unlock the private key     * @param handler the digital signature handler that will be used to verify the     * signature. Current values are {@link #HANDLER_SELFSIGN}, for the Adobe Self-Sign handler,     * and {@link #HANDLER_VERISIGN}, for the VeriSign handler.     * @throws GeneralSecurityException if the keystore, private key, password or certificates are invalid in any way     * @throws IllegalArgumentException if the arguments are technically correct but will result in an invalid signature for any reason.     */    public FormSignature(KeyStore keystore, String alias, char[] password, int handler)        throws GeneralSecurityException, IllegalArgumentException    {	super(new org.faceless.pdf2.FormSignature(keystore, alias, password, handler==HANDLER_VERISIGN ? org.faceless.pdf2.FormSignature.HANDLER_VERISIGN : org.faceless.pdf2.FormSignature.HANDLER_SELFSIGN));    }    /**     * Returns the current state of the signature. The state is     * currently either {@link #STATE_SIGNED} for existing signatures,     * or {@link #STATE_PENDING} for new signatures.     */    public int getState()    {	int state = ((org.faceless.pdf2.FormSignature)element).getState();	if (state==org.faceless.pdf2.FormSignature.STATE_SIGNED) {	    return STATE_SIGNED;	} else {	    return STATE_PENDING;	}    }    /**     * Set the name of the person or entity who is applying this signature.     * Setting this field is recommended but not necessary - it defaults     * to the Common Name (CN) of the signing certificate.     *     * @param name the name of the entity signing the PDF,     * or <code>null</code> to clear the current reason     */    public void setName(String name)    {	((org.faceless.pdf2.FormSignature)element).setName(name);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -