source: portal_2019/pruebas_web_crypto_api/firmandoConMurachi.sign.html @ d1c1139

desarrollo
Last change on this file since d1c1139 was d1c1139, checked in by Laura Colina <lcolina@…>, 5 years ago

Ordenando repositorio para el portal, agregando carpetas de pruebas

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