1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216 public class PAdESLTVSignature extends BasePDFSignature {
217
218
219
220
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
232
233
234
235 public static boolean olderVersionsAllowed = false;
236
237
238
239
240 static Logger logger = Logger.getLogger(PAdESLTVSignature.class);
241
242
243
244
245
246
247
248
249
250
251
252 public PAdESLTVSignature (File pdfFile) throws PDFDocumentException, SignatureNotFoundException {
253
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
269
270
271
272
273
274
275
276 public PAdESLTVSignature (byte[] pdfContentBytes) throws PDFDocumentException, SignatureNotFoundException, IOException {
277
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
293
294
295
296
297
298
299
300 public PAdESLTVSignature (InputStream streamPDF) throws PDFDocumentException, SignatureNotFoundException, IOException {
301
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
313 initialize(fileTemp);
314 }
315
316
317
318
319
320
321
322
323
324
325 public PAdESLTVSignature (IDocument document) throws PDFDocumentException, SignatureNotFoundException, IOException {
326
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
344 initialize(fileTemp);
345 }
346
347
348
349
350 protected PAdESLTVSignature (PAdESLTVSignature signature) {
351 this.pdfFile = signature.pdfFile;
352 }
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
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
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
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
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
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
494 if (reason == null) {
495 reason = DEFAULT_SIGNATURE_REASON;
496 }
497
498
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
509 TSAClient tsc = new TSAClientBouncyCastle(urlTimestamp.toString(), userTSA, passwordTSA);
510
511
512 File fileResult1 = getFileTemp();
513 Util.saveFile(fileResult1, pdfDocument.getInputStream());
514
515
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
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
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
542 java.security.cert.Certificate[] chain = new java.security.cert.Certificate[] { x509Certificate, validateCertificate.getIssuerCertificate().toX509Certificate() };
543
544
545
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
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
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
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
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
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
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
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
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
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
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
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
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
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
817
818
819
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
831
832
833
834 public ValidationResult[] isValid(IDocument document, CAList caList)
835 throws HashingException, SignatureException,
836 NormalizeCertificateException {
837 return isValid (caList);
838 }
839
840
841
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
854
855
856
857 public ValidationResult[] isValid(IDocument document, List<CertificateValidationService> validationServices)
858 throws HashingException, SignatureException, NormalizeCertificateException {
859 return isValid(validationServices);
860 }
861
862
863
864
865
866
867 public String getSignatureType () {
868 return "PAdES-LTV";
869 }
870
871
872
873
874
875
876
877
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
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
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
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
923
924
925
926
927
928
929
930
931
932
933
934
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
942
943
944
945
946
947
948
949
950
951
952
953
954 public void addDocumentTimeStamp (URL urlTSA, CAList caList) throws SignatureException, RetrieveOCSPException, ResponseTimeStampException, CertificateCANotFoundException {
955 addDocumentTimeStamp(urlTSA, null, null, caList);
956 }
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
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
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
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
1008 File fileResult = getFileTemp();
1009
1010 PdfReader reader;
1011 try {
1012 reader = new PdfReader(this.pdfFile.getAbsolutePath());
1013 } catch (IOException e) {
1014
1015 logger.info("[PAdESLTVSignature.addDocumentTimeStamp]::No se puede leer el contenido de este objeto", e);
1016 return;
1017 }
1018
1019
1020 addDocumentTimeStampDSS(reader, caList, fileResult);
1021
1022
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
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
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
1076
1077
1078
1079
1080
1081
1082 public TimeStampDictionary[] getOrderedDocumentTimestamp () throws SignatureException {
1083 PdfReader reader;
1084 try {
1085 reader = new PdfReader(this.pdfFile.getAbsolutePath());
1086 } catch (IOException e) {
1087
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
1104
1105 private void initialize (File pdfFile) throws PDFDocumentException, SignatureNotFoundException {
1106 logger.debug("[PAdESLTVSignature.initialize]::Entrada::" + pdfFile);
1107
1108
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
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
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
1154 this.pdfFile = pdfFile;
1155
1156 }
1157
1158
1159
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
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
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
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
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
1274 PdfDocumentSecurityStore dss = new PdfDocumentSecurityStore();
1275
1276
1277
1278 if (hashingAlgorithm == null) {
1279 hashingAlgorithm = HashingAlgorithm.getDefault();
1280 }
1281
1282
1283
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
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
1316
1317 Certificate signingCertificate = getSigningCertificate(pkcs7.getCertificates());
1318 if (signingCertificate != null) {
1319
1320 ValidateCertificate certificate = new ValidateCertificate (signingCertificate.toDER(), caList);
1321
1322
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
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
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
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
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
1371 return null;
1372 } catch (PDFDocumentException e) {
1373
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
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
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
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
1507
1508
1509
1510
1511
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
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
1621
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
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
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
1658 int validationResult;
1659 if (caList != null) {
1660
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
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
1686 if (validationResult != ValidationResult.RESULT_VALID) {
1687
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
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
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
1722
1723
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
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
1739 Date fechaComprobacion = ts.getTime();
1740
1741
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;
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
1756
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
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
1789 PdfPKCS7 pkcs7 = af.verifySignature(name, CRYPTOGRAPHIC_PROVIDER_NAME);
1790
1791
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
1804
1805 Certificate signingCertificate = getSigningCertificate(pkcs7.getCertificates());
1806 if (signingCertificate != null) {
1807
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
1819
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
1832 if (timestamp != null) {
1833 ts = timestamp;
1834 }
1835
1836 if (timestamp != null && !olderVersionsAllowed) {
1837
1838
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
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
1867 List<List<ValidateCertificate>> certificadosFirma = juntarListasDSS (signatureCertificate, timestampCertificate, null, chainCertificate, chainTimestamp, null);
1868
1869
1870 results.add(validarCertificadosContraDSS(certificadosFirma, signatureCertificate, timestampCertificate, dss,
1871 certificadosDSS, fechaComprobacion, ts, basicOcspResponses, caList));
1872 }
1873 }
1874
1875
1876 TimeStampDictionary[] sellosTiempoDocumento = PAdESLTVSignature.getOrderedDocumentTimestamp(reader);
1877 logger.debug("[PAdESLTVSignature.isValid*]::Se han obtenido " + sellosTiempoDocumento.length + " sellos de tiempo de documento");
1878
1879
1880
1881 if (sellosTiempoDocumento.length > 1) {
1882 logger.debug("[PAdESLTVSignature.isValid*]::Validando otro sello de tiempos de documento");
1883
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
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
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
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
1934 return results.toArray(new ValidationResult[0]);
1935
1936 } finally {
1937 if (reader != null) {
1938 reader.close();
1939 }
1940 }
1941 }
1942
1943
1944
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
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
1962 if (!certificadosDSS.contains(certificadoAValidar)) {
1963 logger.info("[PAdESLTVSignature.isValid]::El certificado no se encuentra en el DSS::" + certificadoAValidar);
1964
1965
1966
1967
1968
1969
1970 }
1971
1972
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
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
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
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
2020
2021
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
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
2043 if (encontradaRespuestaOCSP && resultadoValidacion == ValidationResult.RESULT_VALID) {
2044 encontradaValidacionCertificado = true;
2045 break;
2046 }
2047
2048
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
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
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
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
2097
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
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
2121 if (encontradaCRL && resultadoValidacion == ValidationResult.RESULT_VALID) {
2122 encontradaValidacionCertificado = true;
2123 break;
2124 }
2125
2126
2127 resultadoValidacion = certificadoAValidar.validate();
2128 if (resultadoValidacion == ValidationResult.RESULT_VALID) {
2129 encontradaValidacionCertificado = true;
2130 break;
2131 }
2132
2133 }
2134
2135
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
2162 TimeStamp ts = diccionarioSellosTiempoDocumento.getTs();
2163
2164
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
2175 List<List<ValidateCertificate>> certificadosDSS = juntarListasDSS (null, certificateTimestamp, null, null, cadenaTimestamp, null);
2176 PdfDocumentSecurityStore dss = new PdfDocumentSecurityStore();
2177 cargarDSS(certificadosDSS, dss, caList);
2178
2179
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
2195
2196 static class MyPdfPKCS extends PdfSigGenericPKCS {
2197
2198
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
2207
2208
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 }