source: murachi/murachi/src/main/java/ve/gob/cenditel/murachi/MurachiRESTWS.java @ 4ac0cf4

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

Modificación en archivo de configuración para que la ejecución del servicio sea a través de HTTPS.

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