source: portal_2019/pruebas_web_crypto_api/FirmandoConMurachiModificado.html @ 520961f

desarrollo
Last change on this file since 520961f was 520961f, checked in by pbuitrago@…>, 5 years ago

se agrego documentación al código

  • Property mode set to 100644
File size: 13.0 KB
Line 
1<!--  Prueba: Simulando el proceso de firma de murachí en el cual dentro de la función que gestiona el certificado se realiza el llamado al servicio a murachi enviando el certificado y luego la firma del hash recibido para terminar de completar la firma del archivo pdf todo realizado dentro del llamado a función getCertificate hicimos lo mismo en esta prueba pero gestionando la información requerida para la firma en el archivo .p12
2-->
3<!DOCTYPE html>
4<html lang="es">
5<head>
6  <meta charset="UTF-8">
7  <title>Firma electrónica con Web Crypto API</title>
8<body>
9
10  <main>
11    <form enctype="multipart/form-data" method="post" id="firmar" name="SignFormat">
12      <h1>Firmar un PDF con un pkcs12 y Murachí REST</h1>
13      <p>Seleccione el archivo que va a firmar electrónicamente</p>
14      <input id="file-sign" class="file" type="file" data-min-file-count="1" name="upload" accept=".pdf" >
15      <input id="inputCertificadoPKCS12" type="file" name="inputinputCertificadoPKCS12" accept=".p12"/>
16      <!-- <button type="button" name="buttonsubmit3" id="buttonsubmit3">Firmar</button> -->
17    </form>
18    <section id="resultados">
19      <div id="seccion1"></div>
20      <div id="seccion2"></div>
21      <div id="seccion3"></div>
22      <div id="seccion4"></div>
23    </section>
24  </main>
25
26  <!-- Forge 0.7.0 -->
27  <script src="./forge.min.js"></script>
28  <script src="./jquery.min.js"></script>
29  <script>
30
31  // Variables globales
32  var
33      reader = new FileReader(),
34      certificado = "",
35      password = "123456",
36      inputCertificadoPKCS12 = document.querySelector("#inputCertificadoPKCS12"),
37      fileP12 = null,
38      buttonsubmit3 = document.querySelector("#buttonsubmit3"),
39      decodificado = null,
40      certP12bag = null,
41      certificadoHexadecimal = null,
42      privateKey = null,
43      importarLlave = null;
44
45
46
47  /* ----- Funciones ----- */
48    // Función para convertir el certificado de ArrayBuffer a String
49    function convertirArrayBufferAString ( buffer ) {
50      let _certificadoEnString = '';     
51      let _bytes = new Uint8Array( buffer );
52      let _longitudDeCadena = _bytes.byteLength;
53      for (let i = 0; i < _longitudDeCadena; i++) {
54        _certificadoEnString += String.fromCharCode( _bytes[ i ] );
55      }
56      return _certificadoEnString;
57    }
58
59    // Función para convertir el certificado de String a ArrayBuffer
60    function convertirStringArrayBuffer ( data ) {
61      let _arrayBuffer = new ArrayBuffer ( data.length );
62      let writer = new Uint8Array ( _arrayBuffer );
63      for (let i = 0, len = data.length; i < len; i++) {
64        writer[i] = data.charCodeAt ( i );
65      }
66      return _arrayBuffer;
67    }
68
69    // Función para decodificar el .p12 convertido en string
70    function decodificarPKCS12 ( stringBase64 ) {
71      let pkcs12Asn1 = forge.asn1.fromDer( stringBase64 );
72      let pkcs12 = forge.pkcs12.pkcs12FromAsn1( pkcs12Asn1, false, password );
73      return pkcs12;
74    }
75
76    // Función para buscar la llave privada del PKCS#12
77    function buscarLlavePrivada ( pkcs12 ) {
78      for ( var sci = 0; sci < pkcs12.safeContents.length; ++sci ) {
79        var safeContents = pkcs12.safeContents[ sci ];
80
81        for ( var sbi = 0; sbi < safeContents.safeBags.length; ++sbi ) {
82          var safeBag = safeContents.safeBags[sbi];
83
84          if ( safeBag.type === forge.pki.oids.keyBag ) {
85            privateKey = safeBag.key;
86          } else if ( safeBag.type === forge.pki.oids.pkcs8ShroudedKeyBag ) {
87            privateKey = safeBag.key;
88          }
89        }
90      }
91      return privateKey;
92    }
93
94    // Función para convertir la llave privada a PKCS#8
95    function privateKeyToPkcs8 ( privateKeyP12 ) {
96      var rsaPrivateKey = forge.pki.privateKeyToAsn1(privateKeyP12);
97      var privateKeyInfo = forge.pki.wrapRsaPrivateKey(rsaPrivateKey);
98      var privateKeyInfoDer = forge.asn1.toDer(privateKeyInfo).getBytes();
99      var privateKeyInfoDerBuff = convertirStringArrayBuffer(privateKeyInfoDer);
100      return privateKeyInfoDerBuff;
101    }
102
103    // Función para convertir un Array Buffer a Hexadecimal
104    function buf2hex ( buffer ) {
105      return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
106    }
107
108    // Función para importar la llave privada
109    function importarLlavePrivada ( llavePrivada ) {
110      var qweasd = crypto.subtle.importKey(
111        "pkcs8", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
112        llavePrivada,
113        {   //these are the algorithm options
114          name: "RSASSA-PKCS1-v1_5",
115          hash: { name: "SHA-256" }, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
116        },
117        false, //whether the key is extractable (i.e. can be used in exportKey)
118        ["sign"] //"verify" for public key import, "sign" for private key imports
119      ).then(function(publicKey){
120        //returns a publicKey (or privateKey if you are importing a private key)
121        console.log(publicKey);
122        privateKey = publicKey;
123      })
124      .catch(function(err){
125        console.error(err);
126      });
127    }
128
129    // Función para convertir el certificado .p12 en hexadecimal
130    function convertirPKCS12aHexadecimal ( pkcs12 ) {
131      for ( var sci = 0; sci < pkcs12.safeContents.length; ++sci ) {
132        var safeContents = pkcs12.safeContents[sci];
133        for(var sbi = 0; sbi < safeContents.safeBags.length; ++sbi) {
134          var safeBag = safeContents.safeBags[sbi];
135          if(safeBag.type === forge.pki.oids.keyBag) {
136            privateKey = safeBag.key;
137          } else if(safeBag.type === forge.pki.oids.pkcs8ShroudedKeyBag) {
138            privateKey = safeBag.key;
139          } else if(safeBag.type === forge.pki.oids.certBag) {
140            if(certP12bag == null) {
141              certP12bag = safeBag.cert;
142              var certpem = forge.pki.certificateToPem(certP12bag);
143              console.log("*****************certpem");
144              console.log(certpem);
145              console.log("*****************certpem");
146              var certBytesHex = forge.util.bytesToHex(certpem);
147              console.log("*****************certBytesHex");
148              console.log(certBytesHex);
149              console.log("*****************certBytesHex");
150            }
151          } 
152        }
153      }
154      return certBytesHex;
155    }
156
157    function SignFileAll() {
158      // Paso 1. Obtener el pdf
159        console.log("function SignFileAll");
160        fileP12 = this.files[0];
161        console.log(fileP12);
162        var archivoPDF = document.getElementById("file-sign");
163        var list = archivoPDF.files;
164        var data = new FormData();
165        data.append('upload', $("#file-sign")[0].files[0]);
166        // Paso 2. Primera consulta - Se sube el certificado a Murachí
167        $.ajax({
168                url: "https://murachi.cenditel.gob.ve/Murachi/0.1/archivos",
169                type: "POST",
170                dataType: "JSON",
171                data: data,
172                cache: false,
173                contentType: false,
174                processData: false,
175                xhrFields: { withCredentials: true },
176                headers: { "Authorization":"Basic YWRtaW46YWRtaW4=" },
177                // Paso 2.1. Se evalua la respuesta de la consulta a Murachí
178                success: function(response) {
179                        var responseString = JSON.stringify(response);
180                        document.getElementById("seccion1").innerHTML = responseString;
181                        var fileId = response.fileId.toString();
182                        //Sección para conseguir el certificado
183                        console.log("Antes del leerCertificadoPKCS12");
184                        //leerCertificadoPKCS12();
185                        let archivoAdjuntado = fileP12;
186                        //Función que gestiona la información requerida en el archivo .p12
187                        reader.onload = function(e) {
188                                console.log("Entro a reader.onload = function(e)");
189                                var
190                                contents = e.target.result,
191                                pkcs12Der = convertirArrayBufferAString( contents ),
192                                pkcs12B64 = forge.util.encode64( pkcs12Der );
193                                decodificado = decodificarPKCS12( pkcs12Der );
194                                certificadoHexadecimal = convertirPKCS12aHexadecimal(decodificado);
195                                var
196                                llavePrivada = buscarLlavePrivada(decodificado),
197                                convertirAPKCS8 = privateKeyToPkcs8(llavePrivada);
198                                importarLlavePrivada(convertirAPKCS8);
199
200                                if(certificadoHexadecimal != null) 
201                                {
202                                // -- CERTIFICADO
203                                var cert = certificadoHexadecimal;
204                                // console.log(cert);
205                                // -- Parámetros para la segunda consulta
206                                parameters = JSON.stringify({
207                                        "fileId": fileId,
208                                        "certificate": cert,
209                                        "reason": "Certificado",
210                                        "location": "CENDITEL",
211                                        "contact": "582746574336",
212                                        "signatureVisible": "true"
213                                });
214                                // Paso 3. Segunda consulta
215                                $.ajax({
216                                        type: 'POST',
217                                        contentType: 'application/json',
218                                        url: "https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/pdfs",
219                                        dataType: "json",
220                                        data: parameters,
221                                        xhrFields: { withCredentials: true },
222                                        headers: { "Authorization":"Basic YWRtaW46YWRtaW4=" },
223                                        // Paso 3.1. Se evalua la respuesta de la consulta a Murachí
224                                        success: function(data, textStatus, jqXHR) {
225                                                // data - Objeto obtenido de Murachí que contienen el hash
226                                                // Estado de la consulta -- success
227                                                // Objeto de donde se saca el hash para firmar en pasos posteriores
228                                                var responseString = JSON.stringify(data);
229                                                document.getElementById("seccion2").innerHTML = responseString;
230                                                // Paso 4. Se obtiene el HASH para el firmado   
231                                                hash = data['hash'];
232                                                var digestToSign = hash;
233                                                var digestToSignBuf = convertirStringArrayBuffer(digestToSign);
234                                                var signatureDure = null;
235                                                crypto.subtle.sign(
236                                                { name: "RSASSA-PKCS1-v1_5"},
237                                                privateKey,
238                                                digestToSignBuf 
239                                        )
240                                        .then ( function ( signature ) {
241                                                importarLlave = signature;
242                                                console.log(signature);
243                                                var firmaEnArray8 = new Uint8Array(signature);
244                                                importarLlave = buf2hex(firmaEnArray8);
245                                                console.log("sign()" + importarLlave);
246                                                $.ajax({
247                                                        url:"https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/pdfs/resenas",
248                                                        type: 'POST',
249                                                        dataType: 'json',
250                                                        data: JSON.stringify({'signature':importarLlave}),
251                                                        contentType: 'application/json',
252                                                        headers: {"Authorization":"Basic YWRtaW46YWRtaW4="},
253                                                        xhrFields: { withCredentials: true },
254                                                        success: function(data, textStatus, jqXHR){
255                                                                var responseString = JSON.stringify(data);
256                                                                document.getElementById("seccion3").innerHTML = responseString;
257                                                                alert('Archivo firmado correctamente: ' + data['signedFileId']);
258                                                                document.getElementById("seccion4").innerHTML = "Descargar archivo firmado: https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/descargas/" + data['signedFileId'];
259                                                        }, //respuesta del ajax 3 sin error
260                                                        error: function(jqXHR, textStatus, errorThrown){
261                                                                console.log(jqXHR);
262                                                                console.log(textStatus);
263                                                                console.log(errorThrown);
264                                                                alert('error en pdfs/resenas: ' + textStatus);
265                                                                $("#respuesta").html("error en pdfs/resenas: " + textStatus);
266                                                        } // repuesta del ajax 3 con error
267                                                }); //ajax 3
268                                        })
269                                        .catch(function(err){
270                                                console.error(err);
271                                        });
272                                        } // ajax 2
273                                }); // Paso 3. Segunda consulta
274                                } //sin de la pregunta si el tiene certificado
275                                else {  //fin de la condición si tiene certificado
276                                console.log("No se pudo obtener el certificado");
277                                }
278                        } //función del llamado a buscar el certificado
279                        console.log("Luego de la linea de reader.onload = function(e)");
280                        reader.readAsArrayBuffer(archivoAdjuntado);     
281                        } //ajax 1
282        }); //cierre del llamado ajax 1
283    } //Cierre de la función
284
285  /* ----- Eventos ----- */
286    // 1. Al adjuntar el archivo .p12 se ejecuta la función que lo lee y se extrae su información
287    //inputCertificadoPKCS12.addEventListener('change', leerCertificadoPKCS12, false);
288    inputCertificadoPKCS12.addEventListener('change', SignFileAll, false);
289  /* ----- Eventos ----- */
290  </script>
291</body>
292</html>
Note: See TracBrowser for help on using the repository browser.