source: murachi/murachi/src/main/java/ve/gob/cenditel/murachi/MurachiRESTWS.java @ 6bb4976

Last change on this file since 6bb4976 was 6bb4976, checked in by antonioaraujob <aaraujo@…>, 9 years ago

Cambio en la ruta para almacenar archivos en el servidor: /tmp/murachi

  • Property mode set to 100644
File size: 93.2 KB
Line 
1package ve.gob.cenditel.murachi;
2
3import static java.util.Arrays.asList;
4
5import java.io.BufferedReader;
6import java.io.ByteArrayInputStream;
7import java.io.ByteArrayOutputStream;
8import java.io.File;
9import java.io.FileInputStream;
10import java.io.FileOutputStream;
11import java.io.IOException;
12import java.io.InputStream;
13import java.io.InputStreamReader;
14import java.io.ObjectInputStream;
15import java.io.ObjectOutputStream;
16import java.io.OutputStream;
17import java.net.URISyntaxException;
18import java.net.URL;
19import java.nio.file.Files;
20import java.nio.file.Paths;
21import java.security.GeneralSecurityException;
22import java.security.InvalidKeyException;
23import java.security.KeyStore;
24import java.security.KeyStoreException;
25import java.security.MessageDigest;
26import java.security.NoSuchAlgorithmException;
27import java.security.NoSuchProviderException;
28import java.security.Security;
29import java.security.cert.Certificate;
30import java.security.cert.CertificateException;
31import java.security.cert.CertificateExpiredException;
32import java.security.cert.CertificateFactory;
33import java.security.cert.CertificateNotYetValidException;
34import java.security.cert.X509Certificate;
35import java.util.ArrayList;
36import java.util.Calendar;
37import java.util.Date;
38import java.util.HashMap;
39import java.util.List;
40import java.util.Map.Entry;
41import java.util.UUID;
42import java.text.DateFormat;
43import java.text.NumberFormat;
44import java.text.SimpleDateFormat;
45
46import javax.ws.rs.Consumes;
47import javax.ws.rs.FormParam;
48import javax.ws.rs.GET;
49import javax.ws.rs.POST;
50import javax.ws.rs.Path;
51import javax.ws.rs.PathParam;
52import javax.ws.rs.Produces;
53import javax.ws.rs.core.Context;
54import javax.ws.rs.core.HttpHeaders;
55import javax.ws.rs.core.MediaType;
56import javax.ws.rs.core.Response;
57import javax.ws.rs.core.Response.ResponseBuilder;
58
59import org.bouncycastle.jce.provider.BouncyCastleProvider;
60import org.bouncycastle.tsp.TimeStampToken;
61import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
62import org.glassfish.jersey.media.multipart.FormDataParam;
63import org.json.JSONArray;
64import org.json.JSONObject;
65
66import com.itextpdf.text.DocumentException;
67import com.itextpdf.text.Rectangle;
68import com.itextpdf.text.exceptions.InvalidPdfException;
69import com.itextpdf.text.pdf.AcroFields;
70import com.itextpdf.text.pdf.PdfDate;
71import com.itextpdf.text.pdf.PdfDictionary;
72import com.itextpdf.text.pdf.PdfName;
73import com.itextpdf.text.pdf.PdfReader;
74import com.itextpdf.text.pdf.PdfSignature;
75import com.itextpdf.text.pdf.PdfSignatureAppearance;
76import com.itextpdf.text.pdf.PdfStamper;
77import com.itextpdf.text.pdf.PdfString;
78import com.itextpdf.text.pdf.security.CertificateInfo;
79import com.itextpdf.text.pdf.security.CertificateVerification;
80import com.itextpdf.text.pdf.security.DigestAlgorithms;
81import com.itextpdf.text.pdf.security.ExternalDigest;
82import com.itextpdf.text.pdf.security.PdfPKCS7;
83import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
84import com.itextpdf.text.pdf.security.SignaturePermissions;
85import com.itextpdf.text.pdf.security.VerificationException;
86
87import ee.sk.digidoc.CertValue;
88import ee.sk.digidoc.DigiDocException;
89import ee.sk.digidoc.SignedDoc;
90import ee.sk.digidoc.factory.DigiDocGenFactory;
91
92import javax.servlet.http.HttpServletRequest;
93import javax.servlet.http.HttpServletResponse;
94import javax.servlet.http.HttpSession;
95
96import org.digidoc4j.Configuration;
97import org.digidoc4j.Container;
98import org.digidoc4j.Container.DocumentType;
99import org.digidoc4j.DataFile;
100import org.digidoc4j.Signature;
101import org.digidoc4j.SignatureParameters;
102import org.digidoc4j.SignatureProductionPlace;
103import org.digidoc4j.SignedInfo;
104import org.digidoc4j.ValidationResult;
105import org.digidoc4j.Container.SignatureProfile;
106import org.digidoc4j.X509Cert;
107import org.digidoc4j.exceptions.DigiDoc4JException;
108import org.digidoc4j.exceptions.SignatureNotFoundException;
109import org.digidoc4j.impl.DDocContainer;
110import org.digidoc4j.impl.DDocSignature;
111import org.digidoc4j.impl.ValidationResultForDDoc;
112import org.digidoc4j.signers.PKCS12Signer;
113
114import ve.gob.cenditel.murachi.MurachiException;
115
116import org.apache.log4j.Logger;
117
118@Path("/archivos")
119public class MurachiRESTWS {
120       
121        final static Logger logger = Logger.getLogger(MurachiRESTWS.class);
122       
123        private static final String API_VERSION = "0.1.0";
124       
125        // debe colocarse la barra al final de la ruta
126        private static final String SERVER_UPLOAD_LOCATION_FOLDER = "/tmp/murachi/";
127       
128        private static final String SHA256_MESSAGE_DIGEST = "SHA256";
129       
130        private static final String RSA_DIGEST_ENCRYPTION_ALGORITHM = "RSA";
131       
132        // para reportes de advertencias de BDOC
133        private static boolean bdocWarnings = true;
134       
135        // para reportes en modo verbose de BDOC
136        private static boolean bdocVerboseMode = true;
137
138        /**
139         * Retorna la ruta absoluta de un archivo recurso
140         * @param resource cadena con el nombre del archivo
141         * @return ruta absoluta de un archivo recurso
142         */
143        String getAbsolutePathOfResource(String resource) {
144                ClassLoader classLoader = getClass().getClassLoader();
145                File file = new File(classLoader.getResource(resource).getFile());
146                logger.debug("archivo recurso solicitado: "+ resource +" path abosulto: " + file.getAbsolutePath());
147                return file.getAbsolutePath();         
148        }
149       
150       
151        /**
152         * Retorna la version del api del servicio
153         * @return version del api del servicio
154         * @throws URISyntaxException
155         *
156         * @api {get} /Murachi/0.1/archivos/version Retorna la versión del API
157         * @apiName GetVersion
158         * @apiGroup General
159         * @apiVersion 0.1.0
160         *
161         * @apiExample Example usage:
162     * curl -i http://murachi.cenditel.gob.ve/Murachi/0.1/archivos/version
163         *
164         * @apiSuccess {String} murachiVersion Versión del API
165         */
166        @Path("/version")
167        @GET
168        @Produces(MediaType.APPLICATION_JSON)
169        public Response returnVersion() {
170                logger.info("/version: Murachi Version: " + API_VERSION);       
171                JSONObject jsonObject = new JSONObject();
172                jsonObject.put("murachiVersion", API_VERSION);
173                String result = jsonObject.toString();
174                return Response.status(200).entity(result).build();
175        }
176               
177        /**
178         * Carga un archivo pasado a través de un formulario y retorna
179         * un json con el id del archivo en el servidor para futuras consultas
180         * de estado de firmas
181         *
182         * @param uploadedInputStream stream para obtener el archivo
183         * @param fileDetails datos del archivo
184         * @return
185         * @throws MurachiException
186         *
187         * @api {post} /Murachi/0.1/archivos/ Carga un archivo
188         * @apiName Archivos
189         * @apiGroup Archivos
190         * @apiVersion 0.1.0
191         * @apiDescription Carga un archivo a través de un formulario y retorna un json con el id del archivo en el servidor
192         *
193         *
194         * @apiExample Example usage:
195     * 
196     *  var formData = new FormData();
197     *  formData.append("upload", $("#file-sign")[0].files[0]);           
198     *  $.ajax({
199     *           url: "https://murachi.cenditel.gob.ve/Murachi/0.1/archivos",
200     *           type: "post",
201     *           dataType: "json",
202     *           data: formData,
203     *           cache: false,
204     *           contentType: false,
205         *           processData: false,
206     *           success: function(response) {
207     *                  //identificador del archivo en el servidor
208         *                  var fileId = response.fileId.toString();
209         *                  alert("fileId: "+ fileId);
210         *           },
211         *           error: function(response){
212         *                  alert("error: " + response.error.toString());
213         *           }
214     *  });
215         *
216         * @apiErrorExample {json} Error-Response:
217         *     HTTP/1.1 400 Bad Request
218         *     {
219         *       "error": "datos recibidos del formulario son nulos"
220         *     }
221         *     
222         *     HTTP/1.1 500
223         *     {
224         *       "error": "IOException"
225         *     }
226         *
227         * @apiSuccess {String} fileId Identificador único del archivo cargado en el servidor.
228         *
229         */     
230        @POST
231        @Path("/")
232        @Consumes(MediaType.MULTIPART_FORM_DATA)
233        @Produces(MediaType.APPLICATION_JSON)
234        public Response uploadFile(
235                        @FormDataParam("upload") InputStream uploadedInputStream,
236                        @FormDataParam("upload") FormDataContentDisposition fileDetails) throws MurachiException {
237               
238                logger.info("/: uploadFile");
239               
240                if (uploadedInputStream == null) {
241                        System.out.println("uploadedInputStream == null");
242                        logger.error("uploadedInputStream != null. datos recibidos del formulario son nulos.");
243                        //throw new MurachiException("uploadedInputStream != null. datos recibidos del formulario son nulos.");
244                       
245                        return Response.status(400).entity("{\"error\": \"datos recibidos del formulario son nulos\"}").type(MediaType.APPLICATION_JSON).build();
246                }
247               
248                if (fileDetails == null) {
249                        System.out.println("fileDetails == null");
250                        logger.error("fileDetails == null. datos recibidos del formulario son nulos.");
251                        //throw new MurachiException("fileDetails == null. datos recibidos del formulario son nulos.");
252                        return Response.status(400).entity("{\"error\": \"datos recibidos del formulario son nulos\"}").type(MediaType.APPLICATION_JSON).build();
253                }
254                               
255                String fileId = UUID.randomUUID().toString();
256                System.out.println(fileId);
257               
258                saveToDisk(uploadedInputStream, fileDetails, fileId);
259               
260                try {
261                        uploadedInputStream.close();
262                } catch (IOException e) {
263                        logger.error("Ocurrio una excepcion: ", e);
264                        e.printStackTrace();
265                        //throw new MurachiException(e.getMessage());
266                        return Response.status(500).entity("{\"error\":" + e.getMessage()).build();
267                       
268                }
269               
270                JSONObject jsonObject = new JSONObject();
271                jsonObject.put("fileId", fileId);
272               
273                System.out.println("File saved to server location : " + SERVER_UPLOAD_LOCATION_FOLDER + fileId);
274                String result = jsonObject.toString();
275                logger.info("/: " + result);
276               
277                return Response.status(200).entity(result).build();
278        }
279
280        /**
281         * Descarga un archivo existente en el servidor
282         * @param fileName nombre (identificador) del archivo que se desea descargar
283         * @return archivo existente en el servidor y pasado como argumento
284         *
285         * @api {get} /Murachi/0.1/archivos/descargas/id Descarga un archivo existente en el servidor
286         * @apiName Descargas
287         * @apiGroup Archivos
288         * @apiVersion 0.1.0
289         *
290         * @apiParam {String} id Identificador del archivo que se desea descargar.
291         *
292         * @apiExample Example usage:
293     * curl -i http://murachi.cenditel.gob.ve/Murachi/0.1/archivos/descargas/xxx
294         *       
295         *
296         * @apiErrorExample {json} Error-Response:
297         *     HTTP/1.1 404 Not Found
298         *     {
299         *       "fileExist": false
300         *     }
301         */
302        @GET
303        @Path("/descargas/{filename}")
304        @Produces(MediaType.APPLICATION_OCTET_STREAM)
305        public Response downloadFilebyPath(@PathParam("filename")  String fileName) {
306                logger.info("/descargas/{"+fileName+"}");
307                return downloadFileFromServer(fileName);
308        }
309       
310        /**
311         * Descarga un archivo pasado como argumento del servidor
312         * @param fileName nombre o identificador del archivo que se desea descargar
313         * @return archivo pasado como argumento del servidor
314         */
315        private Response downloadFileFromServer(String fileName) {   
316            String fileLocation = SERVER_UPLOAD_LOCATION_FOLDER + fileName;
317            Response response = null;
318            NumberFormat myFormat = NumberFormat.getInstance();
319              myFormat.setGroupingUsed(true);
320             
321            // Retrieve the file
322            File file = new File(SERVER_UPLOAD_LOCATION_FOLDER + fileName);
323            if (file.exists()) {
324                ResponseBuilder builder = Response.ok(file);
325                builder.header("Content-Disposition", "attachment; filename=" + file.getName());
326                response = builder.build();
327               
328                long file_size = file.length();
329                logger.info(String.format("Inside downloadFile==> fileName: %s, fileSize: %s bytes",
330                                fileName, myFormat.format(file_size)));
331            } else {
332                logger.error(String.format("Inside downloadFile==> FILE NOT FOUND: fileName: %s",
333                                fileName));
334               
335                //response = Response.status(404).entity("{\"fileExist\": " + /*fileLocation*/ fileName + "}").
336                //              type("text/plain").build();
337               
338                response = Response.status(404).entity("{\"fileExist\": false}").
339                                type("text/plain").build();
340            }
341             
342            return response;
343          }
344       
345       
346        /**
347         * Carga un archivo pasado a través de un formulario y retorna
348         * un json con la informacion de la(s) firma(s) del archivo
349         * en caso de que este firmado
350         *
351         * @param uploadedInputStream stream para obtener el archivo
352         * @param fileDetails datos del archivo
353         * @return
354         * @throws MurachiException
355         *
356         * @api {post} /Murachi/0.1/archivos/firmados Carga un archivo y verifica
357         * @apiName Firmados
358         * @apiGroup Archivos
359         * @apiVersion 0.1.0
360         * @apiDescription Carga un archivo a través de un formulario y retorna un json con la información de la firma.
361         *
362         * @apiSuccess {Boolean} fileExist El archivo se cargó exitosamente en el servidor.
363         * @apiSuccess {String} error Extension not supported. En caso de que el archivo sea diferente de PDF y BDOC.
364         *
365         * @apiSuccess {Number} numberOfSignatures Número de firmas existentes en el archivo.
366         * @apiSuccess {Object[]} signatures Lista de firmas.
367         * @apiSuccess {String}   signatures.signatureType Tipo de firma de archivo PDF: approval
368         * @apiSuccess {String}   signatures.signedOn Fecha en que se realiza la firma.
369         * @apiSuccess {Boolean}   signatures.integrityCheck Chequea la integridad de la firma.
370         * @apiSuccess {String}   signatures.timeStamp Estampilla de tiempo
371         * @apiSuccess {String}   signatures.reason Razón de la firma.
372         * @apiSuccess {String}   signatures.location Ubicación donde se realiza la firma.
373         * @apiSuccess {String}   signatures.alternativeNameOfTheSigner Nombre alternativo del firmante.
374         * @apiSuccess {String}   signatures.signerCertificateValidFrom Fecha de inicio de validez del certificado.
375         * @apiSuccess {Boolean}   signatures.signerCertificateStillValid El certificado todavía está válido.
376         * @apiSuccess {Boolean}   signatures.signerCertificateHasExpired El certificado expiró.
377         * @apiSuccess {Boolean}   signatures.signatureCoversWholeDocument La firma abarca todo el documento PDF.
378         * @apiSuccess {String}   signatures.filterSubtype Tipo de subfiltro: /adbe.pkcs7.sha1, /adbe.pkcs7.detached.
379         * @apiSuccess {String}   signatures.signerCertificateSubject Sujeto firmante.
380         * @apiSuccess {Boolean}   signatures.signerCertificateValidAtTimeOfSigning El certificado es válido en el momento de la firma.
381         * @apiSuccess {String}   signatures.encryptionAlgorithm Algoritmo de cifrado.
382         * @apiSuccess {String}   signatures.timeStampService Servicio de estampillado de tiempo.
383         * @apiSuccess {String}   signatures.digestAlgorithm Algoritmo hash (reseña).
384         * @apiSuccess {Boolean}   signatures.certificatesVerifiedAgainstTheKeyStore Certificado verificado contra el repositorio de certificados confiables.
385         * @apiSuccess {Number}   signatures.documentRevision Número de revisión del documento PDF.
386         * @apiSuccess {String}   signatures.nameOfTheSigner Nombre del firmante.
387         * @apiSuccess {Number}   signatures.totalDocumentRevisions Número total de revisiones del documento PDF.
388         * @apiSuccess {String}   signatures.contactInfo Información de contacto del firmante.
389         * @apiSuccess {Boolean}   signatures.timeStampVerified Estampilla de tiempo verificada.
390         * @apiSuccess {String}   signatures.signerCertificateIssuer Emisor del certificado firmante.
391         * @apiSuccess {String}   signatures.signerCertificateValidTo Fecha de fin de validez del certificado.
392         *
393         * @apiExample Example usage:
394         *
395         *  var formData = new FormData();
396     *  formData.append("upload", $("#file-sign")[0].files[0]);           
397     *  $.ajax({
398     *           url: "https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/firmados",
399     *           type: "post",
400     *           dataType: "json",
401     *           data: formData,
402     *           cache: false,
403     *           contentType: false,
404         *           processData: false,
405     *           success: function(response) {
406         *                  var json = JSON.stringify(response);
407         *                  alert(json);
408         *           },
409         *           error: function(response){
410         *                  alert("error: " + response.error.toString());
411         *           }
412     *  });
413         *
414         *
415         *
416         * @apiErrorExample {json} Error-Response:
417         *     HTTP/1.1 400 Bad Request
418         *     {
419         *       "error": "datos recibidos del formulario son nulos"
420         *     }
421         *     
422         *     
423         *     HTTP/1.1 500
424         *     {
425         *       "error": "IOException"
426         *     }
427         *     
428         */
429        @POST
430        @Path("/firmados")
431        @Consumes(MediaType.MULTIPART_FORM_DATA)
432        @Produces(MediaType.APPLICATION_JSON)
433        public Response uploadFileAndVerify(
434                        @FormDataParam("upload") InputStream uploadedInputStream,
435                        @FormDataParam("upload") FormDataContentDisposition fileDetails) throws MurachiException {
436               
437                logger.info("/firmados: uploadFileAndVerify");
438               
439                if (uploadedInputStream == null) {
440                        System.out.println("uploadedInputStream == null");
441                        logger.error("uploadedInputStream != null. datos recibidos del formulario son nulos.");
442                        //throw new MurachiException("uploadedInputStream != null. datos recibidos del formulario son nulos.");
443                        return Response.status(400).entity("{\"error\": \"datos recibidos del formulario son nulos\"}").type(MediaType.APPLICATION_JSON).build();
444                }
445               
446                if (fileDetails == null) {
447                        System.out.println("fileDetails == null");
448                        logger.error("fileDetails == null. datos recibidos del formulario son nulos.");
449                        //throw new MurachiException("fileDetails == null. datos recibidos del formulario son nulos.");
450                        return Response.status(400).entity("{\"error\": \"datos recibidos del formulario son nulos\"}").type(MediaType.APPLICATION_JSON).build();
451                       
452                }
453                               
454                String fileId = UUID.randomUUID().toString();
455                System.out.println(fileId);
456               
457                saveToDisk(uploadedInputStream, fileDetails, fileId);
458               
459                try {
460                        uploadedInputStream.close();
461                } catch (IOException e) {
462                        logger.error("Ocurrio una excepcion: ", e);
463                        e.printStackTrace();
464                        //throw new MurachiException(e.getMessage());
465                        return Response.status(500).entity("{\"error\":" + e.getMessage()).build();
466                }
467               
468                System.out.println("File saved to server location : " + SERVER_UPLOAD_LOCATION_FOLDER + fileId);
469               
470                JSONObject jsonObject = new JSONObject();
471                                       
472                jsonObject = verifyALocalFile(fileId);
473                logger.info("/firmados: " + jsonObject.toString());
474               
475                return Response.status(200).entity(jsonObject.toString()).build();
476        }
477       
478        /**
479         * Escribe un archivo en el sistema de archivos
480         * @param uploadedInputStream
481         * @param fileDetails
482         * @param fileId identificador unico del archivo de acuerdo a UUIDs
483         * @throws MurachiException
484         */
485        private void saveToDisk(InputStream uploadedInputStream, FormDataContentDisposition fileDetails, String fileId) throws MurachiException {
486               
487                String uploadedFileLocation = SERVER_UPLOAD_LOCATION_FOLDER + /*fileDetails.getFileName()*/ fileId;
488               
489                System.out.println("uploadedFileLocation: " + uploadedFileLocation);
490                logger.debug("uploadedFileLocation: " + uploadedFileLocation);
491               
492                try {
493                        OutputStream out = new FileOutputStream(new File(uploadedFileLocation));
494                        int read = 0;
495                        byte[] bytes = new byte[1024];
496                       
497                        out = new FileOutputStream(new File(uploadedFileLocation));
498                        while ((read = uploadedInputStream.read(bytes)) != -1) {
499                                out.write(bytes, 0, read);
500                               
501                        }
502                        out.flush();
503                        out.close();
504                }
505                catch(IOException e) {
506                        logger.error("saveToDisk: ocurrio una excepcion", e);
507                        e.printStackTrace();
508                        throw new MurachiException(e.getMessage());
509                }
510        }
511       
512       
513        /**
514         * Verifica si un archivo posee firmas electronicas y retorna informacion
515         * de las mismas en un json
516         * @param idFile identificador del archivo a verificar
517         * @return JSON con informacion de las firmas
518         * @throws MurachiException
519         */
520        @GET
521        @Path("/{idFile}")
522        @Produces("application/json")
523        public Response verifyAFile(@PathParam("idFile") String idFile) throws MurachiException {
524
525                System.out.println("/{idFile}");
526                logger.info("/{"+idFile+"}");
527               
528                String file = SERVER_UPLOAD_LOCATION_FOLDER + idFile;
529               
530                File tmpFile = new File(file);
531               
532                JSONObject jsonObject = new JSONObject();
533               
534                if (!tmpFile.exists()) {
535                        System.out.println("File : " + file + " does not exists.");
536                        jsonObject.put("fileExist", "false");
537                        logger.debug("fileExist: false");
538                       
539                }else{
540                        System.out.println("File : " + file + " exists.");
541                        jsonObject.put("fileExist", "true");
542                       
543                        String mime = getMimeType(file);
544                        System.out.println("mimetype : " + mime);
545                       
546                        if (mime.equals("application/pdf")){
547                                System.out.println(" PDF ");
548                               
549                                jsonObject = verifySignaturesInPdf(file);
550                               
551                        //}else if (mime.equals("application/vnd.etsi.asic-e+zip")){
552                        }else if (mime.equals("application/zip") ){
553                                System.out.println("BDOC");                             
554                                //jsonObject.put("formato", "BDOC");
555                                //jsonObject.put("resultado", "NO IMPLEMENTADO");
556                               
557                                jsonObject = verifySignaturesInBdoc(file);
558                        }else{
559                                System.out.println("extension no reconocida");
560                                jsonObject.put("fileExist", "true");
561                                jsonObject.put("error", "extension not supported");
562                                logger.debug("error: extension not supported");
563                        }
564                }
565                String result = jsonObject.toString();
566                logger.info("/{"+idFile+"}: result");
567                return Response.status(200).entity(result).build();
568                               
569        }
570       
571        /**
572         * Verifica si un archivo local posee firmas electronicas y retorna informacion
573         * de las mismas en un json.
574         *
575         * @param idFile identificador del archivo a verificar
576         * @return JSONObject con informacion de las firmas
577         * @throws MurachiException
578         */
579        public JSONObject verifyALocalFile(String idFile) throws MurachiException {
580               
581                System.out.println("verifyALocalFile: " + idFile);
582                logger.debug("verifyALocalFile: " + idFile);
583               
584                String file = SERVER_UPLOAD_LOCATION_FOLDER + idFile;
585               
586                File tmpFile = new File(file);
587               
588                JSONObject jsonObject = new JSONObject();
589               
590                if (!tmpFile.exists()) {
591                        System.out.println("File : " + file + " does not exists.");
592                        jsonObject.put("fileExist", "false");
593                        logger.debug("fileExist: false");
594                       
595                }else{
596                        System.out.println("File : " + file + " exists.");
597                        jsonObject.put("fileExist", "true");
598                       
599                        String mime = getMimeType(file);
600                        System.out.println("mimetype : " + mime);
601                       
602                        if (mime.equals("application/pdf")){
603                                System.out.println(" PDF ");
604                               
605                                jsonObject = verifySignaturesInPdf(file);
606                               
607                        //}else if (mime.equals("application/vnd.etsi.asic-e+zip")){
608                        }else if (mime.equals("application/zip") ){
609                                System.out.println("BDOC");                             
610                                //jsonObject.put("formato", "BDOC");
611                                //jsonObject.put("resultado", "NO IMPLEMENTADO");
612                               
613                                jsonObject = verifySignaturesInBdoc(file);
614                        }else{
615                                System.out.println("extension no reconocida");
616                                jsonObject.put("fileExist", "true");
617                                jsonObject.put("error", "extension not supported");     
618                                logger.debug("error: extension not supported");
619                        }
620                }
621                return jsonObject;
622        }
623       
624       
625        /**
626         * Retorna un JSON con informacion de las firmas del documento PDF
627         * @param pdfFile archivo pdf a verificar
628         * @return JSON con informacion de las firmas del documento PDF
629         * @throws MurachiException
630         */
631        private JSONObject verifySignaturesInPdf(String pdfFile) throws MurachiException {
632               
633                logger.debug("verifySignaturesInPdf: "+ pdfFile);
634               
635                JSONObject jsonSignatures = new JSONObject();
636                JSONArray jsonArray = new JSONArray();
637               
638                try {
639                       
640                        Security.addProvider(new BouncyCastleProvider());
641                       
642                        PdfReader reader = new PdfReader(pdfFile);
643                        AcroFields af = reader.getAcroFields();
644                        ArrayList<String> names = af.getSignatureNames();
645                        if (names.size() <= 0) {
646                                jsonSignatures.put("signatureNumber", "0");
647                        }else{
648                               
649                                jsonSignatures.put("fileExist", "true");
650                                jsonSignatures.put("numberOfSignatures", names.size());
651                                                               
652                                HashMap<String, String> signatureInformation;
653                               
654                                // inicializar el keystore para verificacion
655                                KeyStore ks = setupKeyStore();
656                               
657                                for (String name : names) {
658                                        System.out.println("===== " + name + " =====");
659                                        signatureInformation = verifySignature(af, name, ks);
660                                        System.out.println("signatureInformation.size " + signatureInformation.size());
661                                       
662                                        JSONObject jo = getJSONFromASignature(signatureInformation);
663                                        System.out.println("jo:  " + jo.toString());
664                                        jsonArray.put(jo);
665                                }       
666                                jsonSignatures.put("signatures", jsonArray);
667                                System.out.println("jsonSignatures :  " + jsonSignatures.toString());
668                               
669                        }
670                       
671                } catch (IOException e) {
672                        logger.error("verifySignaturesInPdf ocurrio una excepcion", e);
673                        e.printStackTrace();
674                        throw new MurachiException(e.getMessage());
675                } catch (GeneralSecurityException e) {
676                        logger.error("verifySignaturesInPdf ocurrio una excepcion", e);
677                        e.printStackTrace();
678                        throw new MurachiException(e.getMessage());
679                }
680                               
681                return jsonSignatures;         
682        }
683       
684        /**
685         * Chequea la integridad de una revision basada en una firma electronica
686         * @param fields Campos
687         * @param name nombre de la firma
688         * @return HashMap con campos de informacion de la firma electronica
689         * @throws GeneralSecurityException falla en
690         * @throws IOException cuando ca
691         * @throws MurachiException
692         */
693        public HashMap<String, String> verifySignature(AcroFields fields, String name, KeyStore ks) 
694                        throws GeneralSecurityException, IOException, MurachiException {
695                       
696                logger.debug("verifySignature()");
697                HashMap<String, String> integrityMap = new HashMap<String, String>();
698               
699                System.out.println("Signature covers whole document: " + fields.signatureCoversWholeDocument(name));
700               
701                integrityMap.put("signatureCoversWholeDocument", Boolean.toString(fields.signatureCoversWholeDocument(name)));
702               
703                int revision = fields.getRevision(name);
704                System.out.println("Document revision: " + fields.getRevision(name) + " of " + fields.getTotalRevisions());             
705                integrityMap.put("documentRevision", Integer.toString(fields.getRevision(name)));
706               
707                System.out.println("Total Document revisions: " + fields.getTotalRevisions());
708                integrityMap.put("totalDocumentRevisions",  Integer.toString(fields.getTotalRevisions()));
709                               
710                PdfPKCS7 pkcs7 = fields.verifySignature(name);
711        System.out.println("Integrity check OK? " + pkcs7.verify());
712        integrityMap.put("integrityCheck", Boolean.toString(pkcs7.verify()));
713       
714        System.out.println("Digest Algorithm: " + pkcs7.getHashAlgorithm());
715        integrityMap.put("digestAlgorithm", pkcs7.getHashAlgorithm());
716       
717        System.out.println("Encryption Algorithm: " + pkcs7.getEncryptionAlgorithm());
718        integrityMap.put("encryptionAlgorithm", pkcs7.getEncryptionAlgorithm());
719       
720        System.out.println("Filter subtype: " + pkcs7.getFilterSubtype());
721        integrityMap.put("filterSubtype", pkcs7.getFilterSubtype().toString());
722       
723        X509Certificate cert = (X509Certificate) pkcs7.getSigningCertificate();
724                System.out.println("Name of the signer: " + CertificateInfo.getSubjectFields(cert).getField("CN"));
725                integrityMap.put("nameOfTheSigner", CertificateInfo.getSubjectFields(cert).getField("CN"));
726       
727                if (pkcs7.getSignName() != null){
728                        System.out.println("Alternative name of the signer: " + pkcs7.getSignName());
729                        integrityMap.put("alternativeNameOfTheSigner", pkcs7.getSignName());                   
730                }else{
731                        System.out.println("Alternative name of the signer: " + "null");
732                        integrityMap.put("alternativeNameOfTheSigner", "");
733                }
734               
735                SimpleDateFormat date_format = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss.SS");
736                System.out.println("Signed on: " + date_format.format(pkcs7.getSignDate().getTime()));
737                integrityMap.put("signedOn", date_format.format(pkcs7.getSignDate().getTime()).toString());
738               
739                if (pkcs7.getTimeStampDate() != null) {
740                        System.out.println("TimeStamp: " + date_format.format(pkcs7.getTimeStampDate().getTime()));
741                        integrityMap.put("timeStamp", date_format.format(pkcs7.getTimeStampDate().getTime()).toString());
742                        TimeStampToken ts = pkcs7.getTimeStampToken();
743                        System.out.println("TimeStamp service: " + ts.getTimeStampInfo().getTsa());
744                        integrityMap.put("timeStampService", ts.getTimeStampInfo().getTsa().toString());
745                        System.out.println("Timestamp verified? " + pkcs7.verifyTimestampImprint());
746                        integrityMap.put("timeStampVerified", Boolean.toString(pkcs7.verifyTimestampImprint()));
747                }else{
748                        System.out.println("TimeStamp: " + "null");
749                        integrityMap.put("timeStamp", "null");
750                       
751                        System.out.println("TimeStamp service: " + "null");
752                        integrityMap.put("timeStampService", "null");
753                       
754                        System.out.println("Timestamp verified?: " + "null");
755                        integrityMap.put("timeStampVerified", "null");
756                }
757               
758                System.out.println("Location: " + pkcs7.getLocation());
759                integrityMap.put("location", pkcs7.getLocation());             
760               
761                System.out.println("Reason: " + pkcs7.getReason());
762                integrityMap.put("reason", pkcs7.getReason());
763               
764                PdfDictionary sigDict = fields.getSignatureDictionary(name);
765                PdfString contact = sigDict.getAsString(PdfName.CONTACTINFO);
766                if (contact != null){
767                        System.out.println("Contact info: " + contact);
768                        integrityMap.put("contactInfo", contact.toString());                   
769                }else{
770                        System.out.println("Contact info: " + "null");
771                        integrityMap.put("contactInfo", "null");
772                }
773                       
774                SignaturePermissions perms = null;
775                perms = new SignaturePermissions(sigDict, perms);
776                System.out.println("Signature type: " + (perms.isCertification() ? "certification" : "approval"));
777                integrityMap.put("signatureType", (perms.isCertification() ? "certification" : "approval"));
778               
779               
780                //KeyStore ks = setupKeyStore();
781               
782                Certificate[] certs = pkcs7.getSignCertificateChain();
783                Calendar cal = pkcs7.getSignDate();
784                List<VerificationException> errors = CertificateVerification.verifyCertificates(certs, ks, cal);
785                if (errors.size() == 0){               
786                        System.out.println("Certificates verified against the KeyStore");
787                        integrityMap.put("certificatesVerifiedAgainstTheKeyStore", "true");
788                }
789                else{
790                        System.out.println(errors);
791                        integrityMap.put("certificatesVerifiedAgainstTheKeyStore", "false");
792                }
793               
794               
795                X509Certificate certificateTmp = (X509Certificate) certs[0];
796                System.out.println("=== Certificate " + Integer.toString(revision) + " ===");
797
798                HashMap<String, String> signerCertificateMap = getSignerCertificateInfo(certificateTmp, cal.getTime());
799                for (Entry<String, String> entry : signerCertificateMap.entrySet()) {
800                        integrityMap.put(entry.getKey(), entry.getValue());
801                }
802               
803                return integrityMap;
804        }
805       
806        /**
807         * Construye un objeto JSON a partir del HashMap pasado como argumento
808         * @param hashMap HashMap que contiene los elementos para construir el JSON
809         * @return objeto JSON a partir del HashMap pasado como argumento
810         */
811        public JSONObject getJSONFromASignature(HashMap<String, String> hashMap) {
812               
813                logger.debug("getJSONFromASignature()");
814                JSONObject jsonSignature = new JSONObject();
815               
816                for (Entry<String, String> entry : hashMap.entrySet()) {
817                    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
818                    jsonSignature.put(entry.getKey(), entry.getValue());
819                }               
820                return jsonSignature;           
821        }
822       
823        /**
824         * Carga el KeyStore con certificados confiables para la verificacion de certificados
825         * de firmas
826         * @return KeyStore con certificados confiables
827         * @throws MurachiException
828         */
829        private KeyStore setupKeyStore() throws MurachiException {
830                logger.debug("setupKeyStore()");
831                KeyStore ks = null;
832                try {
833                        ks = KeyStore.getInstance(KeyStore.getDefaultType());
834                       
835                        ks.load(null, null);
836                        CertificateFactory cf = CertificateFactory.getInstance("X.509");
837                        ks.setCertificateEntry("acraiz",
838                                        cf.generateCertificate(new FileInputStream(getAbsolutePathOfResource("CERTIFICADO-RAIZ-SHA384.crt"))));
839                        ks.setCertificateEntry("pscfii", 
840                                        cf.generateCertificate(new FileInputStream(getAbsolutePathOfResource("PSCFII-SHA256.crt"))));                   
841                        ks.setCertificateEntry("procert", 
842                                        cf.generateCertificate(new FileInputStream(getAbsolutePathOfResource("PSC-PROCERT-SHA256.crt"))));                     
843                        ks.setCertificateEntry("altosfuncionarios", 
844                                        cf.generateCertificate(new FileInputStream(getAbsolutePathOfResource("ACALTOS-FUNCIONARIOS-SHA256.crt"))));                     
845                        ks.setCertificateEntry("acsubordinadafundayacucho", 
846                                        cf.generateCertificate(new FileInputStream(getAbsolutePathOfResource("ACSUBORDINADA-FUNDAYACUCHO.crt"))));                     
847                        ks.setCertificateEntry("gidsi", 
848                                        cf.generateCertificate(new FileInputStream(getAbsolutePathOfResource("GIDSI.crt"))));
849                                               
850                } catch (KeyStoreException e) { 
851                        logger.error("setupKeyStore() ocurrio una excepcion", e);
852                        e.printStackTrace();
853                        throw new MurachiException(e.getMessage());
854                } catch (NoSuchAlgorithmException e) {
855                        logger.error("setupKeyStore() ocurrio una excepcion", e);
856                        e.printStackTrace();
857                        throw new MurachiException(e.getMessage());
858                } catch (CertificateException e) {
859                        logger.error("setupKeyStore() ocurrio una excepcion", e);
860                        e.printStackTrace();
861                        throw new MurachiException(e.getMessage());
862                } catch (IOException e) {
863                        logger.error("setupKeyStore() ocurrio una excepcion", e);
864                        e.printStackTrace();
865                        throw new MurachiException(e.getMessage());
866                }               
867                return ks;
868        }
869       
870        /**
871         * Obtiene informacion del certificado firmante de una revision
872         * @param cert certificado firmante
873         * @param signDate fecha en que se realizo la firma
874         * @return informacion del certificado firmante de una revision en forma de HashMap
875         * @throws MurachiException
876         */
877        public HashMap<String, String> getSignerCertificateInfo(X509Certificate cert, Date signDate) throws MurachiException {
878                logger.debug("getSignerCertificateInfo()");
879                HashMap<String, String> signerCertificateMap = new HashMap<String, String>();
880               
881                System.out.println("Issuer: " + cert.getIssuerDN());
882                signerCertificateMap.put("signerCertificateIssuer", cert.getIssuerDN().toString());
883               
884               
885                System.out.println("Subject: " + cert.getSubjectDN());
886                signerCertificateMap.put("signerCertificateSubject", cert.getSubjectDN().toString());
887               
888                SimpleDateFormat date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS");
889                System.out.println("Valid from: " + date_format.format(cert.getNotBefore()));
890                signerCertificateMap.put("signerCertificateValidFrom", date_format.format(cert.getNotBefore()).toString());
891               
892                System.out.println("Valid to: " + date_format.format(cert.getNotAfter()));
893                signerCertificateMap.put("signerCertificateValidTo", date_format.format(cert.getNotAfter()).toString());
894               
895                try {
896                        cert.checkValidity(signDate);
897                        System.out
898                                        .println("The certificate was valid at the time of signing.");
899                        signerCertificateMap.put("signerCertificateValidAtTimeOfSigning", "true");
900                } catch (CertificateExpiredException e) {
901                        System.out
902                                        .println("The certificate was expired at the time of signing.");
903                       
904                        signerCertificateMap.put("signerCertificateValidAtTimeOfSigning", "false");
905                       
906                        signerCertificateMap.put("signerCertificateExpiredAtTimeOfSigning", "true");
907                        logger.error("getSignerCertificateInfo() ocurrio una excepcion: The certificate was expired at the time of signing");
908                        //throw new MurachiException(e.getMessage());
909                } catch (CertificateNotYetValidException e) {
910                        System.out
911                                        .println("The certificate wasn't valid yet at the time of signing.");
912                       
913                        signerCertificateMap.put("signerCertificateValidAtTimeOfSigning", "false");
914                       
915                        signerCertificateMap.put("signerCertificateNotValidYetAtTimeOfSigning", "true");
916                        logger.error("getSignerCertificateInfo() ocurrio una excepcion: The certificate wasn't valid yet at the time of signing");
917                        //throw new MurachiException(e.getMessage());
918                }
919                try {
920                        cert.checkValidity();
921                        System.out.println("The certificate is still valid.");
922                        signerCertificateMap.put("signerCertificateStillValid", "true");
923                } catch (CertificateExpiredException e) {
924                        System.out.println("The certificate has expired.");
925                       
926                        signerCertificateMap.put("signerCertificateStillValid", "false");
927                       
928                        signerCertificateMap.put("signerCertificateHasExpired", "true");
929                        logger.error("getSignerCertificateInfo() ocurrio una excepcion: The certificate has expired");
930                        //throw new MurachiException(e.getMessage());
931                } catch (CertificateNotYetValidException e) {
932                        System.out.println("The certificate isn't valid yet.");
933                       
934                        signerCertificateMap.put("signerCertificateStillValid", "false");
935                       
936                        signerCertificateMap.put("signerCertificateNotValidYet", "true");
937                        logger.error("getSignerCertificateInfo() ocurrio una excepcion: The certificate isn't valid yet");
938                        //throw new MurachiException(e.getMessage());
939                }
940                return signerCertificateMap;
941        }
942       
943       
944        /**
945         * Ejecuta el proceso de presign o preparacion de firma de documento pdf.
946         *
947         * Estructura del JSON que recibe la funcion:
948         *
949         *      {"fileId":"file_id",                           
950         *      "certificate":"hex_cert_value",
951         *  "reason":"reason",
952         *  "location":"location",
953         *  "contact":"contact"
954         *  }
955         *
956         *
957         * @param presignPar JSON con los parametros de preparacion: Id del archivo y certificado
958         * firmante
959         * @param req objeto request para crear una sesion y mantener elementos del
960         * pdf en la misma.
961         * @throws MurachiException
962         *
963         * @api {post} /Murachi/0.1/archivos/firmados/pdfs Prepara la firma del documento PDF.
964         * @apiName Pdfs
965         * @apiGroup PDFS
966         * @apiVersion 0.1.0
967         * @apiDescription Prepara la firma de un documento PDF. Se debe pasar un JSON con la siguiente estructura:
968         *  {"fileId":"file_id",                               
969         *      "certificate":"hex_cert_value",
970         *  "reason":"reason",
971         *  "location":"location",
972         *  "contact":"contact"
973         *  }
974         *
975         * @apiSuccess {String} hash Reseña o hash del archivo que se debe cifrar con la clave privada protegida por el
976         * dispositivo criptográfico.
977         *
978         * @apiExample Example usage:
979         *
980         * var parameters = JSON.stringify({
981         *                             "fileId":fileId,
982         *                             "certificate":cert.hex,
983         *                             "reason":"prueba firma web",
984         *                             "location":"Oficina",
985         *                             "contact":"582746574336"
986         *                             });
987         *
988         * $.ajax({
989     *           url: "https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/pdfs",
990     *           type: "post",
991     *           dataType: "json",
992     *           data: parameters,
993     *           contentType: "application/json",
994     *           success: function(data, textStatus, jqXHR){
995         *                              var json_x = data;
996     *                              var hash = json_x['hash'];
997     *                              alert("hash recibido del servidor "+hash);
998     *           },
999         *           error: function(jqXHR, textStatus, errorThrown){
1000         *                              //alert('error: ' + textStatus);
1001         *                              //var responseText = jQuery.parseJSON(jqXHR.responseText);
1002         *                              alert('ajax error function: ' + jqXHR.responseText);
1003         *                             
1004         *           }
1005     *  });
1006         *
1007         *
1008         *
1009         * @apiErrorExample {json} Error-Response:
1010         *     HTTP/1.1 400 Bad Request
1011         *     {
1012         *       "hash": "",
1013         *       "error": "El archivo que desea firmar no es un PDF."
1014         *     }
1015         *     
1016         *     HTTP/1.1 500 Internal Server Error
1017         *     {
1018         *       "hash": "",
1019         *       "error": "error en carga de certificado de firmante"
1020         *     }
1021         *
1022         *
1023         */
1024        @POST
1025        @Path("/pdfs")
1026        @Consumes(MediaType.APPLICATION_JSON)
1027        @Produces(MediaType.APPLICATION_JSON)
1028        //public PresignHash presignPdf(PresignParameters presignPar, @Context HttpServletRequest req) {
1029        public Response presignPdf(PresignParameters presignPar, @Context HttpServletRequest req) throws MurachiException {
1030               
1031                logger.info("/pdfs");
1032               
1033                PresignHash presignHash = new PresignHash();
1034
1035                // obtener el id del archivo
1036                String fileId = presignPar.getFileId();
1037               
1038                // cadena con el certificado
1039                String certHex = presignPar.getCertificate();
1040                System.out.println("certificado en Hex: " + certHex);
1041
1042                String reason = presignPar.getReason();
1043               
1044                String location = presignPar.getLocation();
1045               
1046                String contact = presignPar.getContact();
1047               
1048               
1049                String pdf = SERVER_UPLOAD_LOCATION_FOLDER + fileId;
1050                System.out.println("archivo a firmar: " + pdf);
1051                logger.debug("archivo a firmar: " + pdf);
1052               
1053                String mime = getMimeType(pdf);
1054               
1055                if (!mime.equals("application/pdf")){
1056                        presignHash.setError("El archivo que desea firmar no es un PDF.");
1057                        presignHash.setHash("");
1058                        //return presignHash;
1059                                                                       
1060                        //result = presignHash.toString();
1061                        logger.info("El archivo que desea firmar no es un PDF.");
1062                        return Response.status(400).entity(presignHash).build();
1063                       
1064                }
1065                       
1066                               
1067                try {
1068                        CertificateFactory factory = CertificateFactory.getInstance("X.509");
1069                        Certificate[] chain = new Certificate[1];
1070                       
1071                        InputStream in = new ByteArrayInputStream(hexStringToByteArray(certHex));
1072                        chain[0] = factory.generateCertificate(in);
1073                       
1074                        if (chain[0] == null) {
1075                                System.out.println("error chain[0] == null");
1076                                logger.error("presignPdf: error en carga de certificado de firmante");
1077                                //throw new MurachiException("presignPdf: error en carga de certificado de firmante");
1078                               
1079                                presignHash.setError("error en carga de certificado de firmante");
1080                                presignHash.setHash("");
1081                                return Response.status(500).entity(presignHash).build();
1082                                                               
1083                        }else {
1084                               
1085                                System.out.println("se cargo el certificado correctamente");
1086                                System.out.println(chain[0].toString());
1087                                logger.debug("se cargo el certificado correctamente");
1088                                logger.debug(chain[0].toString());
1089                        }                       
1090                       
1091                        PdfReader reader = new PdfReader(pdf);                 
1092                       
1093                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1094                       
1095                        //PdfStamper stamper = PdfStamper.createSignature(reader, baos, '\0');
1096                        PdfStamper stamper = null;
1097                       
1098                       
1099                        if (pdfAlreadySigned(reader)){
1100                                stamper = PdfStamper.createSignature(reader, baos, '\0', null, true);
1101                        }else{
1102                                stamper = PdfStamper.createSignature(reader, baos, '\0');
1103                        }
1104
1105                        // crear la apariencia de la firma
1106                PdfSignatureAppearance sap = stamper.getSignatureAppearance();
1107                               
1108                sap.setReason(reason);
1109                sap.setLocation(location);
1110                sap.setContact(contact);
1111               
1112                //sap.setVisibleSignature(new Rectangle(36, 748, 144,780),1, "sig");
1113               
1114                if (!pdfAlreadySigned(reader)){
1115                        sap.setVisibleSignature(new Rectangle(36, 748, 144, 780),1, "sig1");
1116                        }else{
1117                                int idSig = numberOfSignatures(reader)+1;
1118                                //sap.setVisibleSignature(new Rectangle(36, 700, 144, 732),1, "sig"+Integer.toString(idSig));
1119                                sap.setVisibleSignature(
1120                                                new Rectangle(36, (748-(numberOfSignatures(reader)*38)), 144, (780-(numberOfSignatures(reader)*38))),
1121                                                        1, "sig"+Integer.toString(idSig));
1122                        }
1123               
1124                sap.setCertificate(chain[0]);
1125               
1126                // crear la estructura de la firma
1127                PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
1128               
1129               
1130                dic.setReason(sap.getReason());
1131                dic.setLocation(sap.getLocation());
1132                dic.setContact(sap.getContact());
1133                dic.setDate(new PdfDate(sap.getSignDate()));
1134               
1135                sap.setCryptoDictionary(dic);
1136               
1137                HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer> ();
1138                exc.put(PdfName.CONTENTS, new Integer(8192 * 2 + 2));
1139                sap.preClose(exc);
1140               
1141                ExternalDigest externalDigest = new ExternalDigest() {
1142                        public MessageDigest getMessageDigest(String hashAlgorithm)
1143                        throws GeneralSecurityException {
1144                                return DigestAlgorithms.getMessageDigest(hashAlgorithm, null);
1145                        }
1146                };
1147                       
1148                       
1149                PdfPKCS7 sgn = new PdfPKCS7(null, chain, SHA256_MESSAGE_DIGEST, null, externalDigest, false);
1150               
1151                InputStream data = sap.getRangeStream();
1152               
1153                byte hash[] = DigestAlgorithms.digest(data, externalDigest.getMessageDigest(SHA256_MESSAGE_DIGEST));
1154               
1155                Calendar cal = Calendar.getInstance();
1156                byte sh[] = sgn.getAuthenticatedAttributeBytes(hash, cal, null, null, CryptoStandard.CMS);
1157               
1158                sh = DigestAlgorithms.digest(new ByteArrayInputStream(sh), externalDigest.getMessageDigest(SHA256_MESSAGE_DIGEST));
1159               
1160                System.out.println("sh length: "+ sh.length);
1161                logger.debug("sh length: "+ sh.length);
1162                       
1163                String hashToSign = byteArrayToHexString(sh);
1164                logger.debug("hashToSign: "+ hashToSign);
1165                logger.debug("length: " +hashToSign.length());
1166                System.out.println("***************************************************************");
1167                System.out.println("HASH EN HEXADECIMAL:");
1168                System.out.println(hashToSign);
1169                System.out.println("length: " +hashToSign.length());   
1170                System.out.println("***************************************************************");
1171                       
1172                DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
1173                        Date date = new Date();
1174                        System.out.println(dateFormat.format(date));
1175                        //String d = dateFormat.format(date);
1176                       
1177                       
1178                        // almacenar los objetos necesarios para realizar el postsign en una sesion
1179                        HttpSession session = req.getSession(true);
1180                        session.setAttribute("hashToSign", hashToSign);
1181                       
1182                        session.setAttribute("stamper", stamper);
1183                        session.setAttribute("sgn", sgn);
1184                        session.setAttribute("hash", hash);
1185                        session.setAttribute("cal", cal);
1186                        session.setAttribute("sap", sap);
1187                        session.setAttribute("baos", baos);
1188                        session.setAttribute("fileId", fileId);
1189                       
1190                        presignHash.setHash(hashToSign);
1191                        presignHash.setError("");
1192                               
1193                       
1194                } catch (CertificateException e1) {
1195                        logger.error("presignPdf ocurrio una excepcion ", e1);
1196                        e1.printStackTrace();
1197                        //throw new MurachiException(e1.getMessage());
1198                        presignHash.setError(e1.getMessage());
1199                        presignHash.setHash("");
1200                        return Response.status(500).entity(presignHash).build();                       
1201                       
1202                } catch (InvalidPdfException e) {
1203                        logger.error("presignPdf ocurrio una excepcion ", e);
1204                        e.printStackTrace();
1205                        //presignHash.setError("No se pudo leer el archivo PDF en el servidor");
1206                        //throw new MurachiException(e.getMessage());
1207                        presignHash.setError("No se pudo leer el archivo PDF en el servidor");
1208                        presignHash.setHash("");
1209                        return Response.status(500).entity(presignHash).build();
1210                       
1211                } catch (IOException e) {
1212                        logger.error("presignPdf ocurrio una excepcion ", e);
1213                        e.printStackTrace();
1214                        //throw new MurachiException(e.getMessage());
1215                       
1216                        presignHash.setError(e.getMessage());
1217                        presignHash.setHash("");
1218                        return Response.status(500).entity(presignHash).build();
1219                       
1220                } catch (DocumentException e) {
1221                        logger.error("presignPdf ocurrio una excepcion ", e);
1222                        e.printStackTrace();
1223                        //throw new MurachiException(e.getMessage());
1224                       
1225                        presignHash.setError(e.getMessage());
1226                        presignHash.setHash("");
1227                        return Response.status(500).entity(presignHash).build();
1228                       
1229                } catch (InvalidKeyException e) {
1230                        logger.error("presignPdf ocurrio una excepcion ", e);
1231                        e.printStackTrace();
1232                        //throw new MurachiException(e.getMessage());
1233                       
1234                        presignHash.setError(e.getMessage());
1235                        presignHash.setHash("");
1236                        return Response.status(500).entity(presignHash).build();
1237                       
1238                } catch (NoSuchProviderException e) {
1239                        logger.error("presignPdf ocurrio una excepcion ", e);
1240                        e.printStackTrace();
1241                        //throw new MurachiException(e.getMessage());
1242                       
1243                        presignHash.setError(e.getMessage());
1244                        presignHash.setHash("");
1245                        return Response.status(500).entity(presignHash).build();
1246                       
1247                } catch (NoSuchAlgorithmException e) {
1248                        logger.error("presignPdf ocurrio una excepcion ", e);
1249                        e.printStackTrace();
1250                        //throw new MurachiException(e.getMessage());
1251                       
1252                        presignHash.setError(e.getMessage());
1253                        presignHash.setHash("");
1254                        return Response.status(500).entity(presignHash).build();
1255                       
1256                } catch (GeneralSecurityException e) {
1257                        logger.error("presignPdf ocurrio una excepcion ", e);
1258                        e.printStackTrace();
1259                        //throw new MurachiException(e.getMessage());
1260                       
1261                        presignHash.setError(e.getMessage());
1262                        presignHash.setHash("");
1263                        return Response.status(500).entity(presignHash).build();
1264                       
1265                } 
1266               
1267                logger.debug("presignPdf: "+ presignHash.toString());
1268                return Response.status(200).entity(presignHash).build();
1269                //return presignHash;
1270                       
1271        }
1272       
1273        /**
1274         * Retorna verdadero si el archivo pdf pasado como argumento ya esta firmado.
1275         *
1276         * @param pdfReader objeto PdfReader asociado al documento pdf
1277         * @return si el archivo pdf pasado como argumento ya esta firmado.
1278         * @throws IOException
1279         */
1280        private Boolean pdfAlreadySigned(PdfReader pdfReader) throws IOException {
1281               
1282                logger.debug("pdfAlreadySigned()");
1283                Security.addProvider(new BouncyCastleProvider());
1284               
1285                AcroFields af = pdfReader.getAcroFields();
1286                ArrayList<String> names = af.getSignatureNames();
1287                if (names.size() <= 0) {
1288                        return false;
1289                }else{
1290                        return true;
1291                }
1292        }
1293       
1294        /**
1295         * Retorna el número de firmas del documento
1296         * @param pdfReader objeto PdfReader asociado al documento pdf
1297         * @return número de firmas del documento
1298         */
1299        private int numberOfSignatures(PdfReader pdfReader) {
1300                logger.debug("numberOfSignatures()");
1301                Security.addProvider(new BouncyCastleProvider());
1302               
1303                AcroFields af = pdfReader.getAcroFields();
1304                ArrayList<String> names = af.getSignatureNames();
1305                return names.size();           
1306        }
1307       
1308       
1309        /**
1310         * Ejecuta el proceso de postsign o completacion de firma de documento pdf
1311         * @param postsignPar JSON con los parametros de postsign: signature realizada a partir
1312         * del hardware criptografico en el navegador.
1313         * @param req objeto request para crear una sesion y mantener elementos del
1314         * pdf en la misma.
1315         * @throws IOException
1316         * @throws MurachiException
1317         *
1318         *
1319         * @api {post} /Murachi/0.1/archivos/firmados/pdfs/resenas Completa la firma del documento PDF.
1320         * @apiName PdfsResenas
1321         * @apiGroup PDFS
1322         * @apiVersion 0.1.0
1323         * @apiDescription Completa la firma del documento PDF. Recibe el hash cifrado del cliente y termina de completar la firma del
1324         * archivo PDF.
1325         *
1326         * @apiSuccess {String} signedFileId Identificador único del archivo firmado en el servidor.
1327         *
1328         * @apiExample Example usage:
1329         *
1330         * $.ajax({
1331     *           url: "https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/pdfs/resenas",
1332     *           type: "post",
1333     *           dataType: "json",
1334     *           data: JSON.stringify({"signature":signature.hex}),
1335     *           contentType: "application/json",
1336     *           success: function(data, textStatus, jqXHR){
1337     *                              alert('Archivo firmado correctamente: ' + data['signedFileId']);
1338     *           },
1339         *           error: function(jqXHR, textStatus, errorThrown){
1340         *                              alert('error en pdfs/resenas: ' + textStatus);
1341         *           }
1342     *  });
1343         *
1344         *
1345         *
1346         * @apiErrorExample {json} Error-Response:
1347         *     HTTP/1.1 500 Internal Server Error
1348         *     {
1349         *       "error": "El archivo que desea firmar no es un PDF."
1350         *     }
1351         *
1352         */
1353        @POST
1354        @Path("/pdfs/resenas")
1355        @Consumes(MediaType.APPLICATION_JSON)
1356        @Produces(MediaType.APPLICATION_JSON)   
1357        public Response postsignPdf(PostsignParameters postsignPar, @Context HttpServletRequest req) throws IOException, MurachiException {
1358               
1359                logger.info("/pdfs/resenas");
1360                // cadena con la firma
1361                String signature = postsignPar.getSignature();
1362                System.out.println("firma en Hex: " + signature);
1363               
1364                HttpSession session = req.getSession(false);
1365               
1366                String fileId = (String) session.getAttribute("fileId");
1367                System.out.println("fileId: " + fileId);
1368                logger.debug("fileId: " + fileId);
1369               
1370                PdfStamper stamper = (PdfStamper) session.getAttribute("stamper");
1371               
1372                PdfPKCS7 sgn = (PdfPKCS7) session.getAttribute("sgn");
1373               
1374                byte[] hash = (byte[]) session.getAttribute("hash");
1375               
1376                Calendar cal = (Calendar) session.getAttribute("cal");
1377               
1378                PdfSignatureAppearance sap = (PdfSignatureAppearance) session.getAttribute("sap");
1379               
1380                ByteArrayOutputStream os = (ByteArrayOutputStream) session.getAttribute("baos");
1381               
1382                JSONObject jsonError = new JSONObject();
1383               
1384                if (sgn == null) {
1385                        System.out.println("sgn == null");
1386                        logger.error("Error en completacion de firma: estructura PdfPKCS7 nula");
1387                        //throw new MurachiException("Error en completacion de firma: estructura PdfPKCS7 nula");
1388                       
1389                        jsonError.put("error", "estructura PdfPKCS7 nula");
1390                        return Response.status(500).entity(jsonError).build();                 
1391                }
1392                if (hash == null) {
1393                        System.out.println("hash == null");
1394                        logger.error("Error en completacion de firma: hash nulo");
1395                        //throw new MurachiException("Error en completacion de firma: hash nulo");
1396                        jsonError.put("error", "hash nulo");
1397                        return Response.status(500).entity(jsonError).build();
1398                }
1399                if (cal == null) {
1400                        System.out.println("cal == null");
1401                        logger.error("Error en completacion de firma: estructura de fecha nula");
1402                        //throw new MurachiException("Error en completacion de firma: estructura de fecha nula");
1403                       
1404                        jsonError.put("error", "estructura de fecha nula");
1405                        return Response.status(500).entity(jsonError).build();
1406                }
1407                if (sap == null) {
1408                        System.out.println("sap == null");
1409                        logger.error("Error en completacion de firma: estructura de apariencia de firma pdf nula");
1410                        //throw new MurachiException("Error en completacion de firma: estructura de apariencia de firma pdf nula");
1411                       
1412                        jsonError.put("error", "estructura de apariencia de firma pdf nula");
1413                        return Response.status(500).entity(jsonError).build();
1414                }
1415                if (os == null) {
1416                        System.out.println("os == null");
1417                        logger.error("Error en completacion de firma: bytes de archivo nulos");
1418                        //throw new MurachiException("Error en completacion de firma: bytes de archivo nulos");
1419                       
1420                        jsonError.put("error", "bytes de archivo nulos");
1421                        return Response.status(500).entity(jsonError).build();
1422                }
1423
1424                System.out.println("antes de  hexStringToByteArray(signature)");
1425                // convertir signature en bytes         
1426                byte[] signatureInBytes = hexStringToByteArray(signature);
1427                               
1428                // completar el proceso de firma
1429                sgn.setExternalDigest(signatureInBytes, null, "RSA");
1430                byte[] encodeSig = sgn.getEncodedPKCS7(hash, cal, null, null, null, CryptoStandard.CMS);
1431                byte[] paddedSig = new byte[8192];
1432                System.arraycopy(encodeSig, 0, paddedSig, 0, encodeSig.length);
1433                PdfDictionary dic2 = new PdfDictionary();
1434                dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));
1435               
1436                try {
1437                        sap.close(dic2);                       
1438                        stamper.close();
1439                        System.out.println("stamper.close");
1440                       
1441                }catch(DocumentException e) {
1442                        System.out.println("throw new IOException");
1443                        logger.error("postsignPdf: ocurrio una excepcion", e);
1444                        //throw new MurachiException(e.getMessage());
1445                        jsonError.put("error", e.getMessage());
1446                        return Response.status(500).entity(jsonError).build();                 
1447                       
1448                } catch (IOException e) {
1449                        System.out.println("IOException e");
1450                        logger.error("postsignPdf: ocurrio una excepcion", e);
1451                        e.printStackTrace();
1452                        //throw new MurachiException(e.getMessage());
1453                       
1454                        jsonError.put("error", e.getMessage());
1455                        return Response.status(500).entity(jsonError).build();
1456                       
1457                }
1458               
1459                String signedPdf = SERVER_UPLOAD_LOCATION_FOLDER + fileId + "-signed.pdf";
1460               
1461                FileOutputStream signedFile = new FileOutputStream(signedPdf);
1462               
1463                os.writeTo(signedFile);
1464                os.flush();
1465                               
1466                // en este punto el archivo pdf debe estar disponible en la ruta
1467                // SERVER_UPLOAD_LOCATION_FOLDER + fileId;             
1468                System.out.println("Archivo firmado correctamente");
1469                logger.debug("Archivo firmado correctamente");
1470                       
1471                PostsignMessage message = new PostsignMessage();
1472                //message.setMessage(SERVER_UPLOAD_LOCATION_FOLDER + fileId + "-signed.pdf");
1473                message.setMessage("{\"signedFile\":"+fileId + "-signed.pdf}");
1474                //return Response.status(200).entity(message).build();
1475               
1476                JSONObject jsonFinalResult = new JSONObject();
1477                jsonFinalResult.put("signedFileId",fileId + "-signed.pdf");
1478               
1479                logger.info(jsonFinalResult.toString());
1480                return Response.status(200).entity(jsonFinalResult.toString()).build();
1481        }
1482       
1483        /**
1484         * Descarga el archivo pdf pasado como argumento.
1485         * @param idFile nombre del archivo pdf a descargar
1486         * @return archivo pdf pasado como argumento.
1487         */
1488        @GET
1489        @Path("/pdfs/{idFile}")
1490        public Response getPdfSigned(@PathParam("idFile") String idFile) {
1491                logger.info("/pdfs/{idFile}");
1492                File file = null;
1493               
1494                file = new File(SERVER_UPLOAD_LOCATION_FOLDER + idFile);
1495                /*
1496                if (!file.exists()){
1497                       
1498                }
1499                */
1500                         
1501                ResponseBuilder response = Response.ok((Object) file);
1502                response.header("Content-Disposition", "attachment; filename=" + file.getName());
1503                return response.build();
1504        }
1505       
1506       
1507        // ******* BDOC ***********************************************************
1508       
1509        /**
1510         * Retorna un JSON con informacion de las firmas del documento BDOC
1511         * @param bdocFile archivo BDOC a verificar
1512         * @return JSON con informacion de las firmas del documento BDOC
1513         */
1514        private JSONObject verifySignaturesInBdoc(String bdocFile) {
1515       
1516                JSONObject jsonSignatures = new JSONObject();
1517
1518                JSONArray jsonSignaturesArray = new JSONArray();
1519                JSONArray jsonContainerValidationExceptionArray = new JSONArray();
1520               
1521                Security.addProvider(new BouncyCastleProvider());
1522                Container container;
1523                container = Container.open(bdocFile);
1524               
1525                int numberOfSignatures = container.getSignatures().size();
1526                if (numberOfSignatures == 0){
1527                        jsonSignatures.put("signatureNumber", "0");
1528                }else{
1529                        jsonSignatures.put("fileExist", "true");
1530                       
1531                        // informacion de archivos dentro del contenedor
1532                        if (container.getDataFiles().size() > 0){
1533                                jsonSignatures.put("numberOfDataFiles", container.getDataFiles().size()); 
1534                                jsonSignatures.put("dataFiles", getJSONFromBDOCDataFiles(container.getDataFiles()));
1535                                System.out.println(" dataFiles:  " + getJSONFromBDOCDataFiles(container.getDataFiles()).toString());
1536                        }else{
1537                                System.out.println(" dataFiles:  == 0");
1538                        }
1539               
1540                        jsonSignatures.put("numberOfSignatures", numberOfSignatures);
1541                       
1542                        ValidationResult validationResult = container.validate();
1543                        List<DigiDoc4JException> exceptions = validationResult.getContainerErrors();
1544                       
1545                        boolean isDDoc = container.getDocumentType() == DocumentType.DDOC;
1546                       
1547                        if (exceptions.size() > 0){
1548                                jsonSignatures.put("containerValidation", false);
1549                               
1550                                for (DigiDoc4JException exception : exceptions) {
1551                                        JSONObject containerException = new JSONObject();
1552                                       
1553                                        if (isDDoc && isWarning(((DDocContainer) container).getFormat(), exception)){
1554                                                System.out.println("    Warning: " + exception.toString());
1555                                               
1556                                    }
1557                                    else{
1558                                        System.out.println((isDDoc ? "  " : "   Error_: ") + exception.toString());
1559                                       
1560                                    }
1561                                        containerException.put("containerValidationException", exception.toString());
1562                                    jsonContainerValidationExceptionArray.put(containerException);
1563                                }
1564                            if (isDDoc && (((ValidationResultForDDoc) validationResult).hasFatalErrors())) {
1565                                jsonSignatures.put("validationResultForDDocHasFatalErrors", true);
1566                                return jsonSignatures; 
1567                            }
1568                            jsonSignatures.put("containerValidationExceptions", jsonContainerValidationExceptionArray);
1569                               
1570                               
1571                        }else{
1572                                jsonSignatures.put("containerValidation", true);
1573                               
1574                                HashMap<String, String> signatureInformation;
1575                                for (int i=0; i< numberOfSignatures; i++) {
1576                                        System.out.println("===== firma " + i + " =====");
1577                                        signatureInformation = verifyBDOCSignature(container.getSignature(i), container.getDocumentType());
1578                                        System.out.println("signatureInformation.size " + signatureInformation.size());
1579                                       
1580                                        JSONObject jo = getJSONFromASignature(signatureInformation);
1581                                        //System.out.println("jo:  " + jo.toString());
1582                                        jsonSignaturesArray.put(jo);                                   
1583                                }
1584                                                               
1585                                jsonSignatures.put("signatures", jsonSignaturesArray);                                                         
1586                                System.out.println(jsonSignatures.toString());                         
1587                        }                       
1588                }
1589                //verifyBdocContainer(container);               
1590                jsonSignatures.put("validation", "executed");                           
1591                return jsonSignatures;
1592        }
1593       
1594        /**
1595         * Retorna un JSON con informacion de los DataFiles incluidos en el contenedor
1596         * @param dataFilesList lista de DataFile incluidos en el contenedor
1597         * @return JSON con informacion de los DataFiles incluidos en el contenedor
1598         */
1599        private JSONArray getJSONFromBDOCDataFiles(List<DataFile> dataFilesList) {
1600                JSONArray jsonDataFileArray = new JSONArray();
1601               
1602                for (int i = 0; i < dataFilesList.size(); i++){
1603                       
1604                        JSONObject tmpJsonDataFile = new JSONObject();
1605                        DataFile df = dataFilesList.get(i);
1606                        tmpJsonDataFile.put("dataFileSize", Long.toString(df.getFileSize()));
1607                        tmpJsonDataFile.put("filename", df.getId());
1608                        tmpJsonDataFile.put("mediaType", df.getMediaType());
1609                        tmpJsonDataFile.put("name", df.getName());
1610                        jsonDataFileArray.put(tmpJsonDataFile);
1611                }
1612               
1613                //JSONObject jsonDataFile = new JSONObject();
1614                //jsonDataFile.put("dataFiles", jsonDataFileArray);
1615               
1616                //return jsonDataFile;
1617                return jsonDataFileArray;
1618        }
1619
1620        /**
1621         * Retorna Hashmap con la informacion de una firma electronica que se verifica
1622         * @param signature firma para verificar
1623         * @param documentType tipo de documento
1624         * @return Hashmap con la informacion de una firma electronica que se verifica
1625         */
1626        private static HashMap<String, String> verifyBDOCSignature(Signature signature, DocumentType documentType) {
1627               
1628                HashMap<String, String> signatureMap = new HashMap<String, String>();
1629               
1630                boolean isDDoc = documentType == DocumentType.DDOC;
1631               
1632                List<DigiDoc4JException> signatureValidationResult = signature.validate();
1633               
1634                if (signatureValidationResult.size() > 0) {
1635                        System.out.println("Signature " + signature.getId() + " is not valid");
1636                signatureMap.put("isValid", Boolean.toString(false));
1637                int counter = 1;
1638               
1639                //JSONArray jsonValidationExceptionArray = new JSONArray();
1640                //JSONObject tmpValidationException = new JSONObject();
1641               
1642                for (DigiDoc4JException exception : signatureValidationResult) {
1643                  System.out.println((isDDoc ? "        " : "   Error: ") + exception.toString());
1644                  signatureMap.put("signature"+signature.getId()+"ValidationException"+counter, exception.toString());
1645                 
1646                  //tmpValidationException.put("ValidationException", exception.toString());             
1647                  //jsonValidationExceptionArray.put(tmpValidationException);
1648                }
1649                //signatureMap.put("validationException", jsonValidationExceptionArray);
1650             
1651              if (isDDoc && isDDocTestSignature(signature)) {
1652                System.out.println("Signature " + signature.getId() + " is a test signature");
1653                signatureMap.put("isDDocTestSignature", Boolean.toString(true));
1654              }
1655                }
1656                else{
1657                       
1658                        System.out.println("Signature " + signature.getId() + " is valid");
1659                signatureMap.put("isValid", Boolean.toString(true));
1660                }
1661                signatureMap.put("signatureId", signature.getId());
1662        signatureMap.put("signatureProfile", signature.getProfile().toString());
1663        signatureMap.put("signatureMethod", signature.getSignatureMethod());
1664        /*
1665        if (signature.getSignerRoles().size() > 0){             
1666                signatureMap.put("signerRole1", signature.getSignerRoles().get(0));
1667                if (signature.getSignerRoles().size() == 2){
1668                        signatureMap.put("signerRole2", signature.getSignerRoles().get(1));
1669                }
1670        }
1671        */
1672        signatureMap.put("signatureCity", signature.getCity());
1673        signatureMap.put("signatureState", signature.getStateOrProvince());
1674        signatureMap.put("signaturePostalCode", signature.getPostalCode());
1675        signatureMap.put("signatureCountry", signature.getCountryName());
1676        signatureMap.put("signatureSigningTime", signature.getSigningTime().toString());
1677        //signatureMap.put("signaturePolicy", signature.getPolicy());
1678        //signatureMap.put("signatureOCSPProducedAtTimestamp", signature.getProducedAt().toString());
1679        //signatureMap.put("signaturePolicyURI", signature.getSignaturePolicyURI().toString());
1680        //signatureMap.put("signatureTimestampGenerationTime", signature.getTimeStampCreationTime().toString());
1681               
1682       
1683        X509Cert signerCertificate = signature.getSigningCertificate();
1684        signatureMap.put("signerCertificateSerial", signerCertificate.getSerial());
1685        signatureMap.put("signerCertificateSubjectName", signerCertificate.getSubjectName());
1686        signatureMap.put("signerCertificateIssuer", signerCertificate.issuerName());
1687        if (signerCertificate.isValid()){
1688                signatureMap.put("signerCertificateIsValid", Boolean.toString(true));
1689        }else{
1690                signatureMap.put("signerCertificateIsValid", Boolean.toString(false));
1691        }
1692       
1693       
1694       
1695                return signatureMap;
1696        }
1697       
1698       
1699        private static void verifyBdocContainer(Container container) {
1700            ValidationResult validationResult = container.validate();
1701
1702            List<DigiDoc4JException> exceptions = validationResult.getContainerErrors();
1703            boolean isDDoc = container.getDocumentType() == DocumentType.DDOC;
1704            for (DigiDoc4JException exception : exceptions) {
1705              if (isDDoc && isWarning(((DDocContainer) container).getFormat(), exception))
1706                System.out.println("    Warning: " + exception.toString());
1707              else
1708                System.out.println((isDDoc ? "  " : "   Error_: ") + exception.toString());
1709            }
1710
1711            if (isDDoc && (((ValidationResultForDDoc) validationResult).hasFatalErrors())) {
1712              return;
1713            }
1714
1715            List<Signature> signatures = container.getSignatures();
1716            if (signatures == null) {
1717              throw new SignatureNotFoundException();
1718            }
1719
1720            for (Signature signature : signatures) {
1721              List<DigiDoc4JException> signatureValidationResult = signature.validate();
1722              if (signatureValidationResult.size() == 0) {
1723                System.out.println("Signature " + signature.getId() + " is valid");
1724              } else {
1725                System.out.println("Signature " + signature.getId() + " is not valid");
1726                for (DigiDoc4JException exception : signatureValidationResult) {
1727                  System.out.println((isDDoc ? "        " : "   Error: ")
1728                      + exception.toString());
1729                }
1730              }
1731              if (isDDoc && isDDocTestSignature(signature)) {
1732                System.out.println("Signature " + signature.getId() + " is a test signature");
1733              }
1734            }
1735
1736            showWarnings(validationResult);
1737            verboseMessage(validationResult.getReport());
1738         }
1739
1740         private static void showWarnings(ValidationResult validationResult) {
1741                 if (bdocWarnings) {
1742                         for (DigiDoc4JException warning : validationResult.getWarnings()) {
1743                                 System.out.println("Warning: " + warning.toString());
1744                     }
1745                 }
1746         }
1747         
1748         /**
1749           * Checks is DigiDoc4JException predefined as warning for DDOC
1750           *
1751           * @param documentFormat format SignedDoc
1752           * @param exception      error to check
1753           * @return is this exception warning for DDOC utility program
1754           * @see SignedDoc
1755           */
1756          public static boolean isWarning(String documentFormat, DigiDoc4JException exception) {
1757            int errorCode = exception.getErrorCode();
1758            return (errorCode == DigiDocException.ERR_DF_INV_HASH_GOOD_ALT_HASH
1759                || errorCode == DigiDocException.ERR_OLD_VER
1760                || errorCode == DigiDocException.ERR_TEST_SIGNATURE
1761                || errorCode == DigiDocException.WARN_WEAK_DIGEST
1762                || (errorCode == DigiDocException.ERR_ISSUER_XMLNS && !documentFormat.equals(SignedDoc.FORMAT_SK_XML)));
1763          }
1764
1765          private static boolean isDDocTestSignature(Signature signature) {
1766                  CertValue certValue = ((DDocSignature) signature).getCertValueOfType(CertValue.CERTVAL_TYPE_SIGNER);
1767                  if (certValue != null) {
1768                          if (DigiDocGenFactory.isTestCard(certValue.getCert())) return true;
1769                  }
1770                  return false;
1771          }
1772         
1773          private static void verboseMessage(String message) {
1774                    if (bdocVerboseMode)
1775                      System.out.println(message);
1776          }
1777
1778       
1779       
1780        /**
1781         * Verifica si un archivo posee firmas electronicas y retorna informacion
1782         * de las mismas en un json
1783         * @param idFile
1784         * @return
1785         */
1786        @GET
1787        @Path("/verificar/{idFile}")
1788        //@Produces("application/json")
1789        @Produces("text/plain")
1790        public String verifyFile(@PathParam("idFile") String idFile) {
1791               
1792                String file = SERVER_UPLOAD_LOCATION_FOLDER + idFile;
1793       
1794                //return getMimeType(file);
1795               
1796                               
1797                File tmpFile = new File(file);
1798                String result = "";
1799
1800               
1801               
1802               
1803                if (tmpFile.exists()) {
1804                        result = "El archivo existe.";
1805                       
1806                        try {
1807                                PdfReader reader = new PdfReader(file);
1808                                AcroFields af = reader.getAcroFields();
1809                                ArrayList<String> names = af.getSignatureNames();
1810                                if (names.size() > 0) {
1811                                        result = "el archivo PDF posee "+ names.size() +" firma(s).\n";
1812                                       
1813                                        // sin esto explota: se debe agregar una implementacion del provider en tiempo de ejecucion
1814                                        //http://www.cs.berkeley.edu/~jonah/bc/org/bouncycastle/jce/provider/BouncyCastleProvider.html
1815                                        Security.addProvider(new BouncyCastleProvider());
1816                                       
1817                                        for (String name: names) {
1818                                                result = result +"Nombre de la firma: "+ name + "\n";
1819                                                System.out.println("Nombre de la firma: "+ name);
1820                                               
1821                                                PdfPKCS7 pk = af.verifySignature(name);
1822                                               
1823                                                Certificate[] pkc = pk.getCertificates();
1824                                               
1825                                                String tmpSignerName = pk.getSigningCertificate().getSubjectX500Principal().toString();
1826                                               
1827                                               
1828                                                result = result + "Sujeto del certificado firmante: " + tmpSignerName + "\n"; 
1829                                                //pk.getSigningCertificate().getSubjectX500Principal().getName() + "\n";
1830                                                System.out.println("Sujeto del certificado firmante: " + 
1831                                                                pk.getSigningCertificate().getSubjectX500Principal().toString());
1832                                                 
1833                                                Calendar cal = pk.getSignDate();
1834                                               
1835                                                SimpleDateFormat date_format = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");
1836                                               
1837                                                //result = result + "Fecha de la firma: " + cal.toString() + "\n";
1838                                                result = result + "Fecha de la firma: " + date_format.format(cal.getTime()) + "\n";
1839                                               
1840                                                /*
1841                                                System.out.println("año: "+ cal.get(Calendar.YEAR));
1842                                                System.out.println("mes: "+ (cal.get(Calendar.MONTH) + 1));
1843                                                System.out.println("día: "+ cal.get(Calendar.DAY_OF_MONTH));
1844                                                System.out.println("hora: "+ cal.get(Calendar.HOUR));
1845                                                System.out.println("minuto: "+ cal.get(Calendar.MINUTE));
1846                                                System.out.println("segundo: "+ cal.get(Calendar.SECOND));
1847                                                */
1848                                                //SimpleDateFormat date_format = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");
1849                                            System.out.println(date_format.format(cal.getTime()));
1850
1851                                        }
1852                                       
1853                                       
1854                                }else{
1855                                        result = "el archivo PDF no posee firmas";
1856                                }
1857                               
1858                               
1859                               
1860                        } catch (IOException e) {
1861                                // TODO Auto-generated catch block
1862                                e.printStackTrace();
1863                        }
1864                       
1865                       
1866                }else {
1867                        result = "El archivo NO existe.";
1868                }
1869               
1870               
1871                return result;
1872               
1873               
1874        }
1875       
1876        /**
1877         * Ejecuta el proceso de presign o preparacion de firma de documento pdf
1878         * @param presignPar
1879         * @param req objeto request para crear una sesion y mantener elementos del
1880         * pdf en la misma
1881         * @param resp
1882         */
1883        @POST
1884        @Path("/prepararfirmapdf")
1885        @Consumes(MediaType.APPLICATION_JSON)
1886        @Produces(MediaType.APPLICATION_JSON)
1887        //public Response presign(PresignParameters presignPar, @Context HttpServletRequest req) {
1888        public PresignHash presign(PresignParameters presignPar, @Context HttpServletRequest req) {
1889               
1890
1891                // cadena resultado de la funcion
1892                String result = "";
1893               
1894                PresignHash presignHash = new PresignHash();
1895               
1896               
1897                // cadena con el certificado
1898                String certHex = presignPar.getCertificate();
1899                System.out.println("certificado en Hex: " + certHex);
1900               
1901                // obtener el id del archivo
1902                String fileId = presignPar.getFileId();
1903                               
1904                try {
1905                        CertificateFactory factory = CertificateFactory.getInstance("X.509");
1906                        Certificate[] chain = new Certificate[1];
1907                       
1908                        InputStream in = new ByteArrayInputStream(hexStringToByteArray(certHex));
1909                        chain[0] = factory.generateCertificate(in);
1910                       
1911                        if (chain[0] == null) {
1912                                System.out.println("error chain[0] == null");
1913                        }else {
1914                               
1915                                System.out.println("se cargo el certificado correctamente");
1916                                System.out.println(chain[0].toString());
1917                        }
1918                       
1919                        //String pdf = SERVER_UPLOAD_LOCATION_FOLDER + "e27a6a90-f955-4191-8e54-580e316a999d";
1920                        String pdf = SERVER_UPLOAD_LOCATION_FOLDER + fileId;
1921                        System.out.println("archivo a firmar: " + pdf);
1922                       
1923                        PdfReader reader = new PdfReader(pdf);
1924                       
1925                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1926                       
1927                        //FileOutputStream baos = new FileOutputStream(pdf+"-signed.pdf");
1928                       
1929                        PdfStamper stamper = PdfStamper.createSignature(reader, baos, '\0');
1930                       
1931                        // crear la apariencia de la firma
1932                PdfSignatureAppearance sap = stamper.getSignatureAppearance();
1933                sap.setReason("Prueba de firma en dos partes");
1934                sap.setLocation("Merida, Venezuela");
1935                sap.setVisibleSignature(new Rectangle(36, 748, 144,780),1, "sig");
1936                sap.setCertificate(chain[0]);
1937               
1938                // crear la estructura de la firma
1939                PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
1940                dic.setReason(sap.getReason());
1941                dic.setLocation(sap.getLocation());
1942                dic.setContact(sap.getContact());
1943                dic.setDate(new PdfDate(sap.getSignDate()));
1944               
1945                sap.setCryptoDictionary(dic);
1946               
1947                HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer> ();
1948                exc.put(PdfName.CONTENTS, new Integer(8192 * 2 + 2));
1949                sap.preClose(exc);
1950               
1951                ExternalDigest externalDigest = new ExternalDigest() {
1952                        public MessageDigest getMessageDigest(String hashAlgorithm)
1953                        throws GeneralSecurityException {
1954                                return DigestAlgorithms.getMessageDigest(hashAlgorithm, null);
1955                        }
1956                };
1957                       
1958                       
1959                PdfPKCS7 sgn = new PdfPKCS7(null, chain, "SHA256", null, externalDigest, false);
1960               
1961                InputStream data = sap.getRangeStream();
1962               
1963                byte hash[] = DigestAlgorithms.digest(data, externalDigest.getMessageDigest("SHA256"));
1964               
1965                Calendar cal = Calendar.getInstance();
1966                byte sh[] = sgn.getAuthenticatedAttributeBytes(hash, cal, null, null, CryptoStandard.CMS);
1967               
1968                sh = DigestAlgorithms.digest(new ByteArrayInputStream(sh), externalDigest.getMessageDigest("SHA256"));
1969               
1970                System.out.println("sh length: "+ sh.length);
1971                       
1972                String hashToSign = byteArrayToHexString(sh);
1973                System.out.println("***************************************************************");
1974                System.out.println("HASH EN HEXADECIMAL:");
1975                System.out.println(hashToSign);
1976                System.out.println("length: " +hashToSign.length());   
1977                System.out.println("***************************************************************");
1978                       
1979                DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
1980                        Date date = new Date();
1981                        System.out.println(dateFormat.format(date));
1982                        //String d = dateFormat.format(date);
1983                       
1984                       
1985                        // almacenar los objetos necesarios para realizar el postsign en una sesion
1986                        HttpSession session = req.getSession(true);
1987                        session.setAttribute("hashToSign", hashToSign);
1988                       
1989                        session.setAttribute("stamper", stamper);
1990                        session.setAttribute("sgn", sgn);
1991                        session.setAttribute("hash", hash);
1992                        session.setAttribute("cal", cal);
1993                        session.setAttribute("sap", sap);
1994                        session.setAttribute("baos", baos);
1995                        session.setAttribute("fileId", fileId);
1996                       
1997                        // creacion del json
1998                        JSONObject jsonHash = new JSONObject();
1999                        jsonHash.put("hashToSign", hashToSign);
2000                       
2001                        result = jsonHash.toString();
2002                       
2003                        presignHash.setHash(hashToSign);
2004                               
2005                       
2006                } catch (CertificateException e1) {
2007                        // TODO Auto-generated catch block
2008                        e1.printStackTrace();
2009                } catch (IOException e) {
2010                        // TODO Auto-generated catch block
2011                        e.printStackTrace();
2012                } catch (DocumentException e) {
2013                        // TODO Auto-generated catch block
2014                        e.printStackTrace();
2015                } catch (InvalidKeyException e) {
2016                        // TODO Auto-generated catch block
2017                        e.printStackTrace();
2018                } catch (NoSuchProviderException e) {
2019                        // TODO Auto-generated catch block
2020                        e.printStackTrace();
2021                } catch (NoSuchAlgorithmException e) {
2022                        // TODO Auto-generated catch block
2023                        e.printStackTrace();
2024                } catch (GeneralSecurityException e) {
2025                        // TODO Auto-generated catch block
2026                        e.printStackTrace();
2027                }
2028               
2029                //return Response.status(200).entity(result).build();
2030                return presignHash;
2031                       
2032        }
2033       
2034       
2035        /**
2036         * Ejecuta el proceso de postsign o completacion de firma de documento pdf
2037         * @param postsignPar
2038         * @param req objeto request para crear una sesion y mantener elementos del
2039         * pdf en la misma
2040         * @param resp
2041         * @throws IOException
2042         */
2043        @POST
2044        @Path("/completarfirmapdf")
2045        @Consumes(MediaType.APPLICATION_JSON)
2046        @Produces(MediaType.APPLICATION_JSON)
2047        public Response postsign(PostsignParameters postsignPar, @Context HttpServletRequest req) throws IOException {
2048               
2049               
2050                // cadena resultado de la funcion
2051                String result = "";
2052                               
2053                // cadena con la firma
2054                String signature = postsignPar.getSignature();
2055                System.out.println("firma en Hex: " + signature);
2056               
2057                HttpSession session = req.getSession(false);
2058               
2059                String fileId = (String) session.getAttribute("fileId");
2060                System.out.println("fileId: " + fileId);
2061               
2062                PdfStamper stamper = (PdfStamper) session.getAttribute("stamper");
2063               
2064                PdfPKCS7 sgn = (PdfPKCS7) session.getAttribute("sgn");
2065               
2066                byte[] hash = (byte[]) session.getAttribute("hash");
2067               
2068                Calendar cal = (Calendar) session.getAttribute("cal");
2069               
2070                PdfSignatureAppearance sap = (PdfSignatureAppearance) session.getAttribute("sap");
2071               
2072                ByteArrayOutputStream os = (ByteArrayOutputStream) session.getAttribute("baos");
2073               
2074                if (sgn == null) {
2075                        System.out.println("sgn == null");
2076                }
2077                if (hash == null) {
2078                        System.out.println("hash == null");
2079                }
2080                if (cal == null) {
2081                        System.out.println("cal == null");
2082                }
2083                if (sap == null) {
2084                        System.out.println("sap == null");
2085                }
2086                if (os == null) {
2087                        System.out.println("os == null");
2088                }
2089               
2090               
2091               
2092                // convertir signature en bytes         
2093                byte[] signatureInBytes = hexStringToByteArray(signature);
2094                               
2095                // completar el proceso de firma
2096                sgn.setExternalDigest(signatureInBytes, null, RSA_DIGEST_ENCRYPTION_ALGORITHM);
2097                byte[] encodeSig = sgn.getEncodedPKCS7(hash, cal, null, null, null, CryptoStandard.CMS);
2098                byte[] paddedSig = new byte[8192];
2099                System.arraycopy(encodeSig, 0, paddedSig, 0, encodeSig.length);
2100                PdfDictionary dic2 = new PdfDictionary();
2101                dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));
2102                try {
2103                        sap.close(dic2);
2104                       
2105                        stamper.close();
2106                        System.out.println("stamper.close");
2107                       
2108                }catch(DocumentException e) {
2109                       
2110                        System.out.println("throw new IOException");
2111                        throw new IOException(e);
2112                       
2113                } catch (IOException e) {
2114                        // TODO Auto-generated catch block
2115                        System.out.println("IOException e");
2116                        e.printStackTrace();
2117                       
2118                }
2119               
2120                String signedPdf = SERVER_UPLOAD_LOCATION_FOLDER + fileId + "-signed.pdf";
2121               
2122                FileOutputStream signedFile = new FileOutputStream(signedPdf);
2123               
2124                os.writeTo(signedFile);
2125                os.flush();
2126               
2127               
2128               
2129                // en este punto el archivo pdf debe estar disponible en la ruta
2130                // SERVER_UPLOAD_LOCATION_FOLDER + fileId;
2131               
2132                // llamar a una funcion que permita descargar el archivo
2133               
2134                result = "Archivo firmado correctamente";
2135                System.out.println("Archivo firmado correctamente");
2136               
2137                return Response.status(200).entity(result).build();
2138        }
2139       
2140        /**
2141         * Ejecuta el proceso de presign o preparacion de firma de documento en formato BDOC
2142         *
2143         * @param presignPar
2144         * @param req
2145         * @return
2146         */
2147        @POST
2148        @Path("/bdoc/")
2149        @Consumes(MediaType.APPLICATION_JSON)
2150        @Produces(MediaType.APPLICATION_JSON)
2151        public PresignHash presignBdoc(PresignParameters presignPar, @Context HttpServletRequest req) {
2152               
2153                System.out.println("presignBdoc: ");
2154               
2155               
2156                String fileId;
2157                String certHex;
2158               
2159                CertificateFactory cf;
2160                X509Certificate signerCert;
2161               
2162                // cadena resultado de la funcion
2163                String result = "";
2164                               
2165                PresignHash presignHash = new PresignHash();
2166               
2167                SignedInfo signedInfo;
2168               
2169                fileId = presignPar.getFileId();
2170                String sourceFile = SERVER_UPLOAD_LOCATION_FOLDER + fileId;
2171               
2172                certHex = presignPar.getCertificate();
2173                System.out.println("certificado en Hex: " + certHex);
2174               
2175//              try {
2176                        /*             
2177                        Configuration configuration = new Configuration(Configuration.Mode.TEST);
2178                       
2179                        configuration.loadConfiguration("/home/aaraujo/desarrollo/2015/workspace-luna/JAXRS-Murachi/WebContent/WEB-INF/lib/digidoc4j.yaml");
2180                        configuration.setTslLocation("http://localhost/trusted-test-mp.xml");
2181                   
2182                        Container container = Container.create(configuration);
2183                    SignatureParameters signatureParameters = new SignatureParameters();
2184                    SignatureProductionPlace productionPlace = new SignatureProductionPlace();
2185                    productionPlace.setCity("Merida");
2186                    signatureParameters.setProductionPlace(productionPlace);
2187                    signatureParameters.setRoles(asList("Desarrollador"));
2188                    container.setSignatureParameters(signatureParameters);
2189                    container.setSignatureProfile(SignatureProfile.B_BES);
2190                    container.addDataFile("/tmp/215d6ef7-d639-4191-87a1-ef68a91b2b27", "text/plain");
2191                    container.sign(new PKCS12Signer("/tmp/JuanHilario.p12", "123456".toCharArray()));
2192//                  Container container = Container.open("util/faulty/bdoc21-bad-nonce-content.bdoc");
2193                    container.save("/tmp/signed.bdoc");
2194                    ValidationResult results = container.validate();
2195                    System.out.println(results.getReport());
2196                        */
2197
2198                       
2199                Security.addProvider(new BouncyCastleProvider());
2200                        System.setProperty("digidoc4j.mode", "TEST");
2201                       
2202                        Configuration configuration;
2203                        configuration = new Configuration(Configuration.Mode.TEST);
2204                        //configuration.loadConfiguration("/home/aaraujo/desarrollo/2015/workspace-luna/JAXRS-Murachi/WebContent/WEB-INF/lib/digidoc4j.yaml");
2205                       
2206                        //configuration.setTslLocation("https://tibisay.cenditel.gob.ve/murachi/raw-attachment/wiki/WikiStart/trusted-test-mp.xml");
2207                        configuration.setTslLocation("http://localhost/trusted-test-mp.xml");
2208                       
2209                        Container container;
2210                       
2211                        container = Container.create(Container.DocumentType.BDOC, configuration);
2212                       
2213                        SignatureParameters signatureParameters = new SignatureParameters();
2214                    SignatureProductionPlace productionPlace = new SignatureProductionPlace();
2215                    productionPlace.setCity("Merida");
2216                    signatureParameters.setProductionPlace(productionPlace);
2217                    signatureParameters.setRoles(asList("Desarrollador"));
2218                    container.setSignatureParameters(signatureParameters);
2219                    container.setSignatureProfile(SignatureProfile.B_BES);
2220                       
2221                        container.addDataFile(sourceFile, "text/plain");
2222                       
2223                        container.sign(new PKCS12Signer("/tmp/JuanHilario.p12", "123456".toCharArray()));
2224                    container.save("/tmp/signed.bdoc");
2225                    ValidationResult results = container.validate();
2226                    System.out.println(results.getReport());
2227                       
2228                        /*
2229                        cf = CertificateFactory.getInstance("X.509");
2230               
2231                        InputStream in = new ByteArrayInputStream(hexStringToByteArray(certHex));
2232                       
2233                        signerCert = (X509Certificate) cf.generateCertificate(in);
2234                       
2235                        signedInfo = container.prepareSigning(signerCert);
2236                       
2237                        String hashToSign = byteArrayToHexString(signedInfo.getDigest());
2238                        //System.out.println("presignBdoc - hash: " + byteArrayToHexString(signedInfo.getDigest()));
2239                        System.out.println("presignBdoc - hash: " + hashToSign);
2240                       
2241                       
2242                        //container.save("/tmp/containerTmp.bdoc");
2243                        serialize(container, "/tmp/containerSerialized");
2244                        */
2245                       
2246                        String hashToSign = "firma exitosa";
2247                       
2248                        // creacion del json
2249                        JSONObject jsonHash = new JSONObject();
2250                        jsonHash.put("hashToSign", hashToSign);
2251                                               
2252                        result = jsonHash.toString();
2253                                               
2254                        presignHash.setHash(hashToSign);
2255                       
2256                       
2257/*                     
2258                } catch (CertificateException e1) {
2259                        // TODO Auto-generated catch block
2260                        e1.printStackTrace();
2261                } catch (IOException e) {
2262                        // TODO Auto-generated catch block
2263                        e.printStackTrace();
2264                }
2265*/             
2266               
2267                return presignHash;
2268               
2269        }
2270       
2271       
2272        @GET
2273        @Path("/testbdoc/")
2274        public String testBdoc() {
2275               
2276                Security.addProvider(new BouncyCastleProvider());
2277               
2278                Configuration configuration = new Configuration(Configuration.Mode.TEST);
2279               
2280                configuration.loadConfiguration("/home/aaraujo/desarrollo/2015/workspace-luna/JAXRS-Murachi/WebContent/WEB-INF/lib/digidoc4j.yaml");
2281                configuration.setTslLocation("http://localhost/trusted-test-mp.xml");
2282               
2283            Container container = Container.create(configuration);
2284            SignatureParameters signatureParameters = new SignatureParameters();
2285            SignatureProductionPlace productionPlace = new SignatureProductionPlace();
2286            productionPlace.setCity("Merida");
2287            signatureParameters.setProductionPlace(productionPlace);
2288            signatureParameters.setRoles(asList("Desarrollador"));
2289            container.setSignatureParameters(signatureParameters);
2290            container.setSignatureProfile(SignatureProfile.B_BES);
2291            container.addDataFile("/tmp/01311213-5756-4707-a73d-6d42b09b26fd", "text/plain");
2292            container.sign(new PKCS12Signer("/tmp/JuanHilario.p12", "123456".toCharArray()));
2293//          Container container = Container.open("util/faulty/bdoc21-bad-nonce-content.bdoc");
2294            container.save("/tmp/signed.bdoc");
2295            ValidationResult result = container.validate();
2296            System.out.println(result.getReport());
2297               
2298                return "test";
2299        }
2300       
2301       
2302       
2303       
2304       
2305        /**
2306         * Prueba de ejecucion de programa desde consola. Incompleta
2307         * @return
2308         * @throws InterruptedException
2309         */
2310        @GET
2311        @Path("/ejecutar")
2312        @Produces("text/plain")
2313        public String executeProcess() throws InterruptedException {
2314               
2315               
2316                String line = "";
2317                OutputStream stdin = null;
2318                InputStream stderr = null;
2319                InputStream stdout = null;
2320               
2321                try {
2322                        System.out.print("...a crear el proceso");
2323                        Process process = Runtime.getRuntime().exec("/usr/java/jdk1.7.0_21/bin/java -jar /home/aaraujo/desarrollo/2015/servicioVerificacion/testsigningpdf/holamundopdf.jar /tmp/589750.pdf /tmp/simonDiaz.pem /tmp/firmadoconsola.pdf");
2324                        //Process process = Runtime.getRuntime().exec("ls -l");
2325                        stdin = process.getOutputStream();
2326                        stderr = process.getErrorStream();
2327                        stdout = process.getInputStream();
2328                       
2329                        InputStreamReader isr = new InputStreamReader(stdout);
2330                        BufferedReader buff = new BufferedReader (isr);
2331
2332                       
2333                        while((line = buff.readLine()) != null)
2334                                System.out.print(line+"\n");
2335                        int exitValue = process.waitFor();
2336                        if (exitValue != 0) {
2337                            System.out.println("Abnormal process termination");
2338                        }       
2339                       
2340                } catch (IOException e) {
2341                        // TODO Auto-generated catch block
2342                        e.printStackTrace();
2343                }
2344                System.out.print("...saliendo");
2345                return line;
2346        }
2347       
2348       
2349       
2350       
2351       
2352        /**
2353         *
2354         * @param certHex
2355         * @param httpHeaders
2356         * @param req
2357         * @param resp
2358         */
2359        @POST
2360        @Path("/presignOld")
2361        @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
2362        public void presignOld(
2363                        @FormParam("certHexInForm") String certHex,
2364                        @Context HttpHeaders httpHeaders,
2365                        @Context HttpServletRequest req,
2366                        @Context HttpServletResponse resp) {
2367               
2368
2369                String host = httpHeaders.getRequestHeader("host").get(0);
2370               
2371                String agent = httpHeaders.getRequestHeader("user-agent").get(0);
2372                String salida = "User agent :"+ agent +" from host : "+host;
2373                System.out.println(host);
2374                System.out.println(agent);
2375                System.out.println(salida);
2376               
2377                System.out.println("certificado en Hex: " + certHex);
2378               
2379                try {
2380                        CertificateFactory factory = CertificateFactory.getInstance("X.509");
2381                        Certificate[] chain = new Certificate[1];
2382                       
2383                        InputStream in = new ByteArrayInputStream(hexStringToByteArray(certHex));
2384                        chain[0] = factory.generateCertificate(in);
2385                       
2386                        if (chain[0] == null) {
2387                                System.out.println("error chain[0] == null");
2388                        }else {
2389                               
2390                                System.out.println("se cargo el certificado correctamente");
2391                                System.out.println(chain[0].toString());
2392                        }
2393                       
2394                        String pdf = SERVER_UPLOAD_LOCATION_FOLDER + "e27a6a90-f955-4191-8e54-580e316a999d";
2395                       
2396                        PdfReader reader = new PdfReader(pdf);
2397                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
2398                        PdfStamper stamper = PdfStamper.createSignature(reader, baos, '\0');
2399                       
2400                        // crear la apariencia de la firma
2401                PdfSignatureAppearance sap = stamper.getSignatureAppearance();
2402                sap.setReason("Prueba de firma en dos partes");
2403                sap.setLocation("Merida, Venezuela");
2404                sap.setVisibleSignature(new Rectangle(36, 748, 144,780),1, "sig");
2405                sap.setCertificate(chain[0]);
2406               
2407                // crear la estructura de la firma
2408                PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
2409                dic.setReason(sap.getReason());
2410                dic.setLocation(sap.getLocation());
2411                dic.setContact(sap.getContact());
2412                dic.setDate(new PdfDate(sap.getSignDate()));
2413               
2414                sap.setCryptoDictionary(dic);
2415               
2416                HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer> ();
2417                exc.put(PdfName.CONTENTS, new Integer(8192 * 2 + 2));
2418                sap.preClose(exc);
2419               
2420                ExternalDigest externalDigest = new ExternalDigest() {
2421                        public MessageDigest getMessageDigest(String hashAlgorithm)
2422                        throws GeneralSecurityException {
2423                                return DigestAlgorithms.getMessageDigest(hashAlgorithm, null);
2424                        }
2425                };
2426                       
2427                       
2428                PdfPKCS7 sgn = new PdfPKCS7(null, chain, "SHA256", null, externalDigest, false);
2429               
2430                InputStream data = sap.getRangeStream();
2431               
2432                byte hash[] = DigestAlgorithms.digest(data, externalDigest.getMessageDigest("SHA256"));
2433               
2434                Calendar cal = Calendar.getInstance();
2435                byte sh[] = sgn.getAuthenticatedAttributeBytes(hash, cal, null, null, CryptoStandard.CMS);
2436               
2437                sh = DigestAlgorithms.digest(new ByteArrayInputStream(sh), externalDigest.getMessageDigest("SHA256"));
2438               
2439                System.out.println("sh length: "+ sh.length);
2440                       
2441                String hashToSign = byteArrayToHexString(sh);
2442                System.out.println("***************************************************************");
2443                System.out.println("HASH EN HEXADECIMAL:");
2444                System.out.println(hashToSign);
2445                System.out.println("length: " +hashToSign.length());   
2446                System.out.println("***************************************************************");
2447                       
2448                DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
2449                        Date date = new Date();
2450                        System.out.println(dateFormat.format(date));
2451                        String d = dateFormat.format(date);
2452                       
2453                       
2454                        // almacenar los objetos necesarios para realizar el postsign en una sesion
2455                        HttpSession session = req.getSession(true);
2456                        session.setAttribute("hashToSign", hashToSign);
2457                       
2458                        session.setAttribute("sgn", sgn);
2459                        session.setAttribute("hash", hash);
2460                        session.setAttribute("cal", cal);
2461                        session.setAttribute("sap", sap);
2462                        session.setAttribute("baos", baos);
2463                       
2464               
2465                       
2466                        resp.sendRedirect("http://localhost/murachi2.html");
2467                       
2468                       
2469                } catch (CertificateException e1) {
2470                        // TODO Auto-generated catch block
2471                        e1.printStackTrace();
2472                } catch (IOException e) {
2473                        // TODO Auto-generated catch block
2474                        e.printStackTrace();
2475                } catch (DocumentException e) {
2476                        // TODO Auto-generated catch block
2477                        e.printStackTrace();
2478                } catch (InvalidKeyException e) {
2479                        // TODO Auto-generated catch block
2480                        e.printStackTrace();
2481                } catch (NoSuchProviderException e) {
2482                        // TODO Auto-generated catch block
2483                        e.printStackTrace();
2484                } catch (NoSuchAlgorithmException e) {
2485                        // TODO Auto-generated catch block
2486                        e.printStackTrace();
2487                } catch (GeneralSecurityException e) {
2488                        // TODO Auto-generated catch block
2489                        e.printStackTrace();
2490                }
2491               
2492               
2493       
2494        }
2495       
2496       
2497        @POST
2498        @Path("/postsign")
2499        public String postsignOld(@Context HttpServletRequest req,
2500                        @Context HttpServletResponse resp) {
2501               
2502                System.out.println("...postsign()...");
2503               
2504                HttpSession session = req.getSession(false);
2505                Object att = session.getAttribute("hashToSign");
2506                               
2507       
2508                String output = "atributo leido de la sesion: " + att.toString();
2509               
2510               
2511                return output;
2512                //return Response.status(200).entity(output).build();
2513        }
2514       
2515       
2516        @GET
2517        @Path("/retornajson")
2518        @Produces(MediaType.APPLICATION_JSON)
2519        public PresignHash retornajson(@Context HttpServletRequest req) {
2520               
2521               
2522               
2523                PresignHash h = new PresignHash();
2524                h.setHash("ESTO SERIA UN HASH");
2525               
2526                System.out.println("...retornajson..."+ h.getHash());
2527               
2528                return h;
2529               
2530        }
2531       
2532        @POST
2533        @Path("/enviarjson")
2534        @Consumes(MediaType.APPLICATION_JSON)
2535        @Produces(MediaType.APPLICATION_JSON)
2536        public PresignHash recibejson( PresignParameters par) {
2537               
2538                String fileId = par.getFileId();
2539                System.out.println("...fileId recibido..."+ fileId);
2540               
2541                String cert = par.getCertificate();
2542                System.out.println("...certificate recibido..."+ cert);
2543               
2544                PresignHash h = new PresignHash();
2545                h.setHash("DEBES FIRMAR ESTO");
2546               
2547                System.out.println("...recibejson..."+ h.getHash());
2548               
2549                return h;
2550               
2551        }
2552       
2553       
2554       
2555       
2556        /**
2557         * Retorna el mimeType del archivo pasado como argumento
2558         * @param absolutFilePath ruta absoluta del archivo
2559         * @return mimeType del archivo pasado como argumento
2560         */
2561        public String getMimeType(String absolutFilePath) {
2562                               
2563                String result = "";             
2564                java.nio.file.Path source = Paths.get(absolutFilePath);
2565                try {
2566                        result = Files.probeContentType(source);                       
2567                        System.out.println(result);
2568                } catch (IOException e) {
2569                        // TODO Auto-generated catch block
2570                        e.printStackTrace();
2571                }               
2572                return result;           
2573        }
2574       
2575        /**
2576         * Convierte una cadena Hexadecimal en un arreglo de bytes
2577         * @param s cadena hexadecimal
2578         * @return arreglo de bytes resultantes de la conversion de la cadena hexadecimal
2579         */
2580        public static byte[] hexStringToByteArray(String s) {
2581            byte[] b = new byte[s.length() / 2];
2582            for (int i = 0; i < b.length; i++) {
2583              int index = i * 2;
2584              int v = Integer.parseInt(s.substring(index, index + 2), 16);
2585              b[i] = (byte) v;
2586            }
2587            return b;
2588          }
2589       
2590        /**
2591           * Converts a byte array into a hex string.
2592           * @param byteArray the byte array source
2593           * @return a hex string representing the byte array
2594           */
2595          public static String byteArrayToHexString(final byte[] byteArray) {
2596              if (byteArray == null) {
2597                  return "";
2598              }
2599              return byteArrayToHexString(byteArray, 0, byteArray.length);
2600          }
2601         
2602          public static String byteArrayToHexString(final byte[] byteArray, int startPos, int length) {
2603              if (byteArray == null) {
2604                  return "";
2605              }
2606              if(byteArray.length < startPos+length){
2607                  throw new IllegalArgumentException("startPos("+startPos+")+length("+length+") > byteArray.length("+byteArray.length+")");
2608              }
2609//            int readBytes = byteArray.length;
2610              StringBuilder hexData = new StringBuilder();
2611              int onebyte;
2612              for (int i = 0; i < length; i++) {
2613                  onebyte = ((0x000000ff & byteArray[startPos+i]) | 0xffffff00);
2614                  hexData.append(Integer.toHexString(onebyte).substring(6));
2615              }
2616              return hexData.toString();
2617          }
2618       
2619          /**
2620           * Serializa el contenedor BDOC pasado como argumento
2621           * @param container Contenedor que se desea serializar
2622           * @param filePath ruta absoluta al archivo serializado
2623           * @throws IOException
2624           */
2625          private static void serialize(Container container, String filePath) throws IOException {
2626                  FileOutputStream fileOut = new FileOutputStream(filePath+".bin");
2627                  ObjectOutputStream out = new ObjectOutputStream(fileOut);
2628                  out.writeObject(container);
2629                  out.flush();
2630                  out.close();
2631                  fileOut.close();
2632          }
2633         
2634          /**
2635           * Deserializa el contenedor BDOC pasado como argumento
2636           * @param filePath ruta absoluta al contenedor que se desea deserializar
2637           * @return contenedor deserializado
2638           * @throws IOException
2639           * @throws ClassNotFoundException
2640           */
2641          private static Container deserializer(String filePath) throws IOException, ClassNotFoundException {
2642                  //FileInputStream fileIn = new FileInputStream("container.bin");
2643                  FileInputStream fileIn = new FileInputStream(filePath);
2644                  ObjectInputStream in = new ObjectInputStream(fileIn);
2645                  Container container = (Container) in.readObject();
2646                  in.close();
2647                  fileIn.close();
2648                  return container;
2649          }
2650         
2651}
Note: See TracBrowser for help on using the repository browser.