001/*
002 * (C) Copyright 2011-2012 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Wojciech Sulejman
016 *     Florent Guillaume
017 */
018package org.nuxeo.ecm.platform.signature.api.sign;
019
020import java.security.cert.X509Certificate;
021import java.util.List;
022
023import org.nuxeo.ecm.core.api.Blob;
024import org.nuxeo.ecm.core.api.DocumentModel;
025import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
026import org.nuxeo.ecm.core.convert.api.ConversionException;
027import org.nuxeo.ecm.platform.signature.api.exception.SignException;
028
029/**
030 * Provides digital signature services that can be performed on PDF documents, e.g.:
031 * <ul>
032 * <li>signing a specific PDF,</li>
033 * <li>obtaining a list of certificates already associated with a document.</li>
034 * </ul>
035 * A PDF document can be signed using a user certificate. This requires an existing user certificate present in the
036 * system. A certificate password must be made available to use this service.
037 */
038public interface SignatureService {
039
040    /**
041     * Information about a blob and its signing status.
042     */
043    public class StatusWithBlob {
044
045        /**
046         * The signing status for a document that is not signable (no attachment or unsupported attachment type).
047         */
048        public static final int UNSIGNABLE = -1;
049
050        /**
051         * The signing status for a document that is not signed.
052         */
053        public static final int UNSIGNED = 0;
054
055        /**
056         * The signing status for a document that is signed by the current user (and maybe others).
057         */
058        public static final int SIGNED_CURRENT = 1;
059
060        /**
061         * The signing status for a document that is signed by users other than the current user.
062         */
063        public static final int SIGNED_OTHER = 2;
064
065        /**
066         * A document's status may be:
067         * <ul>
068         * <li>unsignable ({@link #UNSIGNABLE}),</li>
069         * <li>unsigned ({@link #UNSIGNED}),</li>
070         * <li>signed by the current user (and maybe also others) ( {@link #SIGNED_CURRENT}),</li>
071         * <li>signed only by others ({@link #SIGNED_OTHER}).</li>
072         * </ul>
073         */
074        public final int status;
075
076        public final Blob blob;
077
078        public final BlobHolder blobHolder;
079
080        public final String path;
081
082        public StatusWithBlob(int status, Blob blob, BlobHolder blobHolder, String path) {
083            this.status = status;
084            this.blob = blob;
085            this.blobHolder = blobHolder;
086            this.path = path;
087        }
088
089        public int getStatus() {
090            return status;
091        }
092
093        public Blob getBlob() {
094            return blob;
095        }
096
097        public String getPath() {
098            return path;
099        }
100
101        @Override
102        public String toString() {
103            return getClass().getSimpleName() + "(status=" + status + ",path=" + path + ",blob=" + blob + ")";
104        }
105    }
106
107    /**
108     * Finds the signing status for the document.
109     * <p>
110     * A signature user is determined according to its email.
111     *
112     * @param doc the document
113     * @return the signing status
114     */
115    StatusWithBlob getSigningStatus(DocumentModel doc, DocumentModel currentUser);
116
117    enum SigningDisposition {
118        /** Replace the main blob with the signed one. */
119        REPLACE,
120        /** Replace the main blob with the signed one and archive the original. */
121        ARCHIVE,
122        /** Put the signed blob as an attachment. */
123        ATTACH
124    }
125
126    /**
127     * Signs a document with a user certificate (converts it into a PDF first if needed).
128     * <p>
129     * Requires a password to retrieve the certificate from the user keystore.
130     * <p>
131     * Does not save the modified document.
132     *
133     * @param doc the document to sign
134     * @param user the signing user
135     * @param userKeyPassword the password for the user's signing certificate
136     * @param reason the signing reason
137     * @param pdfa {@code true} if the generated PDF should be a PDF/A-1b
138     * @param disposition the signing disposition
139     * @param archiveFilename the archive filename when using an archive
140     * @return a blob containing the signed PDF
141     * @throws SignException
142     * @throws ConversionException
143     */
144    Blob signDocument(DocumentModel doc, DocumentModel user, String userKeyPassword, String reason, boolean pdfa,
145            SigningDisposition disposition, String archiveFilename);
146
147    /**
148     * Signs a PDF document with a user certificate. Requires a password to retrieve the certificate from the user
149     * keystore.
150     *
151     * @param doc Document model beign signed
152     * @param pdfBlob the blob containing the PDF to sign
153     * @param user the signing user
154     * @param userKeyPassword the password for the user's signing certificate
155     * @param reason the signing reason
156     * @return a blob containing the signed PDF
157     * @throws SignException
158     */
159    Blob signPDF(Blob pdfBlob, DocumentModel doc, DocumentModel user, String userKeyPassword, String reason) throws SignException;
160
161    /**
162     * Returns a list of certificates associated with a given document.
163     *
164     * @param doc the document
165     * @return the list of certificates (may be empty)
166     */
167    List<X509Certificate> getCertificates(DocumentModel doc);
168
169    SignatureLayout getSignatureLayout();
170}