View Javadoc

1   /**
2    * LICENCIA LGPL:
3    * 
4    * Esta librería es Software Libre; Usted puede redistribuirla y/o modificarla
5    * bajo los términos de la GNU Lesser General Public License (LGPL) tal y como 
6    * ha sido publicada por la Free Software Foundation; o bien la versión 2.1 de 
7    * la Licencia, o (a su elección) cualquier versión posterior.
8    * 
9    * Esta librería se distribuye con la esperanza de que sea útil, pero SIN 
10   * NINGUNA GARANTÍA; tampoco las implícitas garantías de MERCANTILIDAD o 
11   * ADECUACIÓN A UN PROPÓSITO PARTICULAR. Consulte la GNU Lesser General Public 
12   * License (LGPL) para más detalles
13   * 
14   * Usted debe recibir una copia de la GNU Lesser General Public License (LGPL) 
15   * junto con esta librería; si no es así, escriba a la Free Software Foundation 
16   * Inc. 51 Franklin Street, 5º Piso, Boston, MA 02110-1301, USA o consulte
17   * <http://www.gnu.org/licenses/>.
18   *
19   * Copyright 2011 Agencia de Tecnología y Certificación Electrónica
20   */
21  package es.accv.arangi.base.signature;
22  
23  import java.io.ByteArrayInputStream;
24  import java.io.File;
25  import java.io.FileInputStream;
26  import java.io.FileNotFoundException;
27  import java.io.FileOutputStream;
28  import java.io.IOException;
29  import java.io.InputStream;
30  import java.net.URL;
31  import java.security.InvalidKeyException;
32  import java.security.NoSuchAlgorithmException;
33  import java.security.NoSuchProviderException;
34  import java.security.PrivateKey;
35  import java.security.cert.X509Certificate;
36  import java.text.SimpleDateFormat;
37  import java.util.ArrayList;
38  import java.util.Arrays;
39  import java.util.Calendar;
40  import java.util.Collections;
41  import java.util.Date;
42  import java.util.HashMap;
43  import java.util.HashSet;
44  import java.util.Iterator;
45  import java.util.List;
46  import java.util.Set;
47  
48  import org.apache.log4j.Logger;
49  import org.bouncycastle.asn1.ocsp.BasicOCSPResponse;
50  import org.bouncycastle.cert.ocsp.BasicOCSPResp;
51  import org.bouncycastle.cert.ocsp.OCSPResp;
52  
53  import com.itextpdf.text.DocumentException;
54  import com.itextpdf.text.Image;
55  import com.itextpdf.text.Rectangle;
56  import com.itextpdf.text.pdf.AcroFields;
57  import com.itextpdf.text.pdf.PdfDate;
58  import com.itextpdf.text.pdf.PdfDictionary;
59  import com.itextpdf.text.pdf.PdfDocumentSecurityStore;
60  import com.itextpdf.text.pdf.PdfName;
61  import com.itextpdf.text.pdf.PdfPKCS7;
62  import com.itextpdf.text.pdf.PdfReader;
63  import com.itextpdf.text.pdf.PdfSigGenericPKCS;
64  import com.itextpdf.text.pdf.PdfSignature;
65  import com.itextpdf.text.pdf.PdfSignatureAppearance;
66  import com.itextpdf.text.pdf.PdfStamper;
67  import com.itextpdf.text.pdf.PdfString;
68  import com.itextpdf.text.pdf.TSAClient;
69  import com.itextpdf.text.pdf.TSAClientBouncyCastle;
70  
71  import es.accv.arangi.base.algorithm.DigitalSignatureAlgorithm;
72  import es.accv.arangi.base.algorithm.HashingAlgorithm;
73  import es.accv.arangi.base.certificate.Certificate;
74  import es.accv.arangi.base.certificate.validation.CAList;
75  import es.accv.arangi.base.certificate.validation.CRL;
76  import es.accv.arangi.base.certificate.validation.CertificateOCSPResponse;
77  import es.accv.arangi.base.certificate.validation.CertificateValidationService;
78  import es.accv.arangi.base.certificate.validation.CertificateValidator;
79  import es.accv.arangi.base.certificate.validation.OCSPClient;
80  import es.accv.arangi.base.certificate.validation.OCSPResponse;
81  import es.accv.arangi.base.certificate.validation.ValidateCertificate;
82  import es.accv.arangi.base.device.DeviceManager;
83  import es.accv.arangi.base.document.IDocument;
84  import es.accv.arangi.base.document.InputStreamDocument;
85  import es.accv.arangi.base.exception.certificate.CRLParsingException;
86  import es.accv.arangi.base.exception.certificate.CertificateCANotFoundException;
87  import es.accv.arangi.base.exception.certificate.NormalizeCertificateException;
88  import es.accv.arangi.base.exception.certificate.validation.MalformedOCSPResponseException;
89  import es.accv.arangi.base.exception.device.AliasNotFoundException;
90  import es.accv.arangi.base.exception.device.LoadingObjectException;
91  import es.accv.arangi.base.exception.device.SearchingException;
92  import es.accv.arangi.base.exception.document.HashingException;
93  import es.accv.arangi.base.exception.signature.AlgorithmNotSuitableException;
94  import es.accv.arangi.base.exception.signature.InvalidCertificateException;
95  import es.accv.arangi.base.exception.signature.PDFDocumentException;
96  import es.accv.arangi.base.exception.signature.RetrieveOCSPException;
97  import es.accv.arangi.base.exception.signature.SignatureException;
98  import es.accv.arangi.base.exception.signature.SignatureNotFoundException;
99  import es.accv.arangi.base.exception.timestamp.MalformedTimeStampException;
100 import es.accv.arangi.base.exception.timestamp.ResponseTimeStampException;
101 import es.accv.arangi.base.exception.timestamp.TimeStampServerConnectionException;
102 import es.accv.arangi.base.timestamp.TimeStamp;
103 import es.accv.arangi.base.timestamp.TimeStampRequestParameters;
104 import es.accv.arangi.base.util.Util;
105 import es.accv.arangi.base.util.validation.ValidationResult;
106 
107 /**
108  * Clase para manejar firmas en PDF (PAdES-A) según los estándares 
109  * <a href="http://www.etsi.org/deliver/etsi_ts/102700_102799/10277804/01.01.01_60/ts_10277804v010101p.pdf" target="estandar">ETSI TS 102 778-4 V1.2.1</a> 
110  * y <a href="http://www.telecomforum.eu/deliver/etsi_ts/119100_119199/11914402/01.01.01_60/ts_11914402v010101p.pdf" target="estandar">ETSI TS 119 144-2 V1.1.1</a>,
111  * basado en la norma <a href="http://www.iso.org/iso/catalogue_detail.htm?csnumber=51502" target="estandar">ISO 32000-1</a><br><br>
112  * 
113  * Por motivos de compatibilidad la clase sigue llamándose PAdESLTVSignature 
114  * aunque sería más correcto llamarla PAdESASignature, ya que siempre se
115  * trabajará con sellos de tiempo de documento, que son lo que diferencia
116  * a un PAdES-LTV de un PAdES-A según la norma ETSI TS 119 144-2.<br><br>
117  * 
118  * La norma ETSI TS 119 144-2 exige añadir más información de validación que
119  * la que se establecía en la ETSI TS 102 778-4. Por ello, las firmas realizadas 
120  * con versiones de Arangí anteriores a la 1.1.4 no serán consideradas válidas por 
121  * dicha versión o versiones posteriores. Para evitar este incoveniente a aquellos 
122  * desarrollos que se hayan realizado con versiones antiguas es posible activar un 
123  * flag estático antes de la validación que permitirá que en las validaciones no 
124  * se tenga en cuenta la información extra exigida por la nueva norma:<br><br>
125  * 
126  * <code>
127  * PAdESLTVSignature.olderVersionsAllowed = true;
128  * </code><br><br>
129  * 
130  * Este tipo de firmas cumplen con los requisitos para ser firmas longevas. En 
131  * ellas se incluye toda la información necesaria para validar los certificados
132  * de las firmas. También se añade un sello de tiempos para el documento que
133  * da garantias sobre la fecha en la que se realizaron las firmas.<br><br>
134  * 
135  * Las últimas versiones de Adobe Acrobat ya utilizan este tipo de firmas, aunque 
136  * existen algunas diferencias entre las firmas PAdES-LTV obtenidas por Adobe y las
137  * normas de la ETSI. En la documentación de Arangí debe haber una explicación de
138  * cuales son estas diferencias.<br><br>
139  * 
140  * Para evitar problemas de saturación de memoria con ficheros PDF muy grandes,
141  * esta clase siempre trabajará sobre un objeto java.io.File. Si el objeto no se 
142  * inicializa con un fichero se creará un archivo temporal en la carpeta temporal 
143  * de Arangi: {@link #getArangiTemporalFolder() getArangiTemporalFolder}.<br><br>
144  * 
145  * Existen dos métodos para obtener una firma PAdES-LTV, dependiendo de si se desea 
146  * una firma visible o invisible. En el caso de las firmas visibles hay que proporcionar 
147  * al método las coordenadas de las esquinas inferior izquierda y superior derecha, así 
148  * como el número de página donde se desea ubicar la firma. También es posible asociar
149  * una imagen a la firma.<br><br>
150  * 
151  * <code>
152  * KeyStoreManager manager = new KeyStoreManager (...,...);<br>
153  * String alias = ...;<br>
154  * ByteArrayDocument documentPDF = new ByteArrayDocument (...);<br>
155  * URL urlTSA = new URL (...);<br>
156  * CAList caList = new CAList (...);<br><br>
157  * 
158  * //-- Firma invisible<br>
159  * PAdESLTVSignature signatureInv = PAdESLTVSignature.sign (new KeyStoreManager[] {manager}, new String[] {alias}, documentPDF, urlTSA, caList, "Porque quiero firmarlo");<br><br>
160  * 
161  * //-- Firma visible<br>
162  * PAdESLTVSignature signatureVis = PAdESLTVSignature.sign (new KeyStoreManager[] {manager}, new String[] {alias},documentPDF, urlTSA, caList, "Porque quiero firmarlo",
163  *      true, Util.readStream(ClassLoader.getSystemResourceAsStream("signature/chip.gif")), 100, 100, 300, 200, 1);<br><br>
164  * </code>
165  * 
166  * En la página 1 de la segunda firma, en la ubicación indicada por las coordenadas, se 
167  * verá la imagen chip.gif como una firma realizada sobre el PDF.<br><br>
168  * 
169  * El primer parámetro de la firma es un array de managers, ya que es posible realizar 
170  * varias firmas a la vez. Es importante destacar que una vez se han añadido los campos 
171  * que hacen de un PDF firmado un PAdES-LTV ya no es posible volver a firmar el documento. 
172  * Si un documento se va firmar por varias personas de forma no simultanea lo que se debe 
173  * hacer es realizar las firmas en un PDF con firma simple y, tras la última firma 
174  * completar a PAdES-LTV. Por supuesto, entre el principio y el fin del proceso ninguno 
175  * de los certificados implicados podrá caducar o ser revocado.<br><br>
176  * 
177  * <code>
178  * URL urlTSA = new URL (...);<br>
179  * CAList caList = new CAList (...);<br><br>
180 
181  * //-- Primera firma<br>
182  * KeyStoreManager manager1 = new KeyStoreManager (...,...);<br>
183  * ByteArrayDocument documentPDF = new ByteArrayDocument (...);<br>
184  * String alias1 = ...;<br>
185  * PDFSignature signature = PDFSignature.sign (new KeyStoreManager[] {manager1}, new String[] {alias1}, documentPDF, urlTSA, caList, "Firma 1");<br><br>
186  * 
187  * //-- Segunda firma (días más tarde)<br>
188  * KeyStoreManager manager2 = new KeyStoreManager (...,...);<br>
189  * String alias2 = ...;<br>
190  * documentPDF = new ByteArrayDocument (signature.toByteArray());<br>
191  * signature = PDFSignature.sign (new KeyStoreManager[] {manager2}, new String[] {alias2}, documentPDF, urlTSA, caList, "Firma 2");<br><br>
192  * 
193  * //-- Completar la firma para que sea PAdES-LTV<br>
194  * PAdESLTVSignature padesLTV = PAdESLTVSignature.completeToPAdESLTV(signature, urlTSA, caList);<br><br>
195  * </code><br><br>
196  * 
197  * La validez de una firma longeva se halla limitada a la vida del certificado del último sello 
198  * de tiempos de documento que contiene el PDF, aunque erroneamente se suele pensar que una firma 
199  * longeva puede validarse eternamente. Por ejemplo, el certificado de la TSA de la ACCV caducará 
200  * el 18 de Noviembre de 2016, lo que implica que a partir de esa fecha las firmas PAdES-LTV 
201  * realizadas con la TSA de la ACCV dejarán de ser válidas. Con el objeto de alargar la vida de
202  * una firma longeva será necesario realizar un resellado de la misma cuando se cambie el certificado
203  * de la TSA. Este sería el código para realizar un resellado: <br><br>
204  * 
205  * <code>
206  * URL urlTSA = new URL (...);<br>
207  * CAList caList = new CAList (...);<br><br>
208  * ByteArrayDocument document = new ByteArrayDocument (...);<br>
209  * PAdESLTVSignature signature = new PAdESLTVSignature(document);<br>
210  * signature.addDocumentTimeStamp(urlTSA, caList);<br>
211  * signature.save(...);<br>
212  * </code>
213  * 
214  * @author <a href="mailto:jgutierrez@accv.es">José M Gutiérrez</a>
215  */
216 public class PAdESLTVSignature extends BasePDFSignature {
217 
218 	/*
219 	 * Constante para incluir como motivo de la firma cuando éste no es pasado 
220 	 * como parámetro
221 	 */
222 	private static final String DEFAULT_SIGNATURE_REASON = "Firma realizada con Arangi (ACCV)";
223 
224     private final static boolean embedOcspInSignature = false;
225 
226     private static final String HASH_ALGORITHM = embedOcspInSignature ?"SHA256" : "SHA1";
227     
228     private static boolean onlyOCSPResponsesInDSS = true;
229     
230     /**
231      * Si es cierto en las validaciones se permitirán firmas PAdES-LTV realizadas
232      * con versiones de Arangí anteriores a la 1.1.4. Por defecto tiene un valor
233      * de falso.
234      */
235     public static boolean olderVersionsAllowed = false; 
236 
237 	/*
238 	 * Logger de la clase 
239 	 */
240 	static Logger logger = Logger.getLogger(PAdESLTVSignature.class);
241 	
242 	//-- Constructores
243 	
244 	/**
245 	 * Inicializa el objeto con un fichero PDF firmado.
246 	 * 
247 	 * @param pdfFile Fichero PDF firmado
248 	 * @throws PDFDocumentException El fichero no es un PDF correcto o bien no puede 
249 	 * 	ser leído
250 	 * @throws SignatureNotFoundException El fichero es un PDF pero no está firmado
251 	 */
252 	public PAdESLTVSignature (File pdfFile) throws PDFDocumentException, SignatureNotFoundException {
253 		//-- Guardar en un fichero temporal
254 		File fileTemp = null;
255 		try {
256 			fileTemp = getFileTemp ();
257 			Util.saveFile(fileTemp, Util.loadFile(pdfFile));
258 		} catch (IOException e) {
259 			logger.info("[PAdESLTVSignature(byte[])::No se puede crear el fichero temporal o no se puede escribir en él", e);
260 			if (fileTemp != null) { fileTemp.delete(); }
261 			throw new PDFDocumentException ("No se puede crear el fichero temporal o no se puede escribir en él", e);
262 		}
263 
264 		initialize(fileTemp);
265 	}
266 	
267 	/**
268 	 * Inicializa el objeto con el contenido de un fichero PDF firmado.
269 	 * 
270 	 * @param pdfContentBytes Array de bytes con el contenido del fichero PDF firmado
271 	 * @throws PDFDocumentException El fichero no es un PDF correcto o bien no puede 
272 	 * 	ser leído
273 	 * @throws SignatureNotFoundException El fichero es un PDF pero no está firmado
274 	 * @throws IOException No se puede crear el fichero temporal
275 	 */
276 	public PAdESLTVSignature (byte[] pdfContentBytes) throws PDFDocumentException, SignatureNotFoundException, IOException {
277 		//-- Guardar en un fichero temporal
278 		File fileTemp = null;
279 		try {
280 			fileTemp = getFileTemp ();
281 			Util.saveFile(fileTemp, pdfContentBytes);
282 		} catch (IOException e) {
283 			logger.info("[PAdESLTVSignature(byte[])::No se puede crear el fichero temporal o no se puede escribir en él", e);
284 			if (fileTemp != null) { fileTemp.delete(); }
285 			throw e;
286 		}
287 		
288 		initialize(fileTemp);
289 	}
290 	
291 	/**
292 	 * Inicializa el objeto con un stream de lectura al contenido de un fichero PDF firmado.
293 	 * 
294 	 * @param streamPDF Stream de lectura al contenido del fichero PDF firmado
295 	 * @throws PDFDocumentException El fichero no es un PDF correcto o bien no puede 
296 	 * 	ser leído
297 	 * @throws SignatureNotFoundException El fichero es un PDF pero no está firmado
298 	 * @throws IOException No se puede crear el fichero temporal
299 	 */
300 	public PAdESLTVSignature (InputStream streamPDF) throws PDFDocumentException, SignatureNotFoundException, IOException {
301 		//-- Guardar en un fichero temporal
302 		File fileTemp = null;
303 		try {
304 			fileTemp = getFileTemp ();
305 			Util.saveFile(fileTemp, streamPDF);
306 		} catch (IOException e) {
307 			logger.info("[PAdESLTVSignature(byte[])::No se puede crear el fichero temporal o no se puede escribir en él", e);
308 			if (fileTemp != null) { fileTemp.delete(); }
309 			throw e;
310 		} 
311 		
312 		//-- Inicializar
313 		initialize(fileTemp);
314 	}
315 	
316 	/**
317 	 * Inicializa el objeto con un documento que debe contener un fichero PDF firmado.
318 	 * 
319 	 * @param document Documento con el contenido del fichero PDF firmado
320 	 * @throws PDFDocumentException El fichero no es un PDF correcto o bien no puede 
321 	 * 	ser leído
322 	 * @throws SignatureNotFoundException El fichero es un PDF pero no está firmado
323 	 * @throws IOException No se puede crear el fichero temporal
324 	 */
325 	public PAdESLTVSignature (IDocument document) throws PDFDocumentException, SignatureNotFoundException, IOException {
326 		//-- Guardar en un fichero temporal
327 		InputStream fis = null;
328 		File fileTemp = null;
329 		try {
330 			fileTemp = getFileTemp ();
331 			fis = document.getInputStream();
332 			Util.saveFile(fileTemp, fis);
333 		} catch (IOException e) {
334 			logger.info("[PAdESLTVSignature(byte[])::No se puede crear el fichero temporal o no se puede escribir en él", e);
335 			if (fileTemp != null) { fileTemp.delete(); }
336 			throw e;
337 		} finally {
338 			if (fis != null) {
339 				fis.close();
340 			}
341 		}
342 		
343 		//-- Inicializar
344 		initialize(fileTemp);
345 	}
346 	
347 	/*
348 	 * Inicializa el objeto con un documento igual.
349 	 */
350 	protected PAdESLTVSignature (PAdESLTVSignature signature) {
351 		this.pdfFile = signature.pdfFile;
352 	}
353 	
354 	//-- Métodos estáticos
355 	
356 	/**
357 	 * Obtiene un objeto {@link PAdESLTVSignature} tras firmar un documento PDF.
358 	 * La firma es invisible.
359 	 * 
360 	 * @param managers Dispositivos criptográfico que realizarán la firma
361 	 * @param alias Alias donde se encuentran las claves privada dentro de los dispositivos
362 	 * @param pdfDocument Documento PDF a firmar
363 	 * @param urlTimestamp URL del servidor de sello de tiempos
364 	 * @param caList Lista de certificados de CA, uno de ellos ha de ser el emisor del 
365 	 * 	certificado con el que se realiza la firma
366 	 * @param reason Texto que aparecerá junto a la firma como razón. Si se pasa un valor
367 	 * 	nulo se escribirá un texto por defecto.
368 	 * @return Documento PDF firmado, con sello de tiempos y respuesta OCSP
369 	 * @throws AliasNotFoundException El alias donde se encuentra la clave privada usada para
370 	 * 	realizar la firma no existe
371 	 * @throws LoadingObjectException No ha sido posible cargar la clave privada usada para
372 	 * 	realizar la firma
373 	 * @throws PDFDocumentException El documento no es un fichero PDF o es un PDF mal formado
374 	 * @throws SignatureException No se puede realizar la firma
375 	 * @throws RetrieveOCSPException No es posible obtener una respuesta OCSP para
376 	 * 	asociarla a la firma
377 	 * @throws HashingException Excepción obteniendo el hash que será sellado por la TSA
378 	 * @throws CertificateCANotFoundException La lista de certificado de CA no contiene el 
379 	 * 	emisor del certificado de firma o existe pero tiene un formato no normalizable por 
380 	 * 	el proveedor criptográfico de Arangi
381 	 * @throws InvalidCertificateException El certificado con el que se firma está revocado
382 	 * @throws NormalizeCertificateException Alguno de los certificados de firma o de sus cadenas
383 	 * 	de certificación no puede ser normalizado
384 	 */
385 	public static PAdESLTVSignature sign (DeviceManager[] managers, String[] alias, IDocument pdfDocument, URL urlTimestamp, 
386 			CAList caList, String reason) throws AliasNotFoundException, LoadingObjectException, PDFDocumentException, SignatureException, RetrieveOCSPException, HashingException, CertificateCANotFoundException, InvalidCertificateException, NormalizeCertificateException {
387 		try {
388 			return sign (managers, alias, pdfDocument, null, urlTimestamp, null, null, caList, reason, false, null, -1, -1, -1, -1, 0);
389 		} catch (AlgorithmNotSuitableException e) {
390 			logger.info("El algoritmo por defecto no debería provocar este error", e);
391 			throw new SignatureException("El algoritmo por defecto no debería provocar este error", e);
392 		}
393 	}
394 	
395 	/**
396 	 * Obtiene un objeto {@link PAdESLTVSignature} tras firmar un documento PDF.
397 	 * El servidor de la TSA requiere autenticación y la firma obtenida es invisible.
398 	 * 
399 	 * @param managers Dispositivos criptográfico que realizarán la firma
400 	 * @param alias Alias donde se encuentran las claves privada dentro de los dispositivos
401 	 * @param pdfDocument Documento PDF a firmar
402 	 * @param urlTimestamp URL del servidor de sello de tiempos
403 	 * @param userTSA Usuario para acceder al servidor de sello de tiempos. Nulo si no
404 	 * 	requiere autenticación.
405 	 * @param passwordTSA Contraseña para acceder al servidor de sello de tiempos. Nula si 
406 	 * no requiere autenticación.
407 	 * @param caList Lista de certificados de CA, uno de ellos ha de ser el emisor del 
408 	 * 	certificado con el que se realiza la firma
409 	 * @param reason Texto que aparecerá junto a la firma como razón. Si se pasa un valor
410 	 * 	nulo se escribirá un texto por defecto.
411 	 * @return Documento PDF firmado, con sello de tiempos y respuesta OCSP
412 	 * @throws AliasNotFoundException El alias donde se encuentra la clave privada usada para
413 	 * 	realizar la firma no existe
414 	 * @throws LoadingObjectException No ha sido posible cargar la clave privada usada para
415 	 * 	realizar la firma
416 	 * @throws PDFDocumentException El documento no es un fichero PDF o es un PDF mal formado
417 	 * @throws SignatureException No se puede realizar la firma
418 	 * @throws RetrieveOCSPException No es posible obtener una respuesta OCSP para
419 	 * 	asociarla a la firma
420 	 * @throws HashingException Excepción obteniendo el hash que será sellado por la TSA
421 	 * @throws CertificateCANotFoundException La lista de certificado de CA no contiene el 
422 	 * 	emisor del certificado de firma o existe pero tiene un formato no normalizable por 
423 	 * 	el proveedor criptográfico de Arangi
424 	 * @throws InvalidCertificateException El certificado con el que se firma está revocado
425 	 * @throws NormalizeCertificateException Alguno de los certificados de firma o de sus cadenas
426 	 * 	de certificación no puede ser normalizado
427 	 */
428 	public static PAdESLTVSignature sign (DeviceManager[] managers, String[] alias, IDocument pdfDocument, URL urlTimestamp, 
429 			String userTSA, String passwordTSA, CAList caList, String reason) throws AliasNotFoundException, LoadingObjectException, PDFDocumentException, SignatureException, RetrieveOCSPException, HashingException, CertificateCANotFoundException, InvalidCertificateException, NormalizeCertificateException {
430 		try {
431 			return sign (managers, alias, pdfDocument, null, urlTimestamp, userTSA, passwordTSA, caList, reason, false, null, -1, -1, -1, -1, 0);
432 		} catch (AlgorithmNotSuitableException e) {
433 			logger.info("El algoritmo por defecto no debería provocar este error", e);
434 			throw new SignatureException("El algoritmo por defecto no debería provocar este error", e);
435 		}
436 	}
437 	
438 	/**
439 	 * Obtiene un objeto {@link PAdESLTVSignature} tras firmar un documento PDF.<br><br>
440 	 * 
441 	 * Si la firma es visible se le puede asociar una imagen. El punto 0,0 de la página 
442 	 * se encuentra en la esquina inferior izquierda de la misma. Un página tiene 
443 	 * aproximadamente unas dimensiones de 580x850. 
444 	 * 
445 	 * @param managers Dispositivos criptográfico que realizarán la firma
446 	 * @param alias Alias donde se encuentran las claves privada dentro de los dispositivos
447 	 * @param pdfDocument Documento PDF a firmar
448 	 * @param digitalSignatureAlgorithm Algoritmo de firma (si nulo algoritmo por defecto)
449 	 * @param urlTimestamp URL del servidor de sello de tiempos
450 	 * @param userTSA Usuario para acceder al servidor de sello de tiempos. Nulo si no
451 	 * 	requiere autenticación.
452 	 * @param passwordTSA Contraseña para acceder al servidor de sello de tiempos. Nula si 
453 	 * no requiere autenticación.
454 	 * @param caList Lista de certificados de CA, uno de ellos ha de ser el emisor del 
455 	 * 	certificado con el que se realiza la firma
456 	 * @param reason Texto que aparecerá junto a la firma como razón. Si se pasa un valor
457 	 * 	nulo se escribirá un texto por defecto.
458 	 * @param isVisible Si tiene un valor cierto se creará una firma visible.
459 	 * @param image Imagen de la firma. Puede tener un valor nulo.
460 	 * @param llX Posición X de la esquina inferior izquierda de la firma en la página (caso de ser visible)
461 	 * @param llY Posición Y de la esquina inferior izquierda de la firma en la página (caso de ser visible) 
462 	 * @param urX Posición X de la esquina superior derecha de la firma en la página (caso de ser visible)
463 	 * @param urY Posición Y de la esquina superior derecha de la firma en la página (caso de ser visible)
464 	 * @param page Página en la que se situará la firma si ésta es visible (1 es la primera página)
465 	 * @return Documento PDF firmado, con sello de tiempos y respuesta OCSP
466 	 * @throws AliasNotFoundException El alias donde se encuentra la clave privada usada para
467 	 * 	realizar la firma no existe
468 	 * @throws LoadingObjectException No ha sido posible cargar la clave privada usada para
469 	 * 	realizar la firma
470 	 * @throws PDFDocumentException El documento no es un fichero PDF o es un PDF mal formado
471 	 * @throws SignatureException No se puede realizar la firma
472 	 * @throws RetrieveOCSPException No es posible obtener una respuesta OCSP para
473 	 * 	asociarla a la firma
474 	 * @throws HashingException Excepción obteniendo el hash que será sellado por la TSA
475 	 * @throws CertificateCANotFoundException La lista de certificado de CA no contiene el 
476 	 * 	emisor del certificado de firma o existe pero tiene un formato no normalizable por 
477 	 * 	el proveedor criptográfico de Arangi
478 	 * @throws InvalidCertificateException El certificado con el que se firma está revocado
479 	 * @throws NormalizeCertificateException Alguno de los certificados de firma o de sus cadenas
480 	 * 	de certificación no puede ser normalizado
481 	 * @throws AlgorithmNotSuitableException El algoritmo de firma pasado no sirve para realizar la firma
482 	 */
483 	public static PAdESLTVSignature sign (DeviceManager[] managers, String[] alias, IDocument pdfDocument, 
484 			String digitalSignatureAlgorithm, URL urlTimestamp, String userTSA, String passwordTSA, 
485 			CAList caList, String reason, boolean isVisible, byte[] image, float llX, float llY, 
486 			float urX, float urY, int page) throws AliasNotFoundException, LoadingObjectException, PDFDocumentException, SignatureException, RetrieveOCSPException, HashingException, CertificateCANotFoundException, InvalidCertificateException, NormalizeCertificateException, AlgorithmNotSuitableException {
487 		
488 		logger.debug("[PAdESLTVSignature.sign]::Entrada::" + Arrays.asList (new Object [] { managers, alias, pdfDocument, digitalSignatureAlgorithm, urlTimestamp, userTSA, passwordTSA, caList, reason, new Boolean (isVisible), image, new Float (llX), new Float (llY), new Float (urX), new Float (urY), new Integer (page) }));
489 		
490 		FileOutputStream fos = null;
491 		try {
492 		
493 			//-- Comprobar parámetros
494 			if (reason == null) {
495 				reason = DEFAULT_SIGNATURE_REASON;
496 			}
497 			
498 			//-- Algoritmos
499 			if (digitalSignatureAlgorithm == null) {
500 				digitalSignatureAlgorithm = DigitalSignatureAlgorithm.getDefault();
501 			}
502 			String hashingAlgorithm = DigitalSignatureAlgorithm.getHashingAlgorithm(digitalSignatureAlgorithm);
503 			if (hashingAlgorithm == null) {
504 				logger.info("No se puede tratar el algoritmo de firma " + digitalSignatureAlgorithm);
505 				throw new AlgorithmNotSuitableException("No se puede tratar el algoritmo de firma " + digitalSignatureAlgorithm);
506 			}
507 	
508 			//-- Cliente TSA (de iText)
509 			TSAClient tsc = new TSAClientBouncyCastle(urlTimestamp.toString(), userTSA, passwordTSA);
510 			
511 			//-- Obtener el fichero temporal donde se dejará el resultado
512 			File fileResult1 = getFileTemp();
513 			Util.saveFile(fileResult1, pdfDocument.getInputStream());
514 			
515 			//-- Si lo último es un sello de tiempos añadir DSS para él antes de firmar
516 			FileInputStream fis = new FileInputStream(fileResult1);
517 			PdfReader reader = new PdfReader(fis);
518 			addDocumentTimeStampDSS(reader, caList, fileResult1);
519 			reader.close();
520 			fis.close();
521 			
522 			List<String> diccionariosRecienFirmados = new ArrayList<String>();
523 			for (int i = 0; i < managers.length; i++) {
524 				
525 				//-- Obtener la clave privada
526 				PrivateKey pk = managers[i].getPrivateKey(alias[i]);
527 				if (pk == null) {
528 					logger.info("[PDFSignature.sign]::No se ha podido encontrar el alias o bien éste no contiene una clave privada");
529 					throw new AliasNotFoundException ("No se ha podido encontrar el alias o bien éste no contiene una clave privada");
530 				}
531 				
532 				//--Obtener y validar el certificado
533 				X509Certificate x509Certificate = managers[i].getCertificate(alias[i]);
534 				ValidateCertificate validateCertificate = new ValidateCertificate (x509Certificate, caList);
535 				int validationResult;
536 				if ((validationResult = validateCertificate.validate()) != ValidationResult.RESULT_VALID) {
537 					logger.info("[PDFSignature.sign]::El certificado de firma no es válido: " + validationResult);
538 					throw new InvalidCertificateException ("El certificado de firma no es válido: " + validationResult, validationResult);
539 				}
540 				
541 				//-- Cadena de confianza
542 				java.security.cert.Certificate[] chain = new java.security.cert.Certificate[] { x509Certificate, validateCertificate.getIssuerCertificate().toX509Certificate() };
543 		
544 				//-- Leer el PDF y crear la firma. Dependiendo de si el PDF ya
545 				//-- está firmado o no se crea el PdfStamper de una manera u otra
546 				fis = new FileInputStream(fileResult1);
547 				reader = new PdfReader(fis);
548 				File fileResult2 = getFileTemp();
549 				fos = new FileOutputStream (fileResult2);
550 				AcroFields af = reader.getAcroFields();
551 				ArrayList names = af.getSignatureNames();
552 				PdfStamper stp;
553 				if (names == null || names.isEmpty()) {
554 					stp = PdfStamper.createSignature(reader, fos, '\0');
555 				} else {
556 					stp = PdfStamper.createSignature(reader, fos, '\0', null, true);
557 				}
558 				
559 				//-- Apariencia de la firma
560 				PdfSignatureAppearance sap = stp.getSignatureAppearance();
561 				sap.setCrypto(null, chain, null, PdfSignatureAppearance.SELF_SIGNED);
562 				sap.setReason(reason);
563 				if (isVisible) {
564 					sap.setVisibleSignature(new Rectangle(llX, llY, urX, urY), page, null);
565 					StringBuffer detail = new StringBuffer();
566 					detail.append(DIGITALLY_SIGNED_TEXT + ": " + validateCertificate.getCommonName() + "\n");
567 					SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm");
568 					detail.append("Fecha: " + sdf.format(new Date()) + "\n");
569 					if (reason != null && !reason.equals("")) {
570 						detail.append("Motivo: " + reason + "\n");
571 					}
572 					sap.setLayer2Text(detail.toString());
573 					if (image != null) {
574 						sap.setImage(Image.getInstance(image));
575 					}
576 				}
577 		
578 				//-- Cargar valores en el diccionario
579 				PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("adbe.pkcs7.detached"));
580 				dic.setReason(sap.getReason());
581 				dic.setLocation(sap.getLocation());
582 				dic.setContact(sap.getContact());
583 				dic.setDate(new PdfDate(sap.getSignDate()));
584 				sap.setCryptoDictionary(dic);
585 				sap.setExternalDigest(new byte[128], null, "RSA"); 
586 		
587 				int contentEstimated = 15000;
588 				HashMap exc = new HashMap();
589 				exc.put(PdfName.CONTENTS, new Integer(contentEstimated * 2 + 2));
590 				sap.preClose(exc);
591 		
592 				//-- Construir el PKCS#7 (firmando con el manager de Arangi)
593 				Calendar cal = Calendar.getInstance();
594 				PdfPKCS7 pkcs7 = new PdfPKCS7(null, chain, null, hashingAlgorithm, CRYPTOGRAPHIC_PROVIDER_NAME, false);
595 				byte hash[] = new InputStreamDocument (sap.getRangeStream()).getHash(hashingAlgorithm);
596 				byte sh[] = pkcs7.getAuthenticatedAttributeBytes(hash, cal, null);
597 				byte[] signatureBytes = managers[i].signDocument(new ByteArrayInputStream (sh), alias[i], digitalSignatureAlgorithm);
598 				pkcs7.setExternalDigest(signatureBytes, sh, "RSA"); 
599 				byte[] encodedSig = pkcs7.getEncodedPKCS7(hash, cal, tsc, hashingAlgorithm, null);
600 				
601 				//-- Añadir la firma al diccionario
602 				if (contentEstimated + 2 < encodedSig.length) {
603 					logger.info("[PDFSignature.sign]::No se puede añadir la firma al PDF por falta de espacio en el mismo");
604 					throw new SignatureException ("No se puede añadir la firma al PDF por falta de espacio en el mismo");
605 				}
606 		
607 				byte[] paddedSig = new byte[contentEstimated];
608 				System.arraycopy(encodedSig, 0, paddedSig, 0, encodedSig.length);
609 		
610 				PdfDictionary dic2 = new PdfDictionary();
611 				dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));
612 				sap.close(dic2);
613 				
614 				fis.close();
615 	            reader.close();
616 	            fos.close();
617 	            fos = null;
618 	            
619 	            fileResult1.delete();
620 	            fileResult1 = fileResult2;
621 	            
622 	            diccionariosRecienFirmados.add(sap.getFieldName());
623 	            
624 			}
625 
626 			//-- Completar a PAdES-LTV)
627 			reader = null;
628 			fis = null;
629 			try {
630 				fis = new FileInputStream(fileResult1);
631 				reader = new PdfReader(fis);
632 				return PAdESLTVSignature.completeToPAdESLTV(reader, urlTimestamp, userTSA, passwordTSA, hashingAlgorithm, caList, diccionariosRecienFirmados);
633 			} catch (PDFDocumentException e) {
634 				//-- No se va a dar, el fichero se acaba de firmar
635 				return null;
636 			} finally {
637 				if (fis != null) { fis.close(); }
638 				if (reader != null) { reader.close(); }
639 				fileResult1.delete();
640 			}
641 			
642 		} catch (LoadingObjectException e) {
643 			logger.info("[PAdESLTVSignature.sign]::No se ha podido obtener la clave privada para firma", e);
644 			throw new LoadingObjectException ("No se ha podido obtener la clave privada para firma", e);
645 		} catch (SearchingException e) {
646 			logger.info("[PAdESLTVSignature.sign]::No se ha podido encontrar la clave privada para firma", e);
647 			throw new LoadingObjectException ("No se ha podido encontrar la clave privada para firma", e);
648 		} catch (IOException e) {
649 			logger.info("[PAdESLTVSignature.sign]::No se ha podido leer el fichero PDF o no se ha podido crear el fichero temporal con la firma", e);
650 			throw new PDFDocumentException ("No se ha podido leer el fichero PDF o no se ha podido crear el fichero temporal con la firma", e);
651 		} catch (DocumentException e) {
652 			logger.info("[PAdESLTVSignature.sign]::No se ha podido manejar alguna de las partes del fichero PDF", e);
653 			throw new PDFDocumentException ("No se ha podido manejar alguna de las partes del fichero PDF", e);
654 		} catch (InvalidKeyException e) {
655 			logger.info("[PAdESLTVSignature.sign]::La clave privada no es válida para realizar la firma", e);
656 			throw new SignatureException ("La clave privada no es válida para realizar la firma", e);
657 		} catch (NoSuchProviderException e) {
658 			logger.info("[PAdESLTVSignature.sign]::No se ha podido obtener el proveedor criptográfico", e);
659 			return null;
660 		} catch (NoSuchAlgorithmException e) {
661 			logger.info("[PAdESLTVSignature.sign]::No existen en el proveedor criptográfico los algoritmos de firma (SHA1WithRSA)", e);
662 			throw new SignatureException ("No existen en el proveedor criptográfico los algoritmos de firma (SHA1WithRSA)", e);
663 		} catch (CertificateCANotFoundException e) {
664 			logger.info("[PAdESLTVSignature.sign]::La lista de certificado de CA no contiene el emisor del certificado de firma", e);
665 			throw new CertificateCANotFoundException ("La lista de certificado de CA no contiene el emisor del certificado de firma", e);
666 		} 
667 
668 	}
669 	
670 	/**
671 	 * Método que completa un fichero PDF firmado a PAdES-LTV. La firma del PDF firmado ha de ser
672 	 * correcta y los certificados han de ser válidos en este momento.
673 	 * 
674 	 * @param signature PDF firmado
675 	 * @param urlTimestamp URL del servidor de sello de tiempos
676 	 * @param caList Lista de certificados de CA, uno de ellos ha de ser el emisor del 
677 	 * 	certificado con el que se realiza la firma
678 	 * @return PAdES-LTV
679 	 * @throws PDFDocumentException El documento no es un fichero PDF o es un PDF mal formado
680 	 * @throws SignatureException Error completando la firma
681 	 * @throws RetrieveOCSPException No es posible obtener una respuesta OCSP para
682 	 * 	asociarla a la firma
683 	 * @throws HashingException Excepción obteniendo el hash que será sellado por la TSA
684 	 * @throws CertificateCANotFoundException La lista de certificado de CA no contiene el 
685 	 * 	emisor del certificado de firma o existe pero tiene un formato no normalizable por 
686 	 * 	el proveedor criptográfico de Arangi
687 	 * @throws InvalidCertificateException El certificado con el que se firma está revocado
688 	 * @throws NormalizeCertificateException Alguno de los certificados de firma o de sus cadenas
689 	 * 	de certificación no puede ser normalizado
690 	 */
691 	public static PAdESLTVSignature completeToPAdESLTV (PDFSignature signature, URL urlTimestamp, CAList caList) throws SignatureException, 
692 		RetrieveOCSPException, InvalidCertificateException, NormalizeCertificateException, PDFDocumentException, CertificateCANotFoundException, 
693 		HashingException {
694 		
695 		return PAdESLTVSignature.completeToPAdESLTV(signature, urlTimestamp, null, caList);
696 		
697 	}
698 
699 	/**
700 	 * Método que completa un fichero PDF firmado a PAdES-LTV. La firma del PDF firmado ha de ser
701 	 * correcta y los certificados han de ser válidos en este momento.
702 	 * 
703 	 * @param signature PDF firmado
704 	 * @param urlTimestamp URL del servidor de sello de tiempos
705 	 * @param tsaHashingAlgorithm Algoritmo de hash para llamar a la TSA
706 	 * @param caList Lista de certificados de CA, uno de ellos ha de ser el emisor del 
707 	 * 	certificado con el que se realiza la firma
708 	 * @return PAdES-LTV
709 	 * @throws PDFDocumentException El documento no es un fichero PDF o es un PDF mal formado
710 	 * @throws SignatureException Error completando la firma
711 	 * @throws RetrieveOCSPException No es posible obtener una respuesta OCSP para
712 	 * 	asociarla a la firma
713 	 * @throws HashingException Excepción obteniendo el hash que será sellado por la TSA
714 	 * @throws CertificateCANotFoundException La lista de certificado de CA no contiene el 
715 	 * 	emisor del certificado de firma o existe pero tiene un formato no normalizable por 
716 	 * 	el proveedor criptográfico de Arangi
717 	 * @throws InvalidCertificateException El certificado con el que se firma está revocado
718 	 * @throws NormalizeCertificateException Alguno de los certificados de firma o de sus cadenas
719 	 * 	de certificación no puede ser normalizado
720 	 */
721 	public static PAdESLTVSignature completeToPAdESLTV (PDFSignature signature, URL urlTimestamp, String tsaHashingAlgorithm, CAList caList) throws SignatureException, 
722 		RetrieveOCSPException, InvalidCertificateException, NormalizeCertificateException, PDFDocumentException, CertificateCANotFoundException, 
723 		HashingException {
724 		
725 		return PAdESLTVSignature.completeToPAdESLTV(signature, urlTimestamp, null, null, caList);
726 		
727 	}
728 
729 	/**
730 	 * Método que completa un fichero PDF firmado a PAdES-LTV. La firma del PDF firmado ha de ser
731 	 * correcta y los certificados han de ser válidos en este momento.
732 	 * 
733 	 * @param signature PDF firmado
734 	 * @param urlTimestamp URL del servidor de sello de tiempos
735 	 * @param userTSA Usuario para acceder al servidor de sello de tiempos. Nulo si no
736 	 * 	requiere autenticación.
737 	 * @param passwordTSA Contraseña para acceder al servidor de sello de tiempos. Nula si 
738 	 * no requiere autenticación.
739 	 * @param caList Lista de certificados de CA, uno de ellos ha de ser el emisor del 
740 	 * 	certificado con el que se realiza la firma
741 	 * @return PAdES-LTV
742 	 * @throws PDFDocumentException El documento no es un fichero PDF o es un PDF mal formado
743 	 * @throws SignatureException Error completando la firma
744 	 * @throws RetrieveOCSPException No es posible obtener una respuesta OCSP para
745 	 * 	asociarla a la firma
746 	 * @throws HashingException Excepción obteniendo el hash que será sellado por la TSA
747 	 * @throws CertificateCANotFoundException La lista de certificado de CA no contiene el 
748 	 * 	emisor del certificado de firma o existe pero tiene un formato no normalizable por 
749 	 * 	el proveedor criptográfico de Arangi
750 	 * @throws InvalidCertificateException El certificado con el que se firma está revocado
751 	 * @throws NormalizeCertificateException 
752 	 * @throws NormalizeCertificateException Alguno de los certificados de firma o de sus cadenas
753 	 * 	de certificación no puede ser normalizado
754 	 */
755 	public static PAdESLTVSignature completeToPAdESLTV (PDFSignature signature, URL urlTimestamp, 
756 			String userTSA, String passwordTSA, CAList caList) throws SignatureException, RetrieveOCSPException, InvalidCertificateException, 
757 			PDFDocumentException, CertificateCANotFoundException, HashingException, NormalizeCertificateException {
758 		return completeToPAdESLTV(signature, urlTimestamp, userTSA, passwordTSA, null, caList);
759 	}
760 	
761 	/**
762 	 * Método que completa un fichero PDF firmado a PAdES-LTV. La firma del PDF firmado ha de ser
763 	 * correcta y los certificados han de ser válidos en este momento.
764 	 * 
765 	 * @param signature PDF firmado
766 	 * @param urlTimestamp URL del servidor de sello de tiempos
767 	 * @param userTSA Usuario para acceder al servidor de sello de tiempos. Nulo si no
768 	 * 	requiere autenticación.
769 	 * @param passwordTSA Contraseña para acceder al servidor de sello de tiempos. Nula si 
770 	 * no requiere autenticación.
771 	 * @param tsaHashingAlgorithm Algoritmo de hash para llamar a la TSA
772 	 * @param caList Lista de certificados de CA, uno de ellos ha de ser el emisor del 
773 	 * 	certificado con el que se realiza la firma
774 	 * @return PAdES-LTV
775 	 * @throws PDFDocumentException El documento no es un fichero PDF o es un PDF mal formado
776 	 * @throws SignatureException Error completando la firma
777 	 * @throws RetrieveOCSPException No es posible obtener una respuesta OCSP para
778 	 * 	asociarla a la firma
779 	 * @throws HashingException Excepción obteniendo el hash que será sellado por la TSA
780 	 * @throws CertificateCANotFoundException La lista de certificado de CA no contiene el 
781 	 * 	emisor del certificado de firma o existe pero tiene un formato no normalizable por 
782 	 * 	el proveedor criptográfico de Arangi
783 	 * @throws InvalidCertificateException El certificado con el que se firma está revocado
784 	 * @throws NormalizeCertificateException 
785 	 * @throws NormalizeCertificateException Alguno de los certificados de firma o de sus cadenas
786 	 * 	de certificación no puede ser normalizado
787 	 */
788 	public static PAdESLTVSignature completeToPAdESLTV (PDFSignature signature, URL urlTimestamp, 
789 			String userTSA, String passwordTSA, String tsaHashingAlgorithm, CAList caList) throws SignatureException, RetrieveOCSPException, InvalidCertificateException, 
790 			PDFDocumentException, CertificateCANotFoundException, HashingException, NormalizeCertificateException {
791 		logger.debug ("[PAdESLTVSignature.completeToPAdESLTV]::Entrada::" + signature);
792 		
793 		FileInputStream fis = null;
794 		PdfReader reader = null;
795 		File fileResult = null;
796 		try {
797 			//-- Obtener el fichero temporal donde se dejará el resultado
798 			fileResult = getFileTemp();
799 			signature.save(fileResult);
800 			fis = new FileInputStream(fileResult);
801 			reader = new PdfReader(fis);
802 			
803 			return completeToPAdESLTV(reader, urlTimestamp, userTSA, passwordTSA, tsaHashingAlgorithm, caList, null);
804 			
805 		} catch (IOException e) {
806 			logger.info("[PAdESLTVSignature.completeToPAdESLTV]::No se ha podido leer el fichero PDF o no se ha podido crear el fichero temporal con la firma", e);
807 			throw new PDFDocumentException ("No se ha podido leer el fichero PDF o no se ha podido crear el fichero temporal con la firma", e);
808 		} finally {
809 			if (fis != null) { try { fis.close(); } catch (IOException e) { } }
810 			if (reader != null) { reader.close(); }
811 			if (fileResult != null) { fileResult.delete(); }
812 		}
813 		
814 	}
815 	
816 	//-- Métodos públicos
817 	
818 	/* (non-Javadoc)
819 	 * @see es.accv.arangi.base.signature.ISignature#isValid(es.accv.arangi.base.certificate.validation.CAList)
820 	 */
821 	public ValidationResult[] isValid(CAList caList) throws HashingException, SignatureException, NormalizeCertificateException {
822 		
823 		logger.debug("[PAdESLTVSignature.isValid]::Entrada::" + caList);
824 		
825 		return isValidCommon(caList, null);
826 		
827 	}
828 	
829 	/**
830 	 * En el caso de los PDF no tiene sentido realizar la validación sobre un 
831 	 * documento que no sea el mismo PDF. Por ello, el resultado de este método 
832 	 * será igual a llamar a {@link #isValid(CAList) isValid} con sólo un parámetro. 
833 	 */
834 	public ValidationResult[] isValid(IDocument document, CAList caList)
835 			throws HashingException, SignatureException,
836 			NormalizeCertificateException {
837 		return isValid (caList);
838 	}
839 	
840 	/* (non-Javadoc)
841 	 * @see es.accv.arangi.base.signature.ISignature#isValid(java.util.List(es.accv.arangi.base.certificate.validation.service.CertificateValidationService))
842 	 */
843 	public ValidationResult[] isValid(List<CertificateValidationService> validationServices)
844 			throws HashingException, SignatureException, NormalizeCertificateException {
845 		
846 		logger.debug("[PAdESLTVSignature.isValid]::Entrada::" + validationServices);
847 		
848 		return isValidCommon(null, validationServices);
849 		
850 	}
851 
852 	/**
853 	 * En el caso de los PDF no tiene sentido realizar la validación sobre un 
854 	 * documento que no sea el mismo PDF. Por ello, el resultado de este método 
855 	 * será igual a llamar a {@link #isValid(List) isValid} con sólo un parámetro. 
856 	 */
857 	public ValidationResult[] isValid(IDocument document, List<CertificateValidationService> validationServices)
858 			throws HashingException, SignatureException, NormalizeCertificateException {
859 		return isValid(validationServices);
860 	}
861 
862 	/**
863 	 * Devuelve una cadena de texto con el tipo de la firma
864 	 * 
865 	 * @return Cadena de texto con el tipo de la firma
866 	 */
867 	public String getSignatureType () {
868 		return "PAdES-LTV";
869 	}
870 	
871 	/**
872 	 * Obtiene la fecha en que caduca el certificado del sello de tiempo que cubre la 
873 	 * firma longeva.
874 	 * 
875 	 * @return Fecha de caducidad del sello de tiempo del documento
876 	 * @throws SignatureException No hay sello de tiempo del documento o éste no se 
877 	 * 	puede leer
878 	 */
879 	public Date getTimeStampCertificateExpiration() throws SignatureException {
880 		logger.debug("[PAdESLTVSignature.getTimeStampCertificateExpiration]::Entrada");
881 		
882 		PdfReader reader;
883 		try {
884 			reader = new PdfReader(this.pdfFile.getAbsolutePath());
885 		} catch (IOException e) {
886 			// El fichero ya pasó la validación
887 			logger.info("[PAdESLTVSignature.getTimeStampCertificateExpiration]::No se puede leer el contenido de este objeto", e);
888 			return null;
889 		}
890 		AcroFields af = reader.getAcroFields();
891 		ArrayList<String> tempNames = af.getSignatureNames();
892 		ArrayList<String> names = new ArrayList<String>();
893 		
894 		//-- Comprobar que el sello de tiempos para el documento es correcto
895 		for (Iterator iterator = tempNames.iterator(); iterator.hasNext();) {
896 			String name = (String) iterator.next();
897 			if (af.getSignatureDictionary(name).get(PdfName.SUBFILTER) != null &&
898 					af.getSignatureDictionary(name).get(PdfName.SUBFILTER).equals(new PdfName("ETSI.RFC3161"))) {
899 				
900 				TimeStamp ts;
901 				try {
902 					ts = new TimeStamp (af.getSignatureDictionary(name).getAsString(PdfName.CONTENTS).getOriginalBytes());
903 					logger.debug("[PAdESLTVSignature.getTimeStampCertificateExpiration]::Devolviendo: " + ts.getSignatureCertificate().getValidityPeriodEnd());
904 					return ts.getSignatureCertificate().getValidityPeriodEnd();
905 				} catch (MalformedTimeStampException e) {
906 					logger.info("[PAdESLTVSignature.getTimeStampCertificateExpiration]::El sello de tiempos del documento no es correcto", e);
907 					throw new SignatureException ("El sello de tiempos del documento no es correcto", e);
908 				}
909 
910 			} else {
911 				names.add(name);
912 			}
913 		}
914 		
915 		//-- No hay sello de tiempos del documento
916 		logger.info("[PAdESLTVSignature.getTimeStampCertificateExpiration]::No hay sello de tiempos del documento");
917 		throw new SignatureException ("No hay sello de tiempos del documento");
918 		
919 	}
920 
921 	/**
922 	 * Añade un sello de tiempos al documento PDF (document time-stamp).
923 	 * 
924 	 * @param urlTSA URL del servidor de sello de tiempos
925 	 * @param caList Lista de certificados de CA admitidos. Sirve para obtener las cadenas
926 	 * 	de certificación de los certificados implicados en la firma y/o sello de tiempos
927 	 * @param hashingAlgorithm Algoritmo del hash que se envía a la TSA
928 	 * @throws SignatureException Error leyendo o guardando objetos de la firma
929 	 * @throws RetrieveOCSPException No es posible obtener una respuesta OCSP para el 
930 	 * 	certificado del último sello de tiempos del documento
931 	 * @throws ResponseTimeStampException No es posible obtener una respuesta del servidor
932 	 * 	de sello de tiempos
933 	 * @throws CertificateCANotFoundException El certificado del último sello de tiempos del 
934 	 * 	documento no pertenece a ninguna de las Autoridades de Certificación de confianza
935 	 */
936 	public void addDocumentTimeStamp (URL urlTSA, CAList caList, String hashingAlgorithm) throws SignatureException, RetrieveOCSPException, ResponseTimeStampException, CertificateCANotFoundException {
937 		addDocumentTimeStamp(urlTSA, null, null, caList, hashingAlgorithm);
938 	}
939 	
940 	/**
941 	 * Añade un sello de tiempos al documento PDF (document time-stamp).
942 	 * 
943 	 * @param urlTSA URL del servidor de sello de tiempos
944 	 * @param caList Lista de certificados de CA admitidos. Sirve para obtener las cadenas
945 	 * 	de certificación de los certificados implicados en la firma y/o sello de tiempos
946 	 * @throws SignatureException Error leyendo o guardando objetos de la firma
947 	 * @throws RetrieveOCSPException No es posible obtener una respuesta OCSP para el 
948 	 * 	certificado del último sello de tiempos del documento
949 	 * @throws ResponseTimeStampException No es posible obtener una respuesta del servidor
950 	 * 	de sello de tiempos
951 	 * @throws CertificateCANotFoundException El certificado del último sello de tiempos del 
952 	 * 	documento no pertenece a ninguna de las Autoridades de Certificación de confianza
953 	 */
954 	public void addDocumentTimeStamp (URL urlTSA, CAList caList) throws SignatureException, RetrieveOCSPException, ResponseTimeStampException, CertificateCANotFoundException {
955 		addDocumentTimeStamp(urlTSA, null, null, caList);
956 	}
957 	
958 	/**
959 	 * Añade un sello de tiempos al documento PDF (document time-stamp), convirtiéndolo, si 
960 	 * no lo era ya, en un PAdES-A.
961 	 * 
962 	 * @param urlTSA URL del servidor de sello de tiempos
963 	 * @param userTSA Usuario para acceder al servidor de sello de tiempos. Nulo si no
964 	 * 	requiere autenticación.
965 	 * @param passwordTSA Contraseña para acceder al servidor de sello de tiempos. Nula si 
966 	 * no requiere autenticación.
967 	 * @param caList Lista de certificados de CA admitidos. Sirve para obtener las cadenas
968 	 * 	de certificación de los certificados implicados en la firma y/o sello de tiempos
969 	 * @throws SignatureException Error leyendo o guardando objetos de la firma
970 	 * @throws RetrieveOCSPException No es posible obtener una respuesta OCSP para el 
971 	 * 	certificado del último sello de tiempos del documento
972 	 * @throws ResponseTimeStampException No es posible obtener una respuesta del servidor
973 	 * 	de sello de tiempos
974 	 * @throws CertificateCANotFoundException El certificado del último sello de tiempos del 
975 	 * 	documento no pertenece a ninguna de las Autoridades de Certificación de confianza
976 	 */
977 	public void addDocumentTimeStamp (URL urlTSA, String userTSA, String passwordTSA, CAList caList) throws SignatureException, RetrieveOCSPException, ResponseTimeStampException, CertificateCANotFoundException {
978 		addDocumentTimeStamp(urlTSA, userTSA, passwordTSA, caList, HashingAlgorithm.getDefault());
979 	}
980 	
981 	/**
982 	 * Añade un sello de tiempos al documento PDF (document time-stamp), convirtiéndolo, si 
983 	 * no lo era ya, en un PAdES-A.
984 	 * 
985 	 * @param urlTSA URL del servidor de sello de tiempos
986 	 * @param userTSA Usuario para acceder al servidor de sello de tiempos. Nulo si no
987 	 * 	requiere autenticación.
988 	 * @param passwordTSA Contraseña para acceder al servidor de sello de tiempos. Nula si 
989 	 * no requiere autenticación.
990 	 * @param caList Lista de certificados de CA admitidos. Sirve para obtener las cadenas
991 	 * 	de certificación de los certificados implicados en la firma y/o sello de tiempos
992 	 * @param hashingAlgorithm Algoritmo del hash que se envía a la TSA
993 	 * @throws SignatureException Error leyendo o guardando objetos de la firma
994 	 * @throws RetrieveOCSPException No es posible obtener una respuesta OCSP para el 
995 	 * 	certificado del último sello de tiempos del documento
996 	 * @throws ResponseTimeStampException No es posible obtener una respuesta del servidor
997 	 * 	de sello de tiempos
998 	 * @throws CertificateCANotFoundException El certificado del último sello de tiempos del 
999 	 * 	documento no pertenece a ninguna de las Autoridades de Certificación de confianza
1000 	 */
1001 	public void addDocumentTimeStamp (URL urlTSA, String userTSA, String passwordTSA, CAList caList, String hashingAlgorithm) throws SignatureException, RetrieveOCSPException, ResponseTimeStampException, CertificateCANotFoundException {
1002 		logger.debug("[PAdESLTVSignature.addDocumentTimeStamp]::Entrada::"+ Arrays.asList(new Object[] { urlTSA, userTSA, passwordTSA, caList, hashingAlgorithm } ));
1003 		
1004 		FileOutputStream fos = null;
1005 		try {
1006 		
1007 			//-- Obtener el fichero temporal donde se dejará el resultado
1008 			File fileResult = getFileTemp();
1009 			
1010     		PdfReader reader;
1011     		try {
1012     			reader = new PdfReader(this.pdfFile.getAbsolutePath());
1013     		} catch (IOException e) {
1014     			// El fichero ya pasó la validación
1015     			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::No se puede leer el contenido de este objeto", e);
1016     			return;
1017     		}
1018     		
1019     		//-- Añadir DSS si hay último sello de tiempos
1020     		addDocumentTimeStampDSS(reader, caList, fileResult);
1021     
1022 			//-- Añadir sello de tiempos
1023 			File fileResult2 = getFileTemp();
1024 			addDocumentTimeStamp(fileResult, fileResult2, urlTSA, hashingAlgorithm, userTSA, passwordTSA);
1025 			fileResult.delete();
1026 			this.pdfFile.delete();
1027 			initialize(fileResult2);
1028 			
1029 		} catch (DocumentException e) {
1030 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::No se ha podido manejar alguna de las partes del fichero PDF", e);
1031 			throw new SignatureException ("No se ha podido manejar alguna de las partes del fichero PDF", e);
1032 		} catch (ResponseTimeStampException e) {
1033 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::El servidos de sello de tiempos devuelve un error en la respuesta", e);
1034 			throw e;
1035 		} catch (TimeStampServerConnectionException e) {
1036 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::No ha sido posible conectarse al servidor de sello de tiempos", e);
1037 			throw new ResponseTimeStampException ("No ha sido posible conectarse al servidor de sello de tiempos", e);
1038 		} catch (MalformedTimeStampException e) {
1039 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::El sello de tiempos obtenido no está bien formado", e);
1040 			throw new ResponseTimeStampException ("El sello de tiempos obtenido no está bien formado", e);
1041 		} catch (CertificateCANotFoundException e) {
1042 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::El certificado del último sello de tiempos de documento no pertenece a ninguna de las CAs de confianza", e);
1043 			throw e;
1044 		} catch (NormalizeCertificateException e) {
1045 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::El certificado del último sello de tiempos de documento no puede ser normalizado", e);
1046 			throw new SignatureException ("El certificado del último sello de tiempos de documento no puede ser normalizado", e);
1047 		} catch (RetrieveOCSPException e) {
1048 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::No se puede obtener la respuesta OCSP", e);
1049 			throw e;
1050 		} catch (InvalidCertificateException e) {
1051 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::El certificado del último sello de tiempos de documento no es válido", e);
1052 			throw new SignatureException ("El certificado del último sello de tiempos de documento no es válido", e);
1053 		} catch (IOException e) {
1054 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::Error de entrada/salida tratando el PDF", e);
1055 			throw new SignatureException ("Error de entrada/salida tratando el PDF", e);
1056 		} catch (HashingException e) {
1057 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::Error obteniendo el hash para sellar", e);
1058 			throw new SignatureException ("Error obteniendo el hash para sellar", e);
1059 		} catch (PDFDocumentException e) {
1060 			// No se va a dar, el PDF ya se abrió y era correcto
1061 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::El PDF tras el resellado no puede ser abierto", e);
1062 			throw new SignatureException ("El PDF tras el resellado no puede ser abierto", e);
1063 		} catch (SignatureNotFoundException e) {
1064 			// No se va a dar, el PDF está firmado
1065 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::El PDF tras el resellado no presenta firma", e);
1066 			throw new SignatureException ("El PDF tras el resellado no presenta firma", e);
1067 		} catch (NoSuchAlgorithmException e) {
1068 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::No existe el algoritmo de hash con el que se quiere realizar el sellado de tiempos", e);
1069 			throw new SignatureException ("No existe el algoritmo de hash con el que se quiere realizar el sellado de tiempos", e);
1070 		} 
1071 		
1072 	}
1073 	
1074 	/**
1075 	 * Obtiene una lista ordenada por fecha de los sellos de tiempo de documento
1076 	 * 
1077 	 * @param reader Lectura del PDF
1078 	 * @return Lista ordenada de sellos de tiempo del documento
1079 	 * @throws SignatureException No es posible parsear un sello de tiempos al
1080 	 * 	objeto TimeStamp del proveedor criptográfico
1081 	 */
1082 	public TimeStampDictionary[] getOrderedDocumentTimestamp () throws SignatureException {
1083 		PdfReader reader;
1084 		try {
1085 			reader = new PdfReader(this.pdfFile.getAbsolutePath());
1086 		} catch (IOException e) {
1087 			// El fichero ya pasó la validación
1088 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::No se puede leer el contenido de este objeto", e);
1089 			throw new SignatureException ("No se puede leer el contenido de este objeto");
1090 		}
1091 		
1092 		return PAdESLTVSignature.getOrderedDocumentTimestamp(reader);
1093 	}
1094 	
1095 	public static boolean isOnlyOCSPResponsesInDSS() {
1096 		return onlyOCSPResponsesInDSS;
1097 	}
1098 
1099 	public static void setOnlyOCSPResponsesInDSS(boolean onlyOCSPResponsesInDSS) {
1100 		PAdESLTVSignature.onlyOCSPResponsesInDSS = onlyOCSPResponsesInDSS;
1101 	}
1102 
1103 	//-- Métodos privados
1104 	
1105 	private void initialize (File pdfFile) throws PDFDocumentException, SignatureNotFoundException {
1106 		logger.debug("[PAdESLTVSignature.initialize]::Entrada::" + pdfFile);
1107 		
1108 		//-- Comprobar que el fichero es un PDF firmado
1109 		try {
1110 			PdfReader reader = new PdfReader(pdfFile.getAbsolutePath());
1111 			AcroFields af = reader.getAcroFields();
1112 			ArrayList names = af.getSignatureNames();
1113 			if (names == null || names.isEmpty()) {
1114 				logger.info("[PAdESLTVSignature.initialize]::El documento PDF no está firmado");
1115 				pdfFile.delete(); 
1116 				throw new SignatureNotFoundException ("El documento PDF no está firmado");
1117 			}
1118 			if (names.size() == 1) {
1119 				logger.info("[PAdESLTVSignature.initialize]::El documento PDF no es PAdES-LTV: sólo hay una firma y debería haber firma y sello de tiempos");
1120 				pdfFile.delete(); 
1121 				throw new SignatureNotFoundException ("El documento PDF no es PAdES-LTV: sólo hay una firma y debería haber firma y sello de tiempos");
1122 			}
1123 			
1124 			//-- Comprobar que existe el diccionario DSS
1125 			if (reader.getCatalog().get(new PdfName("DSS")) == null) {
1126 				logger.info("[PAdESLTVSignature.initialize]::El documento PDF no es PAdES-LTV: no contiene un diccionario Document Security Store (DSS)");
1127 				pdfFile.delete(); 
1128 				throw new SignatureNotFoundException ("El documento PDF no es PAdES-LTV: no contiene un diccionario Document Security Store (DSS)");
1129 			}
1130 			
1131 			//-- Comprobar que existe el sello de tiempos para el documento
1132 			boolean encontrado = false;
1133 			for (Iterator iterator = names.iterator(); iterator.hasNext();) {
1134 				String name = (String) iterator.next();
1135 				if (af.getSignatureDictionary(name) != null && af.getSignatureDictionary(name).get(PdfName.SUBFILTER) != null &&
1136 						af.getSignatureDictionary(name).get(PdfName.SUBFILTER).equals(new PdfName("ETSI.RFC3161"))) {
1137 					encontrado = true;
1138 					break;
1139 				}
1140 			}
1141 			if (!encontrado) {
1142 				logger.info("[PAdESLTVSignature.initialize]::El documento PDF no es PAdES-LTV: no contiene un sello de tiempos para todo el documento)");
1143 				pdfFile.delete(); 
1144 				throw new SignatureNotFoundException ("El documento PDF no es PAdES-LTV: no contiene un sello de tiempos para todo el documento)");
1145 			}
1146 			
1147 		} catch (IOException e) {
1148 			logger.info("[PAdESLTVSignature.initialize]::No se ha podido leer el fichero PDF", e);
1149 			pdfFile.delete(); 
1150 			throw new PDFDocumentException ("No se ha podido leer el fichero PDF", e);
1151 		} 
1152 		
1153 		//-- Todo correcto, se inicializa
1154 		this.pdfFile = pdfFile;
1155 
1156 	}
1157 
1158 	/*
1159 	 * Método que añade el sello de tiempos al documento
1160 	 */
1161 	private static void addDocumentTimeStamp (File sourcePdf, File destPdf, URL urlTimestamp, String hashingAlgorithm,
1162 			String userTSA, String passwordTSA) throws FileNotFoundException, IOException, DocumentException, MalformedTimeStampException, HashingException, ResponseTimeStampException, TimeStampServerConnectionException, NoSuchAlgorithmException {
1163 		
1164 		if (hashingAlgorithm == null) {
1165 			hashingAlgorithm = HashingAlgorithm.getDefault();
1166 		}
1167 		
1168 		FileInputStream fis = null;
1169 		PdfReader reader = null;
1170         FileOutputStream fos = null;
1171         try {
1172         	fis = new FileInputStream(sourcePdf);
1173         	reader = new PdfReader(fis);
1174     		AcroFields af = reader.getAcroFields();
1175     		ArrayList names = af.getSignatureNames();
1176 	        fos = new FileOutputStream (destPdf);
1177 	        PdfStamper stp;
1178 			if (names == null || names.isEmpty()) {
1179 				stp = PdfStamper.createSignature(reader, fos, '\0');
1180 			} else {
1181 				stp = PdfStamper.createSignature(reader, fos, '\0', null, true);
1182 			}
1183 	        PdfSignatureAppearance sap = stp.getSignatureAppearance();
1184 	
1185 	        PdfSignature timeStampSignature = new PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("ETSI.RFC3161"));
1186 	        timeStampSignature.put(PdfName.TYPE, new PdfName("DocTimeStamp"));
1187 	        sap.setCryptoDictionary(timeStampSignature);
1188 	
1189 	        int csize = 15000;
1190 	        HashMap<PdfName,Integer> exc = new HashMap<PdfName,Integer>();
1191 	        exc.put(PdfName.CONTENTS, new Integer(csize * 2 + 2));
1192 	        sap.preClose(exc);
1193 	
1194 	        TimeStampRequestParameters tsParameters = new TimeStampRequestParameters();
1195 	        tsParameters.setUser(userTSA);
1196 	        tsParameters.setPassword(passwordTSA);
1197 	        TimeStamp ts = TimeStamp.stampDocument(Util.readStream(sap.getRangeStream()), urlTimestamp, hashingAlgorithm, tsParameters);
1198 	        byte[] timestampToken = ts.toDER();
1199 	
1200 	        byte[] outc = new byte[csize];
1201 	        PdfDictionary dic = new PdfDictionary();
1202 	        System.arraycopy(timestampToken, 0, outc, 0, timestampToken.length);
1203 	        dic.put(PdfName.CONTENTS, new PdfString(outc).setHexWriting(true));
1204 	        sap.close(dic);
1205         } finally {
1206         	if (fis != null) { fis.close(); }
1207         	if (reader != null) { reader.close(); }
1208         	if (fos != null) { fos.close(); }
1209         }
1210 
1211 	}
1212 	
1213 	/*
1214 	 * Obtiene una respuesta OCSP para el certificado pasado como parámetro
1215 	 */
1216 	private static OCSPResponse getOcspBasicResponse(ValidateCertificate validateCertificate) throws RetrieveOCSPException, InvalidCertificateException, IOException {
1217 		OCSPClient[] ocspClient = validateCertificate.getOCSPClients();
1218 		OCSPResponse ocspResponse = null;
1219 		for (int i = 0; i < ocspClient.length; i++) {
1220 			try {
1221 				ocspResponse = ocspClient[i].getOCSPResponse(validateCertificate);
1222 				logger.debug ("[PAdESLTVSignature.sign]::Encontrada respuesta OCSP en " + ocspClient[i].getURL());
1223 			} catch (Exception e) {
1224 				//-- Pasamos al siguiente OCSPClient
1225 				logger.debug ("[PAdESLTVSignature.sign]::Excepción buscando respuesta OCSP en " + ocspClient[i].getURL(), e);
1226 			}
1227 		}
1228 		if (ocspResponse == null) {
1229 			logger.info("[PAdESLTVSignature.sign]::No se puede obtener una respuesta de un servidor OCSP para validar el certificado de firma");
1230 			throw new RetrieveOCSPException ("No se puede obtener una respuesta de un servidor OCSP para validar el certificado de firma");
1231 		}
1232 		if (ocspResponse.getStatus() != ValidationResult.RESULT_VALID) {
1233 			logger.info("[PAdESLTVSignature.sign]::Según la respuesta OCSP el certificado de firma no es válido::" + CertificateValidator.getString(ocspResponse.getStatus()));
1234 			throw new InvalidCertificateException ("Según la respuesta OCSP el certificado de firma no es válido: " + CertificateValidator.getString(ocspResponse.getStatus()), ocspResponse.getStatus());
1235 		}
1236 
1237 		return ocspResponse;
1238 	}
1239 
1240 	/*
1241 	 * Método que completa un fichero PDF firmado a PAdES-LTV. La firma del PDF firmado ha de ser
1242 	 * correcta y los certificados han de ser válidos en este momento.
1243 	 * 
1244 	 * @param signature PDF firmado
1245 	 * @param urlTimestamp URL del servidor de sello de tiempos
1246 	 * @param userTSA Usuario para acceder al servidor de sello de tiempos. Nulo si no
1247 	 * 	requiere autenticación.
1248 	 * @param passwordTSA Contraseña para acceder al servidor de sello de tiempos. Nula si 
1249 	 * no requiere autenticación.
1250 	 * @param caList Lista de certificados de CA, uno de ellos ha de ser el emisor del 
1251 	 * 	certificado con el que se realiza la firma
1252 	 * @return PAdES-LTV
1253 	 * @throws PDFDocumentException El documento no es un fichero PDF o es un PDF mal formado
1254 	 * @throws SignatureException Error completando la firma
1255 	 * @throws RetrieveOCSPException No es posible obtener una respuesta OCSP para
1256 	 * 	asociarla a la firma
1257 	 * @throws HashingException Excepción obteniendo el hash que será sellado por la TSA
1258 	 * @throws CertificateCANotFoundException La lista de certificado de CA no contiene el 
1259 	 * 	emisor del certificado de firma o existe pero tiene un formato no normalizable por 
1260 	 * 	el proveedor criptográfico de Arangi
1261 	 * @throws InvalidCertificateException El certificado con el que se firma está revocado
1262 	 * @throws NormalizeCertificateException 
1263 	 * @throws NormalizeCertificateException Alguno de los certificados de firma o de sus cadenas
1264 	 * 	de certificación no puede ser normalizado
1265 	 */
1266 	private static PAdESLTVSignature completeToPAdESLTV (PdfReader reader, URL urlTimestamp, 
1267 			String userTSA, String passwordTSA, String hashingAlgorithm, CAList caList, List<String> diccionariosRecienFirmados) throws SignatureException, RetrieveOCSPException, InvalidCertificateException, 
1268 			PDFDocumentException, CertificateCANotFoundException, HashingException, NormalizeCertificateException {
1269 		logger.debug ("[PAdESLTVSignature.completeToPAdESLTV]::Entrada");
1270 		
1271 		try {
1272 		
1273 			//-- Objeto con el diccionario DSS
1274     		PdfDocumentSecurityStore dss = new PdfDocumentSecurityStore();
1275     		
1276     		//-- Algoritmo de hashing. Si hay alguna firma con un algoritmo superior
1277     		//-- al que hay por defecto se hará el sello con dicho algoritmo
1278     		if (hashingAlgorithm == null) {
1279     			hashingAlgorithm = HashingAlgorithm.getDefault();
1280     		}
1281 			
1282 			//-- Leer el PDF y crear la firma. Dependiendo de si el PDF ya
1283 			//-- está firmado o no se crea el PdfStamper de una manera u otra
1284 			AcroFields af = reader.getAcroFields();
1285 			ArrayList<String> names = getRealSignatureNames(af);
1286 			for (Iterator<String> iterator = names.iterator(); iterator.hasNext();) {
1287 				String name = iterator.next();
1288 				
1289 				if (diccionariosRecienFirmados != null && !diccionariosRecienFirmados.contains(name)) {
1290 					continue;
1291 				}
1292             
1293 				//-- Validar que el PKCS#7 se corresponde con el documento
1294 				PdfPKCS7 pkcs7 = af.verifySignature(name, CRYPTOGRAPHIC_PROVIDER_NAME);
1295 				boolean valido;
1296 				try {
1297 					valido = pkcs7.verify();
1298 				} catch (java.security.SignatureException e) {
1299 					logger.info("[PAdESLTVSignature.completeToPAdESLTV]::Error en una de las firmas del PDF", e);
1300 					throw new SignatureException ("Error en una de las firmas del PDF", e);
1301 				}
1302 				if (!valido) {
1303 					logger.info("[PAdESLTVSignature.completeToPAdESLTV]::Una de las firmas del PDF no es correcta");
1304 					throw new SignatureException ("Una de las firmas del PDF no es correcta");
1305 				}
1306 				
1307 				if (HashingAlgorithm.isGreater(pkcs7.getHashAlgorithm(), hashingAlgorithm)) {
1308 					try {
1309 						hashingAlgorithm = HashingAlgorithm.getAlgorithmFromExternalName(pkcs7.getHashAlgorithm());
1310 					} catch (NoSuchAlgorithmException e) {
1311 						logger.info("No se puede hacer el sello para el algoritmo de hash: " + pkcs7.getHashAlgorithm()) ;
1312 					}
1313 				}
1314 				
1315 				//-- Si se ha definido un hueco para firmar pero no se ha rellenado llegamos hasta aquí pero
1316 				//-- no hay certificado de firma
1317 				Certificate signingCertificate = getSigningCertificate(pkcs7.getCertificates());
1318 				if (signingCertificate != null) {
1319 					//-- Obtener el certificado de la firma
1320 					ValidateCertificate certificate = new ValidateCertificate (signingCertificate.toDER(), caList);
1321 					
1322 					//-- Obtener el certificado del sello de tiempos
1323 					ValidateCertificate certificateTimestamp = null;
1324 					List<List<ValidateCertificate>> cadenaTimestamp = null;
1325 					if (pkcs7.getTimeStampToken() != null) {
1326 						TimeStamp ts = new TimeStamp (pkcs7.getTimeStampToken().getEncoded());
1327 						certificateTimestamp = new ValidateCertificate (ts.getSignatureCertificate().toX509Certificate(), caList);
1328 						cadenaTimestamp = certificateTimestamp.getCertificationChainSeveralIssuers();
1329 					}
1330 					
1331 					//-- Obtener el certificado del sello de archivo. Para ello llamar a la tsa con datos de prueba
1332 			        TimeStampRequestParameters tsParameters = new TimeStampRequestParameters();
1333 			        tsParameters.setUser(userTSA);
1334 			        tsParameters.setPassword(passwordTSA);
1335 			        TimeStamp ts = TimeStamp.stampDocument("a sellar".getBytes(), urlTimestamp, hashingAlgorithm, tsParameters);
1336 					ValidateCertificate certificateArchiveTimestamp = new ValidateCertificate (ts.getSignatureCertificate().toX509Certificate(), caList);
1337 					List<List<ValidateCertificate>> cadenaArchiveTimestamp = certificateArchiveTimestamp.getCertificationChainSeveralIssuers();
1338 					
1339 		            //-- Añadir información al objeto con el diccionario DSS
1340 					List<List<ValidateCertificate>> cadenaCertificate = certificate.getCertificationChainSeveralIssuers();
1341 					List<List<ValidateCertificate>> certificadosDSS = juntarListasDSS (certificate, certificateTimestamp, 
1342 							certificateArchiveTimestamp, cadenaCertificate, cadenaTimestamp, cadenaArchiveTimestamp);
1343 					
1344 					cargarDSS(certificadosDSS, dss, caList);
1345 				}
1346 				
1347 			}
1348 			
1349 			//-- Añadir DSS (estándar PAdES-LTV)------------------------------
1350 			FileOutputStream fos = null;
1351 			File fileResult = getFileTemp();
1352 			try {
1353 	            fos = new FileOutputStream (fileResult);
1354 	            PdfStamper stamper = new PdfStamper(reader, fos, '\0', true);
1355 				stamper.addDocumentSecurityStore(dss);
1356 				stamper.close();
1357 			} finally {
1358 				if (fos != null) {
1359 					fos.close();
1360 				}
1361 			}
1362 			
1363 			//-- Añadir sello de tiempos
1364 			File fileResult2 = getFileTemp();
1365 			addDocumentTimeStamp(fileResult, fileResult2, urlTimestamp, hashingAlgorithm, userTSA, passwordTSA);
1366 			fileResult.delete();
1367 			try {
1368 				return new PAdESLTVSignature (fileResult2);
1369 			} catch (SignatureNotFoundException e) {
1370 				//-- No se va a dar, el fichero se acaba de completar
1371 				return null;
1372 			} catch (PDFDocumentException e) {
1373 				//-- No se va a dar, el fichero se acaba de completar
1374 				return null;
1375 			}
1376 			
1377 		} catch (IOException e) {
1378 			logger.info("[PAdESLTVSignature.completeToPAdESLTV]::No se ha podido leer el fichero PDF o no se ha podido crear el fichero temporal con la firma", e);
1379 			throw new PDFDocumentException ("No se ha podido leer el fichero PDF o no se ha podido crear el fichero temporal con la firma", e);
1380 		} catch (CertificateCANotFoundException e) {
1381 			logger.info("[PAdESLTVSignature.completeToPAdESLTV]::La lista de certificado de CA no contiene el emisor del certificado de firma", e);
1382 			throw new CertificateCANotFoundException ("La lista de certificado de CA no contiene el emisor del certificado de firma", e);
1383 		} catch (MalformedTimeStampException e) {
1384 			logger.info("[PAdESLTVSignature.sign]::El sello de tiempos obtenido no está bien formado", e);
1385 			throw new SignatureException ("El sello de tiempos obtenido no está bien formado", e);
1386 		} catch (ResponseTimeStampException e) {
1387 			logger.info("[PAdESLTVSignature.sign]::El servidos de sello de tiempos devuelve un error en la respuesta", e);
1388 			throw new SignatureException ("El servidos de sello de tiempos devuelve un error en la respuesta", e);
1389 		} catch (DocumentException e) {
1390 			logger.info("[PAdESLTVSignature.completeToPAdESLTV]::No se ha podido manejar alguna de las partes del fichero PDF", e);
1391 			throw new PDFDocumentException ("No se ha podido manejar alguna de las partes del fichero PDF", e);
1392 		} catch (TimeStampServerConnectionException e) {
1393 			logger.info("[PAdESLTVSignature.sign]::No ha sido posible conectarse al servidor de sello de tiempos", e);
1394 			throw new SignatureException ("No ha sido posible conectarse al servidor de sello de tiempos", e);
1395 		} catch (NoSuchAlgorithmException e) {
1396 			logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::No existe el algoritmo de hash con el que se quiere realizar el sellado de tiempos", e);
1397 			throw new SignatureException ("No existe el algoritmo de hash con el que se quiere realizar el sellado de tiempos", e);
1398 		} 
1399 		
1400 	}
1401 	
1402 	/*
1403 	 * Junta los certificados y los arrays en un único array sin elementos repetidos
1404 	 */
1405     private static List<List<ValidateCertificate>> juntarListasDSS(ValidateCertificate certificate,
1406 			ValidateCertificate certificateTimestamp, ValidateCertificate certificateArchiveTimestamp, 
1407 			List<List<ValidateCertificate>> cadenaCertificate, List<List<ValidateCertificate>> cadenaTimestamp,
1408 			List<List<ValidateCertificate>> cadenaArchiveTimestamp) {
1409 		
1410     	HashSet<String> setHuellas = new HashSet<String>();
1411     	List<List<ValidateCertificate>> certificates = new ArrayList<List<ValidateCertificate>>();
1412     	
1413     	if (certificate != null) {
1414     		List<ValidateCertificate> lista = new ArrayList<ValidateCertificate>();
1415     		lista.add(certificate);
1416 	    	certificates.add(lista);
1417 	    	setHuellas.add(certificate.getFingerPrint());
1418     	}
1419     	
1420     	if (certificateTimestamp != null && !setHuellas.contains(certificateTimestamp.getFingerPrint())) {
1421     		List<ValidateCertificate> lista = new ArrayList<ValidateCertificate>();
1422     		lista.add(certificateTimestamp);
1423 	    	certificates.add(lista);
1424         	setHuellas.add(certificateTimestamp.getFingerPrint());
1425     	}
1426     	
1427     	if (certificateArchiveTimestamp != null && !setHuellas.contains(certificateArchiveTimestamp.getFingerPrint())) {
1428     		List<ValidateCertificate> lista = new ArrayList<ValidateCertificate>();
1429     		lista.add(certificateArchiveTimestamp);
1430 	    	certificates.add(lista);
1431         	setHuellas.add(certificateArchiveTimestamp.getFingerPrint());
1432     	}
1433     	
1434     	if (cadenaCertificate != null) {
1435 	    	for (List<ValidateCertificate> lista : cadenaCertificate) {
1436 	    		boolean encontrados = true;
1437 	    		for(ValidateCertificate cert : lista) {
1438 		        	if (!setHuellas.contains(cert.getFingerPrint())) {
1439 		            	encontrados = false;
1440 		            	setHuellas.add(cert.getFingerPrint());
1441 		        	}
1442 	    		}
1443 	    		if (!encontrados) {
1444 	    			certificates.add(lista);
1445 	    		}
1446 			}
1447     	}
1448     	if (cadenaTimestamp != null) {
1449 	    	for (List<ValidateCertificate> lista : cadenaTimestamp) {
1450 	    		boolean encontrados = true;
1451 	    		for(ValidateCertificate cert : lista) {
1452 		        	if (!setHuellas.contains(cert.getFingerPrint())) {
1453 		            	encontrados = false;
1454 		            	setHuellas.add(cert.getFingerPrint());
1455 		        	}
1456 	    		}
1457 	    		if (!encontrados) {
1458 	    			certificates.add(lista);
1459 	    		}
1460 			}
1461     	}
1462     	if (cadenaArchiveTimestamp != null) {
1463 	    	for (List<ValidateCertificate> lista : cadenaArchiveTimestamp) {
1464 	    		boolean encontrados = true;
1465 	    		for(ValidateCertificate cert : lista) {
1466 		        	if (!setHuellas.contains(cert.getFingerPrint())) {
1467 		            	encontrados = false;
1468 		            	setHuellas.add(cert.getFingerPrint());
1469 		        	}
1470 	    		}
1471 	    		if (!encontrados) {
1472 	    			certificates.add(lista);
1473 	    		}
1474 			}
1475     	}
1476     	
1477 		return certificates;
1478 	}
1479 
1480     /*
1481      * Pasa de lista de Integers a array de int
1482      */
1483 	private static int[] toArray(ArrayList<Integer> certIds) {
1484 		int[] result = new int [certIds.size()];
1485 		int i = 0;
1486 		for (Iterator<Integer> iterator = certIds.iterator(); iterator.hasNext();) {
1487 			result[i] = iterator.next();
1488 			i++;			
1489 		}
1490 		return result;
1491 	}
1492 
1493 	/*
1494 	 * Obtiene la lista de certificados del DSS
1495 	 */
1496 	private List<Certificate> getCertificadosDeDSS(PdfDocumentSecurityStore dss) throws NormalizeCertificateException {
1497 		ArrayList<Certificate> lCertificates = new ArrayList<Certificate>();
1498 		Set<Integer> setKeys = dss.getCertificates().keySet();
1499 		for (Integer key : setKeys) {
1500 			lCertificates.add(new Certificate(dss.getCertificates().get(key)));
1501 		}
1502 		return lCertificates;
1503 	}
1504 	
1505 	/**
1506 	 * Obtiene una lista ordenada por fecha de los sellos de tiempo de documento
1507 	 * 
1508 	 * @param reader Lectura del PDF
1509 	 * @return Lista ordenada de sellos de tiempo del documento
1510 	 * @throws SignatureException No es posible parsear un sello de tiempos al
1511 	 * 	objeto TimeStamp del proveedor criptográfico
1512 	 */
1513 	private static TimeStampDictionary[] getOrderedDocumentTimestamp (PdfReader reader) throws SignatureException {
1514 		logger.debug("[PAdESLTVSignature.getOrderedDocumentTimestamp]::Entrada");
1515 
1516 		AcroFields af = reader.getAcroFields();
1517 		ArrayList<String> tempNames = af.getSignatureNames();
1518 		ArrayList<TimeStampDictionary> lTimeStamps = new ArrayList<TimeStampDictionary>();
1519 		for (Iterator iterator = tempNames.iterator(); iterator.hasNext();) {
1520 			String name = (String) iterator.next();
1521 			if (af.getSignatureDictionary(name).get(PdfName.SUBFILTER) != null &&
1522 					af.getSignatureDictionary(name).get(PdfName.SUBFILTER).equals(new PdfName("ETSI.RFC3161"))) {
1523 				
1524 				try {
1525 					lTimeStamps.add(new PAdESLTVSignature.TimeStampDictionary (
1526 							name,
1527 							new TimeStamp (af.getSignatureDictionary(name).getAsString(PdfName.CONTENTS).getOriginalBytes()),
1528 							af.getSignatureDictionary(name)));
1529 				} catch (MalformedTimeStampException e) {
1530 					logger.info("[PAdESLTVSignature.isValid]::El sello de tiempos del documento no es correcto", e);
1531 					throw new SignatureException ("El sello de tiempos del documento no es correcto", e);
1532 				}
1533 
1534 			} 
1535 		}
1536 		
1537 		logger.debug("[PAdESLTVSignature.getOrderedDocumentTimestamp]::Ordenando " + lTimeStamps.size() + " sellos de tiempo de documento");
1538 		Collections.sort(lTimeStamps);
1539 		
1540 		logger.debug("[PAdESLTVSignature.getOrderedDocumentTimestamp]::Devolviendo " + lTimeStamps.size() + " sellos de tiempo de documento");
1541 		return lTimeStamps.toArray(new TimeStampDictionary[0]);
1542 		
1543 	}
1544 
1545 	/*
1546 	 * Carga un DSS con la información proveniente de los certificados pasados como parámetro
1547 	 */
1548 	private static void cargarDSS (List<List<ValidateCertificate>> certificadosDSS, PdfDocumentSecurityStore dss, CAList caList) throws NormalizeCertificateException, RetrieveOCSPException, InvalidCertificateException, IOException {
1549 		ArrayList<ValidateCertificate> selfSignedCertificates = new ArrayList<ValidateCertificate>(); 
1550 		ArrayList<ValidateCertificate> ocspCertificatesWithoutNoRevocationCheck = new ArrayList<ValidateCertificate>(); 
1551 		for (List<ValidateCertificate> lista : certificadosDSS) {
1552 			ValidateCertificate certificadoDSS = lista.get(0);
1553 			
1554 			if (certificadoDSS.isExpired()) {
1555 				throw new InvalidCertificateException ("El certificado está caducado", ValidationResult.RESULT_CERTIFICATE_NOT_ACTIVE);
1556 			}
1557 
1558 			if (!certificadoDSS.isSelfSigned()) {
1559 				dss.registerCertificate(certificadoDSS.toDER());
1560 				try {
1561 					logger.debug("Intentando cargar respuesta OCSP en DSS para el certificado " + certificadoDSS.getCommonName());
1562 					OCSPResponse ocspResponse = getOcspBasicResponse (certificadoDSS);
1563 					dss.registerOcspBasicResp(ocspResponse.getBasicOCSPResponse().getEncoded());
1564 					if (!ocspResponse.getSignatureCertificate().hasNoRevocationCheck()) {
1565 						ocspCertificatesWithoutNoRevocationCheck.add(new ValidateCertificate (ocspResponse.getSignatureCertificate().toX509Certificate(), caList));
1566 					}
1567 				} catch (Exception eOcsp) {
1568 					logger.debug("No es posible obtener una respuesta OCSP para el certificado " + certificadoDSS.getCommonName(), eOcsp);
1569 					if (PAdESLTVSignature.isOnlyOCSPResponsesInDSS() || (eOcsp instanceof InvalidCertificateException)) {
1570 						if (eOcsp instanceof RetrieveOCSPException) { throw (RetrieveOCSPException) eOcsp; }
1571 						if (eOcsp instanceof InvalidCertificateException) { throw (InvalidCertificateException) eOcsp; }
1572 						if (eOcsp instanceof IOException) { throw (IOException) eOcsp; }
1573 					}
1574 					logger.debug("Intentando cargar CRL en DSS para el certificado " + certificadoDSS.getCommonName());
1575 					try {
1576 						CRL crl = certificadoDSS.getCRL();
1577 						if (crl.isRevoked(certificadoDSS)) {
1578 							throw new InvalidCertificateException(ValidationResult.RESULT_CERTIFICATE_REVOKED);
1579 						}
1580 						dss.registerCrl(crl.toDER());
1581 					} catch (Exception e1) {
1582 						logger.debug("No es posible obtener una CRL para el certificado " + certificadoDSS.getCommonName(), e1);
1583 						if (eOcsp instanceof RetrieveOCSPException) { throw (RetrieveOCSPException) eOcsp; }
1584 						if (eOcsp instanceof InvalidCertificateException) { throw (InvalidCertificateException) eOcsp; }
1585 						if (eOcsp instanceof IOException) { throw (IOException) eOcsp; }
1586 					} 
1587 				} 
1588 				
1589 			} else {
1590 				selfSignedCertificates.add(certificadoDSS);
1591 			}
1592 		}
1593 		for (Iterator<ValidateCertificate> iterator2 = selfSignedCertificates.iterator(); iterator2.hasNext();) {
1594 			dss.registerCertificate(iterator2.next().toDER());
1595 		}
1596 		for (Iterator<ValidateCertificate> iteratorOcsp = ocspCertificatesWithoutNoRevocationCheck.iterator(); iteratorOcsp.hasNext();) {
1597 			ValidateCertificate ocspCertificate = iteratorOcsp.next();
1598 			dss.registerCertificate(ocspCertificate.toDER());
1599 			try {
1600 				logger.debug("Intentando cargar respuesta OCSP en DSS para el certificado " + ocspCertificate.getCommonName());
1601 				OCSPResponse ocspResponse = getOcspBasicResponse (ocspCertificate);
1602 				dss.registerOcspBasicResp(ocspResponse.getBasicOCSPResponse().getEncoded());
1603 			} catch (Exception eOcsp) {
1604 				logger.debug("No es posible obtener una respuesta OCSP para el certificado " + ocspCertificate.getCommonName(), eOcsp);
1605 				logger.debug("Intentando cargar CRL en DSS para el certificado " + ocspCertificate.getCommonName());
1606 				try {
1607 					dss.registerCrl(ocspCertificate.getCRL().toDER());
1608 				} catch (Exception e1) {
1609 					logger.debug("No es posible obtener una CRL para el certificado " + ocspCertificate.getCommonName(), e1);
1610 					if (eOcsp instanceof RetrieveOCSPException) { throw (RetrieveOCSPException) eOcsp; }
1611 					if (eOcsp instanceof InvalidCertificateException) { throw (InvalidCertificateException) eOcsp; }
1612 					if (eOcsp instanceof IOException) { throw (IOException) eOcsp; }
1613 				} 
1614 			} 
1615 		}
1616 
1617 	}
1618 	
1619 	/*
1620 	 * Método que realizará la validación, tanto si se valida con caList como con
1621 	 * servicio de validación
1622 	 */
1623 	private ValidationResult[] isValidCommon(CAList caList, List<CertificateValidationService> validationServices) throws HashingException, SignatureException, NormalizeCertificateException {
1624 		
1625 		logger.debug("[PAdESLTVSignature.isValidCommon]::Entrada::" + Arrays.asList(new Object[] { caList, validationServices }));
1626 		
1627 		PdfReader reader;
1628 		try {
1629 			reader = new PdfReader(this.pdfFile.getAbsolutePath());
1630 		} catch (IOException e) {
1631 			// El fichero ya pasó la validación
1632 			logger.info("[PAdESLTVSignature.isValidCommon]::No se puede leer el contenido de este objeto", e);
1633 			throw new SignatureException ("No se puede leer el contenido de este objeto");
1634 		}
1635 		AcroFields af = reader.getAcroFields();
1636 		
1637 		TimeStampDictionary[] sellosTiempoDocumento = PAdESLTVSignature.getOrderedDocumentTimestamp(reader);
1638 		logger.debug("[PAdESLTVSignature.isValidCommon]::Se han obtenido " + sellosTiempoDocumento.length + " sellos de tiempo de documento");
1639 		if (sellosTiempoDocumento.length == 0) {
1640 			logger.info("[PAdESLTVSignature.isValidCommon]::No hay ningún sello de tiempos de documento");
1641 			throw new SignatureException ("No hay ningún sello de tiempos de documento");
1642 		}
1643 		
1644 		//-- Validar el último sello a día de hoy
1645 		TimeStamp ts = sellosTiempoDocumento[sellosTiempoDocumento.length - 1].getTs();
1646 		try {
1647 			if (!ts.isValid()) {
1648 				logger.info("[PAdESLTVSignature.isValidCommon]::El último sello de tiempos del documento de fecha " + ts.getTime() + " no es correcto");
1649 				throw new SignatureException ("El último sello de tiempos del documento de fecha " + ts.getTime() + " no es correcto");
1650 			}
1651 		} catch (MalformedTimeStampException e) {
1652 			logger.info("[PAdESLTVSignature.isValidCommon]::El último sello de tiempos del documento está mal formado", e);
1653 			throw new SignatureException ("El último sello de tiempos del documento está mal formado", e);
1654 		}
1655 		logger.debug("[PAdESLTVSignature.isValidCommon]::El sello de tiempos de fecha " + ts.getTime() + " es correcto");
1656 		
1657 		//-- Validar el certificado del sello de tiempos a día de hoy
1658 		int validationResult;
1659 		if (caList != null) {
1660 			//-- Validar mediante CAList
1661 			logger.debug("[PAdESLTVSignature.isValidCommon]::Validar el certificado de la tsa con CAList");
1662 			ValidateCertificate tsCertificate;
1663 			try {
1664 				tsCertificate = new ValidateCertificate(ts.getSignatureCertificate().toX509Certificate(), caList);
1665 			} catch (CertificateCANotFoundException e) {
1666 				logger.info("[PAdESLTVSignature.isValidCommon]::El certificado del último sello de tiempos del documento no pertenece a una de las CA de confianza", e);
1667 				throw new SignatureException ("El certificado del último sello de tiempos del documento no pertenece a una de las CA de confianza", e);
1668 			} catch (MalformedTimeStampException e) {
1669 				logger.info("[PAdESLTVSignature.isValidCommon]::El último sello de tiempos del documento está mal formado", e);
1670 				throw new SignatureException ("El último sello de tiempos del documento está mal formado", e);
1671 			}
1672 			
1673 			validationResult = tsCertificate.validate();
1674 		} else {
1675 			//-- Validar mediante servicio de validación
1676 			logger.debug("[PAdESLTVSignature.isValidCommon]::Validar el certificado de la tsa con servicio de validación");
1677 			try {
1678 				validationResult = ts.getSignatureCertificate().validate(validationServices).getResult();
1679 			} catch (MalformedTimeStampException e) {
1680 				logger.info("[PAdESLTVSignature.isValidCommon]::El último sello de tiempos del documento está mal formado", e);
1681 				throw new SignatureException ("El último sello de tiempos del documento está mal formado", e);
1682 			}
1683 		}
1684 		
1685 		//-- Si el certificado del sello de tiempos no es válido
1686 		if (validationResult != ValidationResult.RESULT_VALID) {
1687 			//-- Devolver todas las firmas con el error de que el certificado del sello de tiempos del documento no es válido 
1688 			logger.info("[PAdESLTVSignature.isValidCommon]::El último certificado del sello de tiempos no es válido:" + CertificateValidator.getString(validationResult));
1689 			ArrayList<String> allSignatureNames = af.getSignatureNames();
1690 			ArrayList<ValidationResult> result = new ArrayList<ValidationResult>();
1691 			for (Iterator<String> iterator = allSignatureNames.iterator(); iterator.hasNext();) {
1692 				String name = iterator.next();
1693 				if (af.getSignatureDictionary(name).get(PdfName.SUBFILTER) == null ||
1694 						!af.getSignatureDictionary(name).get(PdfName.SUBFILTER).equals(new PdfName("ETSI.RFC3161"))) {
1695 					PdfPKCS7 pkcs7 = af.verifySignature(name, CRYPTOGRAPHIC_PROVIDER_NAME);
1696 					result.add(new ValidationResult(ValidationResult.RESULT_INVALID_TIMESTAMP, pkcs7.getSigningCertificate(), ts.getTime(), ts, null));
1697 				}
1698 			}
1699 			return result.toArray(new ValidationResult[0]);
1700 		}
1701 		
1702 		//-- Obtener el DSS (para que funcione Adobe)
1703 		PdfDocumentSecurityStore dss;
1704 		try {
1705 			dss = new PdfDocumentSecurityStore ((PdfDictionary)reader.getCatalog().getAsDict(new PdfName("DSS")));
1706 		} catch (IOException e) {
1707 			logger.info("[PAdESLTVSignature.isValidCommon]::No ha sido posible leer alguno de los objetos contenidos en el DSS", e);
1708 			throw new SignatureException ("No ha sido posible leer alguno de los objetos contenidos en el DSS", e);
1709 		}
1710 		
1711 		//-- Validar el resto del documento
1712 		try {
1713 			return isValid(ts, dss, caList, af.extractRevision(sellosTiempoDocumento[sellosTiempoDocumento.length - 1].getName()));
1714 		} catch (IOException e) {
1715 			logger.info("[PAdESLTVSignature.isValidCommon]::No es posible obtener la parte del PDF que sella el último sello de tiempos del documento", e);
1716 			throw new SignatureException ("No es posible obtener la parte del PDF que sella el último sello de tiempos del documento", e);
1717 		}
1718 	}
1719 	
1720 	/*
1721 	 * Valida un "trozo" del PDF que se halla envuelto por el sello de tiempos que se pasa
1722 	 * como parámetro. Si en el "trozo" hay otro sello de documento se tendrá que validar
1723 	 * y llamar recursivamente a esta función para que valide su "trozo" interno.
1724 	 */
1725 	private ValidationResult[] isValid (TimeStamp ts, PdfDocumentSecurityStore dssAdobe, CAList caList, InputStream is) throws HashingException, SignatureException, NormalizeCertificateException {
1726 		
1727 		PdfReader reader = null;
1728 		try {
1729 			try {
1730 				reader = new PdfReader(is);
1731 			} catch (IOException e) {
1732 				// El fichero ya pasó la validación
1733 				logger.info("[PAdESLTVSignature.isValid*]::No se puede leer el contenido de este objeto", e);
1734 				return null;
1735 			}
1736 			AcroFields af = reader.getAcroFields();
1737 	
1738 			//-- La fecha de comprobación es la del sello de tiempos anterior
1739 			Date fechaComprobacion = ts.getTime();
1740 			
1741 			//-- Obtener el DSS
1742 			PdfDocumentSecurityStore dss;
1743 			try {
1744 				PdfDictionary dssDictionary = (PdfDictionary)reader.getCatalog().getAsDict(new PdfName("DSS"));
1745 				if (dssDictionary != null) {
1746 					dss = new PdfDocumentSecurityStore (dssDictionary);
1747 				} else {
1748 					dss = dssAdobe; // para que funcione Adobe
1749 				}
1750 			} catch (IOException e) {
1751 				logger.info("[PAdESLTVSignature.isValid*]::No ha sido posible leer alguno de los objetos contenidos en el DSS", e);
1752 				throw new SignatureException ("No ha sido posible leer alguno de los objetos contenidos en el DSS", e);
1753 			}
1754 			
1755 			//-- Obtener todos los certificados que están en el dss (debe coincidir con certificadosDSS) y,
1756 			//-- si no se ha pasado un CAList, con ellos construir el CAList
1757 			List<Certificate> certificadosDSS;
1758 			try {
1759 				certificadosDSS = getCertificadosDeDSS (dss);
1760 				if (caList == null) {
1761 					caList = new CAList(certificadosDSS);
1762 				}
1763 			} catch (NormalizeCertificateException e) {
1764 				logger.info("[PAdESLTVSignature.isValid]::Alguno de los certificados del DSS no puede ser normalizado", e);
1765 				throw new SignatureException ("Alguno de los certificados del DSS no puede ser normalizado");
1766 			}
1767 			
1768 			//-- Validar las firmas
1769 			logger.debug("[PAdESLTVSignature.isValid*]::Se han acabado los sellos de tiempo de documento, validar las firmas");
1770 			ArrayList<String> allSignatureNames = af.getSignatureNames();
1771 			Collections.sort(allSignatureNames);
1772 			ArrayList<String> noTimestampNames = new ArrayList<String>();
1773 			for (Iterator iterator = allSignatureNames.iterator(); iterator.hasNext();) {
1774 				String name = (String) iterator.next();
1775 				if (af.getSignatureDictionary(name).get(PdfName.SUBFILTER) == null ||
1776 						!af.getSignatureDictionary(name).get(PdfName.SUBFILTER).equals(new PdfName("ETSI.RFC3161"))) {
1777 	
1778 					noTimestampNames.add(name);
1779 					
1780 				}
1781 			}
1782 	
1783 			logger.debug("[PAdESLTVSignature.isValid*]::Se van a validar " + noTimestampNames.size() + " firmas");
1784 			List<ValidationResult> results = new ArrayList<ValidationResult>(); 
1785 			for (int i = 0; i < noTimestampNames.size(); i++) {
1786 				String name = noTimestampNames.get(i);
1787 				
1788 				//-- Obtener el pkcs7
1789 				PdfPKCS7 pkcs7 = af.verifySignature(name, CRYPTOGRAPHIC_PROVIDER_NAME);
1790 				
1791 				//-- Validar que el PKCS#7 se corresponde con el documento
1792 				try {
1793 					if (!pkcs7.verify()) {
1794 						logger.info("[PAdESLTVSignature.isValid]::La firma no se corresponde con el documento");
1795 						results.add(new ValidationResult(ValidationResult.RESULT_SIGNATURE_NOT_MATCH_DATA, pkcs7.getSigningCertificate(), ts.getTime(), ts, null));
1796 						continue;
1797 					}
1798 				} catch (java.security.SignatureException e) {
1799 					logger.info("[PAdESLTVSignature.isValid]::Error en una de las firmas del PDF", e);
1800 					throw new SignatureException ("Error en una de las firmas del PDF", e);
1801 				}
1802 				
1803 				//-- Si se ha definido un hueco para firmar pero no se ha rellenado llegamos hasta aquí pero
1804 				//-- no hay certificado de firma
1805 				Certificate signingCertificate = getSigningCertificate(pkcs7.getCertificates());
1806 				if (signingCertificate != null) {
1807 					//-- Obtener el certificado de la firma y la cadena de certificación de éste
1808 					ValidateCertificate signatureCertificate;
1809 					try {
1810 						signatureCertificate = new ValidateCertificate (signingCertificate.toDER(), caList);
1811 					} catch (CertificateCANotFoundException e) {
1812 						logger.info("[PAdESLTVSignature.isValid]::Certificado" + i + " no pertenece a ninguna de las CAs de confianza");
1813 						results.add(new ValidationResult(ValidationResult.RESULT_CERTIFICATE_NOT_BELONGS_TRUSTED_CAS, pkcs7.getSigningCertificate(), ts.getTime(), ts, null));
1814 						continue;
1815 					}
1816 					List<List<ValidateCertificate>> chainCertificate = signatureCertificate.getCertificationChainSeveralIssuers();
1817 					
1818 					//-- Obtener el certificado del sello de tiempos y la cadena de certificación de éste: en las versiones
1819 					//-- antiguas no se tiene en cuenta el certificado del sello de tiempos
1820 					TimeStamp timestamp = null;
1821 					List<List<ValidateCertificate>> chainTimestamp = null;
1822 					ValidateCertificate timestampCertificate = null;
1823 					try {
1824 						if (pkcs7.getTimeStampToken() != null) {
1825 							timestamp = new TimeStamp(pkcs7.getTimeStampToken().getEncoded());
1826 						}
1827 					} catch (Exception e) {
1828 						logger.info("[PAdESLTVSignature.isValid]::No es posible leer el sello de tiempos interno de la firma", e);
1829 					}
1830 					
1831 					//-- La fecha de validación será la de este sello de tiempos
1832 					if (timestamp != null) {
1833 						ts = timestamp;
1834 					}
1835 					
1836 					if (timestamp != null && !olderVersionsAllowed) {
1837 						
1838 						//-- Validar el certificado del sello
1839 						try {
1840 							timestampCertificate = new ValidateCertificate (timestamp.getSignatureCertificate().toX509Certificate(), caList);
1841 						} catch (CertificateCANotFoundException e) {
1842 							logger.info("[PAdESLTVSignature.isValid]::Certificado de sello de tiempos " + i + " no pertenece a ninguna de las CAs de confianza");
1843 							results.add(new ValidationResult(ValidationResult.RESULT_CERTIFICATE_NOT_BELONGS_TRUSTED_CAS, pkcs7.getSigningCertificate(), ts.getTime(), ts, null));
1844 							continue;
1845 						} catch (MalformedTimeStampException e) {
1846 							logger.info("[PAdESLTVSignature.isValid]::No se ha podido obtener el certificado del sello de tiempos " + i, e);
1847 							results.add(new ValidationResult(ValidationResult.RESULT_CERTIFICATE_CHAIN_VALIDATION_INVALID, pkcs7.getSigningCertificate(), ts.getTime(), ts, null));
1848 							continue;
1849 						}
1850 						chainTimestamp = timestampCertificate.getCertificationChainSeveralIssuers();
1851 					}
1852 					
1853 					//-- Obtener la respuesta OCSP si está en el PKCS#7 (CAdES)
1854 					List<BasicOCSPResp> basicOcspResponses = null;
1855 					if (pkcs7.getOcspResponses() != null && !pkcs7.getOcspResponses().isEmpty()) {
1856 						try {
1857 							basicOcspResponses = new ArrayList<BasicOCSPResp>();
1858 							for(BasicOCSPResp bResp : pkcs7.getOcspResponses()) {
1859 								basicOcspResponses.add(new BasicOCSPResp(BasicOCSPResponse.getInstance(bResp.getEncoded())));
1860 							}
1861 						} catch (IOException e) {
1862 							logger.info("[PAdESLTVSignature.isValid]::No se ha podido parsear la respuesta OCSP en el CAdES de la firma " + i, e);
1863 						}
1864 					}
1865 					
1866 					//-- Obtener todos los certificados que deben estar en el dss
1867 					List<List<ValidateCertificate>> certificadosFirma = juntarListasDSS (signatureCertificate, timestampCertificate, null, chainCertificate, chainTimestamp, null);
1868 					
1869 					//-- Validar
1870 					results.add(validarCertificadosContraDSS(certificadosFirma, signatureCertificate, timestampCertificate, dss, 
1871 							certificadosDSS, fechaComprobacion, ts, basicOcspResponses, caList));
1872 				}
1873 			}
1874 			
1875 			//-- Obtener los sellos de tiempo
1876 			TimeStampDictionary[] sellosTiempoDocumento = PAdESLTVSignature.getOrderedDocumentTimestamp(reader);
1877 			logger.debug("[PAdESLTVSignature.isValid*]::Se han obtenido " + sellosTiempoDocumento.length + " sellos de tiempo de documento");
1878 			
1879 			//-- Si hay más de un sello de tiempos estamos en una zona donde hay que validar
1880 			//-- un sello de documento
1881 			if (sellosTiempoDocumento.length > 1) {
1882 				logger.debug("[PAdESLTVSignature.isValid*]::Validando otro sello de tiempos de documento");
1883 				//-- Hay que validar el sello y continuar con la siguiente parte del documento
1884 				TimeStamp siguienteTS = sellosTiempoDocumento[sellosTiempoDocumento.length - 2].getTs();
1885 				try {
1886 					if (!siguienteTS.isValid()) {
1887 						logger.info("[PAdESLTVSignature.isValid*]::El sello de tiempos del documento de fecha " + siguienteTS.getTime() + " no es válido");
1888 						throw new SignatureException ("El sello de tiempos del documento de fecha " + siguienteTS.getTime() + " no es válido");
1889 					}
1890 				} catch (MalformedTimeStampException e) {
1891 					logger.info("[PAdESLTVSignature.isValid*]::El sello de tiempos del documento no es correcto", e);
1892 					throw new SignatureException ("El sello de tiempos del documento no es correcto", e);
1893 				}
1894 				logger.debug("[PAdESLTVSignature.isValid*]::El sello de tiempos de documento de fecha " + siguienteTS.getTime() + " es válido");
1895 				
1896 				//-- Validar su certificado con el DSS
1897 				ValidateCertificate tsCertificate;
1898 				try {
1899 					tsCertificate = new ValidateCertificate(siguienteTS.getSignatureCertificate().toX509Certificate(), caList);
1900 				} catch (CertificateCANotFoundException e) {
1901 					logger.info("[PAdESLTVSignature.isValid]::El sello de tiempos del documento de fecha " + siguienteTS.getTime() + " no pertenece a una de las CA de confianza", e);
1902 					throw new SignatureException ("El sello de tiempos del documento de fecha " + siguienteTS.getTime() + " no pertenece a una de las CA de confianza", e);
1903 				} catch (MalformedTimeStampException e) {
1904 					logger.info("[PAdESLTVSignature.isValid]::El sello de tiempos del documento de fecha " + siguienteTS.getTime() + " está mal formado", e);
1905 					throw new SignatureException ("El sello de tiempos del documento de fecha " + siguienteTS.getTime() + " está mal formado", e);
1906 				}
1907 				List<List<ValidateCertificate>> chainCertificate = tsCertificate.getCertificationChainSeveralIssuers();
1908 				ValidationResult tsCertValidationResult = validarCertificadosContraDSS(chainCertificate, tsCertificate, null, dss, certificadosDSS, fechaComprobacion, siguienteTS, null, caList);
1909 				if (!tsCertValidationResult.isValid()) {
1910 					//-- Devolver todas las firmas con el error de que el certificado del sello de tiempos del documento no es válido 
1911 					logger.info("[PAdESLTVSignature.isValid]::El certificado del sello de tiempos del documento de fecha " + siguienteTS.getTime() + "  no es válido:" + CertificateValidator.getString(tsCertValidationResult.getResult()));
1912 					ArrayList<ValidationResult> result = new ArrayList<ValidationResult>();
1913 					for (Iterator<String> iterator = allSignatureNames.iterator(); iterator.hasNext();) {
1914 						String name = iterator.next();
1915 						if (af.getSignatureDictionary(name).get(PdfName.SUBFILTER) == null ||
1916 								!af.getSignatureDictionary(name).get(PdfName.SUBFILTER).equals(new PdfName("ETSI.RFC3161"))) {
1917 							PdfPKCS7 pkcs7 = af.verifySignature(name, CRYPTOGRAPHIC_PROVIDER_NAME);
1918 							result.add(new ValidationResult(ValidationResult.RESULT_INVALID_TIMESTAMP, pkcs7.getSigningCertificate(), siguienteTS.getTime(), siguienteTS, null));
1919 						}
1920 					}
1921 					return result.toArray(new ValidationResult[0]);
1922 				}
1923 				
1924 				//-- Validar el resto del documento
1925 				try {
1926 					return isValid(siguienteTS, dss, caList, af.extractRevision(sellosTiempoDocumento[sellosTiempoDocumento.length - 2].getName()));
1927 				} catch (IOException e) {
1928 					logger.info("[PAdESLTVSignature.isValid*]::No es posible obtener la parte del PDF que sella el sello de tiempos del documento de fecha " + siguienteTS.getTime(), e);
1929 					throw new SignatureException ("No es posible obtener la parte del PDF que sella el sello de tiempos del documento de fecha " + siguienteTS.getTime(), e);
1930 				}
1931 			}
1932 			
1933 			//-- Devolver resultado
1934 			return results.toArray(new ValidationResult[0]);
1935 
1936 		} finally {
1937 			if (reader != null) {
1938 				reader.close();
1939 			}
1940 		}
1941 	}
1942 	
1943 	/*
1944 	 * Valida una lista de certificados contra una DSS
1945 	 */
1946 	private ValidationResult validarCertificadosContraDSS (List<List<ValidateCertificate>> certificadosAValidar, ValidateCertificate certificadoFirma,
1947 			ValidateCertificate certificadoTS, PdfDocumentSecurityStore dss, List<Certificate> certificadosDSS, 
1948 			Date fechaComprobacion, TimeStamp ts, List<BasicOCSPResp> basicOcspResponses, CAList caList) throws SignatureException {
1949 		
1950 		int resultadoValidacion = ValidationResult.RESULT_VALID;
1951 		
1952 		//-- Para cada certificado comprobar que o es autofirmado o existe una respuesta OCSP válida
1953 		List<OCSPResponse> lOcspResponses = new ArrayList<OCSPResponse>();
1954 		int nivel = -1;
1955 		boolean todosValidados = true;
1956 		for (List<ValidateCertificate> lista : certificadosAValidar) {
1957 			nivel++;
1958 			boolean encontradaValidacionCertificado = false;
1959 			for (ValidateCertificate certificadoAValidar : lista) {
1960 			
1961 				//-- Comprobar que el certificado existe en el DSS (es opcional - sólo lo pondremos en los logs)
1962 				if (!certificadosDSS.contains(certificadoAValidar)) {
1963 					logger.info("[PAdESLTVSignature.isValid]::El certificado no se encuentra en el DSS::" + certificadoAValidar);
1964 	//				if(certificadoAValidar.equals(certificadoFirma) || (certificadoTS != null && certificadoAValidar.equals(certificadoTS))) {
1965 	//					resultadoValidacion = ValidationResult.RESULT_CERTIFICATE_CANNOT_BE_VALIDATED;
1966 	//				} else {
1967 	//					resultadoValidacion = ValidationResult.RESULT_CERTIFICATE_CHAIN_VALIDATION_INVALID;
1968 	//				}
1969 	//				break;
1970 				}
1971 				
1972 				//-- Si es autofirmado se continua
1973 				try {
1974 					if(certificadoAValidar.isSelfSigned()) {
1975 						encontradaValidacionCertificado = true;
1976 						break;
1977 					}
1978 				} catch (NormalizeCertificateException e) {
1979 					logger.info("[PAdESLTVSignature.isValid]::Uno de los certificados no puede ser normalizado:: " + certificadoAValidar.getCommonName(), e);
1980 					throw new SignatureException ("Uno de los certificados no puede ser normalizado", e);
1981 				}
1982 				
1983 				//-- Obtener y validar la respuesta OCSP
1984 				boolean encontradaRespuestaOCSP = false;
1985 				Set<Integer> setKeys = dss.getOcsps().keySet();
1986 				for (Integer key : setKeys) {
1987 					OCSPResponse ocspResponse;
1988 					try {
1989 						ocspResponse = new OCSPResponse (dss.getOcsps().get(key));
1990 					} catch (MalformedOCSPResponseException e) {
1991 						logger.info("[PAdESLTVSignature.isValid]::Una de las respuestas OCSP del DSS está mal formada", e);
1992 						break;
1993 					}
1994 					
1995 					if (ocspResponse.getSingleResponses()[0].match(certificadoAValidar)) {
1996 						logger.debug("[PAdESLTVSignature.isValid]::Encontrada respuesta OCSP para el certificado. Estado: " + ocspResponse.getSingleResponses()[0].getStatus());
1997 						encontradaRespuestaOCSP = true;
1998 						
1999 						//-- Comprobar que la respuesta OCSP sea válida
2000 						if (!ocspResponse.isSignatureValid()) {
2001 							if(certificadoAValidar.equals(certificadoFirma) || (certificadoTS != null && certificadoAValidar.equals(certificadoTS))) {
2002 								resultadoValidacion = ValidationResult.RESULT_INVALID_VALIDITY_ITEM;
2003 							} else {
2004 								resultadoValidacion = ValidationResult.RESULT_CERTIFICATE_CHAIN_VALIDATION_INVALID;
2005 							}
2006 							continue;
2007 						}
2008 						
2009 						//-- Comprobar el estado de la respuesta
2010 						if (ocspResponse.getSingleResponses()[0].getStatus() != ValidationResult.RESULT_VALID) {
2011 							if(certificadoAValidar.equals(certificadoFirma) || (certificadoTS != null && certificadoAValidar.equals(certificadoTS))) {
2012 								resultadoValidacion = ocspResponse.getSingleResponses()[0].getStatus();
2013 							} else {
2014 								resultadoValidacion = ValidationResult.RESULT_CERTIFICATE_CHAIN_VALIDATION_INVALID;
2015 							}
2016 							continue;
2017 						}
2018 						
2019 						//-- Comprobar que la fecha de la respuesta OCSP sea posterior a la fecha (del sello de tiempos del documento 
2020 						//-- o del sello de tiempos de la firma).
2021 						//-- Comprobar también que la respuesta no se realizó después de caducar el certificado
2022 						if ((ocspResponse.getSingleResponses()[0].getValidityPeriodEnd() != null && 
2023 								ocspResponse.getSingleResponses()[0].getValidityPeriodEnd().before(fechaComprobacion)) ||
2024 								ocspResponse.getSingleResponses()[0].getValidityPeriodBeginning().after(certificadoAValidar.getValidityPeriodEnd())) {
2025 							logger.debug("[PAdESLTVSignature.isValid]::La fecha de la respuesta OCSP (" + ocspResponse.getSingleResponses()[0].getValidityPeriodEnd() + 
2026 									") es anterior a la fecha de comprobación (" + fechaComprobacion + ")");
2027 							if(certificadoAValidar.equals(certificadoFirma) || (certificadoTS != null && certificadoAValidar.equals(certificadoTS))) {
2028 								resultadoValidacion = ValidationResult.RESULT_TIMESTAMP_AFTER_VALIDITY_ITEM;
2029 							} else {
2030 								resultadoValidacion = ValidationResult.RESULT_CERTIFICATE_CHAIN_VALIDATION_INVALID;
2031 							}
2032 							continue;
2033 						}
2034 						
2035 						//-- Respuesta OCSP OK
2036 						logger.debug("[PAdESLTVSignature.isValid]::La respuesta OCSP es correcta para el certificado de CN=" + certificadoFirma.getCommonName());
2037 						resultadoValidacion = ValidationResult.RESULT_VALID;
2038 						break;
2039 					}
2040 				}
2041 				
2042 				//-- Si se ha encontrado una respuesta válida pasamos al siguiente certificado
2043 				if (encontradaRespuestaOCSP && resultadoValidacion == ValidationResult.RESULT_VALID) {
2044 					encontradaValidacionCertificado = true;
2045 					break;
2046 				}
2047 				
2048 				//-- Si no se ha encontrado respuesta pero había una respuesta OCSP mirar si es correcta
2049 				try {
2050 					resultadoValidacion = validateFromCAdES(basicOcspResponses, certificadoAValidar, certificadoFirma, ts);
2051 				} catch (MalformedTimeStampException e) {
2052 					logger.info("[PAdESLTVSignature.isValid]::El sello de tiempo CAdES no se puede parsear", e);
2053 					resultadoValidacion = ValidationResult.RESULT_CERTIFICATE_CANNOT_BE_VALIDATED;
2054 				}
2055 				if (resultadoValidacion == ValidationResult.RESULT_VALID) {
2056 					encontradaValidacionCertificado = true;
2057 					break;
2058 				}
2059 				
2060 				//-- Si no se encuentra una respuesta OCSP o esta no es válida probar con CRL
2061 				logger.debug("[PAdESLTVSignature.isValid]::No se ha encontrado una respuesta OCSP para el certificado. Probar con CRLs");
2062 				
2063 				boolean encontradaCRL = false;
2064 				setKeys = dss.getCrls().keySet();
2065 				for (Integer key : setKeys) {
2066 					try {
2067 						CRL crl = new CRL (dss.getCrls().get(key));
2068 						
2069 						logger.debug("[PAdESLTVSignature.isValid]::Obtenida CRL, comprobar si sirve para validar el certificado");
2070 						if (crl.match(certificadoAValidar)) {
2071 							encontradaCRL = true;
2072 						
2073 							//-- Comprobar que la CRL sea válida
2074 							try {
2075 								crl.validate(caList);
2076 							} catch (Exception e) {
2077 								if(certificadoAValidar.equals(certificadoFirma) || (certificadoTS != null && certificadoAValidar.equals(certificadoTS))) {
2078 									resultadoValidacion = ValidationResult.RESULT_INVALID_VALIDITY_ITEM;
2079 								} else {
2080 									resultadoValidacion = ValidationResult.RESULT_CERTIFICATE_CHAIN_VALIDATION_INVALID;
2081 								}
2082 								break;
2083 							} 
2084 							
2085 							//-- Comprobar que el certificado no esté entre los revocados
2086 							logger.debug("[PAdESLTVSignature.isValid]::Obtenida CRL, comprobar si el certificado está entre los revocados");
2087 							if (crl.isRevoked(certificadoAValidar.getSerialNumberBigInteger())) {
2088 								if(certificadoAValidar.equals(certificadoFirma) || (certificadoTS != null && certificadoAValidar.equals(certificadoTS))) {
2089 									resultadoValidacion = ValidationResult.RESULT_CERTIFICATE_REVOKED;
2090 								} else {
2091 									resultadoValidacion = ValidationResult.RESULT_CERTIFICATE_CHAIN_VALIDATION_INVALID;
2092 								}
2093 								break;
2094 							}
2095 							
2096 							//-- Comprobar que la fecha de la CRL sea posterior a la fecha (del sello de tiempos del documento 
2097 							//-- o del sello de tiempos de la firma)
2098 							if (crl.getValidityPeriodEnd().before(fechaComprobacion)) {
2099 								logger.debug("[PAdESLTVSignature.isValid]::La fecha de la CRL (" + crl.getValidityPeriodEnd() + 
2100 										") es anterior a la fecha de comprobación (" + fechaComprobacion + ")");
2101 								if(certificadoAValidar.equals(certificadoFirma) || (certificadoTS != null && certificadoAValidar.equals(certificadoTS))) {
2102 									resultadoValidacion = ValidationResult.RESULT_TIMESTAMP_AFTER_VALIDITY_ITEM;
2103 								} else {
2104 									resultadoValidacion = ValidationResult.RESULT_CERTIFICATE_CHAIN_VALIDATION_INVALID;
2105 								}
2106 								break;
2107 							}
2108 	
2109 							//-- CRL OK
2110 							logger.debug("[PAdESLTVSignature.isValid]::La CRL es correcta para el certificado de CN=" + certificadoFirma.getCommonName());
2111 							resultadoValidacion = ValidationResult.RESULT_VALID;
2112 							break;
2113 						}
2114 						
2115 					} catch (CRLParsingException e) {
2116 						logger.info("[PAdESLTVSignature.isValid]::No se ha podido cargar una de las CRLs contenidas en el DSS", e);
2117 					}
2118 				}
2119 	
2120 				//-- Si se ha encontrado una CRL correcta pasamos al siguiente certificado
2121 				if (encontradaCRL && resultadoValidacion == ValidationResult.RESULT_VALID) {
2122 					encontradaValidacionCertificado = true;
2123 					break;
2124 				}
2125 				
2126 				//-- Probar a validar a día de hoy
2127 				resultadoValidacion = certificadoAValidar.validate();
2128 				if (resultadoValidacion == ValidationResult.RESULT_VALID) {
2129 					encontradaValidacionCertificado = true;
2130 					break;
2131 				}
2132 				
2133 			}
2134 			
2135 			//-- Si no se ha encontrado ni CRL ni respuesta OCSP para todos los certificados CA del nivel la validación es incorrecta
2136 			if (!encontradaValidacionCertificado) {
2137 				logger.debug("[PAdESLTVSignature.isValid]::No se ha encontrado una CRL para validar el certificado");
2138 				if(nivel == 0) {
2139 					resultadoValidacion = ValidationResult.RESULT_CERTIFICATE_CANNOT_BE_VALIDATED;
2140 				} else {
2141 					resultadoValidacion = ValidationResult.RESULT_CERTIFICATE_CHAIN_VALIDATION_INVALID;
2142 				}
2143 				todosValidados = false;
2144 				break;
2145 			}
2146 		}
2147 		
2148 		if (todosValidados) {
2149 			resultadoValidacion = ValidationResult.RESULT_VALID;
2150 		}
2151 		
2152 		return new ValidationResult(resultadoValidacion, certificadoFirma.toX509Certificate(), ts.getTime(), ts, lOcspResponses.toArray(new OCSPResponse[0]));
2153 		
2154 	}
2155 	
2156 	private static void addDocumentTimeStampDSS(PdfReader reader, CAList caList, File fileResult) throws SignatureException, NoSuchAlgorithmException, CertificateCANotFoundException, NormalizeCertificateException, RetrieveOCSPException, InvalidCertificateException, IOException, DocumentException {
2157 		TimeStampDictionary[] diccionariosSellosTiempoDocumento = getOrderedDocumentTimestamp(reader);
2158 		if (diccionariosSellosTiempoDocumento.length > 0) {
2159     		TimeStampDictionary diccionarioSellosTiempoDocumento = diccionariosSellosTiempoDocumento[diccionariosSellosTiempoDocumento.length - 1];
2160     		
2161 			//-- Obtener el último certificado del sello de tiempos
2162 			TimeStamp ts = diccionarioSellosTiempoDocumento.getTs();
2163 			
2164 			//-- Obtener la cadena del certificado de sello de tiempos
2165 			ValidateCertificate certificateTimestamp;
2166 			try {
2167 				certificateTimestamp = new ValidateCertificate (ts.getSignatureCertificate().toX509Certificate(), caList);
2168 			} catch (MalformedTimeStampException e) {
2169 				logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::El último sello de tiempos del documento no está bien formado", e);
2170 				throw new SignatureException ("El último sello de tiempos del documento no está bien formado", e);
2171 			} 
2172 			List<List<ValidateCertificate>> cadenaTimestamp = certificateTimestamp.getCertificationChainSeveralIssuers();
2173 			
2174 			//-- Añadir información de validación (DSS)
2175 			List<List<ValidateCertificate>> certificadosDSS = juntarListasDSS (null, certificateTimestamp, null, null, cadenaTimestamp, null);
2176 			PdfDocumentSecurityStore dss = new PdfDocumentSecurityStore();
2177 			cargarDSS(certificadosDSS, dss, caList);
2178 
2179 			//-- Añadir el diccionario DSS (estándar PAdES-LTV)
2180 			FileOutputStream fos = null;
2181 			try {
2182 	            fos = new FileOutputStream (fileResult);
2183 	            PdfStamper stamper = new PdfStamper(reader, fos, '\0', true);
2184 				stamper.addDocumentSecurityStore(dss);
2185 				stamper.close();
2186 			} finally {
2187 				if (fos != null) {
2188 					fos.close();
2189 				}
2190 			}
2191 		}
2192 	}
2193 	
2194 	//-- Classes
2195 	
2196 	static class MyPdfPKCS extends PdfSigGenericPKCS {
2197         /**
2198          * The constructor for the default provider.
2199          */
2200         public MyPdfPKCS() {
2201                 super(PdfName.ADOBE_PPKMS, (embedOcspInSignature) ? PdfName.ADBE_PKCS7_DETACHED : PdfName.ADBE_PKCS7_SHA1);
2202                 hashAlgorithm = HASH_ALGORITHM;
2203         }
2204 
2205         /**
2206          * The constructor for an explicit provider.
2207          *
2208          * @param provider the crypto provider
2209          */
2210         public MyPdfPKCS(String provider) {
2211                 this();
2212                 this.provider = provider;
2213         }
2214     }
2215 	
2216 	public static class TimeStampDictionary implements Comparable<TimeStampDictionary>{
2217 		String name;
2218 		TimeStamp ts;
2219 		PdfDictionary dictionary;
2220 		public TimeStampDictionary(String name, TimeStamp ts, PdfDictionary dictionary) {
2221 			super();
2222 			this.name = name;
2223 			this.ts = ts;
2224 			this.dictionary = dictionary;
2225 		}
2226 		public String getName() {
2227 			return name;
2228 		}
2229 		public void setName(String name) {
2230 			this.name = name;
2231 		}
2232 		public TimeStamp getTs() {
2233 			return ts;
2234 		}
2235 		public void setTs(TimeStamp ts) {
2236 			this.ts = ts;
2237 		}
2238 		public PdfDictionary getDictionary() {
2239 			return dictionary;
2240 		}
2241 		public void setDictionary(PdfDictionary dictionary) {
2242 			this.dictionary = dictionary;
2243 		}
2244 		public int compareTo(TimeStampDictionary o) {
2245 			return this.ts.getTime().compareTo(o.getTs().getTime());
2246 		}
2247 		
2248 	}
2249 
2250 }