source: murachi/murachi/src/main/java/ve/gob/cenditel/murachi/MurachiRESTWS.java @ 7c45d87

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

Cambios menores en cadenas que identifican a elementos estáticos que se utilizan en varias funciones.

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