source: murachi/murachi/src/main/java/ve/gob/cenditel/murachi/MurachiRESTWS.java @ 9ab4eef

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

Agregada función para descargar un archivo desde el servidor.

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