source: portal_2019/pruebas_web_crypto_api/testingDigitalSignatureWebCryptography.html @ 0d48c0c

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

pruebas de firma, desde el cliente usuando libreria javascript y otras pruebas usando el servivio de Murachi

  • Property mode set to 100644
File size: 21.7 KB
Line 
1<!--  Prueba: Este código contiene dos pruebas
21.- Verificar y firmar el Hash usando la claves asimétricas generadas por la librería javascript Cryptography API Supported y usando los algoritmo de firma RSASSA-PKCS1-v1₅ y RSA-PSS
3
42.- Verificar y firmar el Hash usando la información gestionada del archivo .p12 por la librería javascript Forge y exportando dicha información a Cryptography API Supported, se probo usando los algoritmo de firma RSASSA-PKCS1-v1₅ y RSA-PSS
5
6para ver los resultados debe activar la consola web del navegador
7-->
8
9<!DOCTYPE html>
10<html lang="es">
11<head>
12  <meta charset="UTF-8">
13  <title>Firma electrónica con Web Crypto API</title>
14<body>
15
16  <main>
17    <form enctype="multipart/form-data" method="post" id="firmar" name="SignFormat">
18      <h1>Firmar un PDF con un pkcs12 y Murachí REST</h1>
19      <p>Seleccione el archivo que va a firmar electrónicamente</p>
20      <input id="file-sign" class="file" type="file" data-min-file-count="1" name="upload" accept=".pdf" >
21      <input id="inputCertificadoPKCS12" type="file" name="inputinputCertificadoPKCS12" />
22      <button type="button" name="buttonsubmit3" id="buttonsubmit3">Firmar</button>
23    </form>
24    <section id="resultados">
25      <br>
26      <div id="seccion1"></div>
27      <br>
28      <div id="seccion2"></div>
29      <br>
30      <div id="seccion3"></div>
31      <br>
32      <div id="seccion4"></div>
33    </section>
34  </main>
35
36  <!-- Forge 0.7.0 -->
37  <script src="./forge.min.js"></script>
38  <script src="./jquery.min.js"></script>
39  <script>
40
41  // Variables globales
42  var
43      reader = new FileReader(),
44      certificado = "",
45      password = "123456",
46      inputCertificadoPKCS12 = document.querySelector("#inputCertificadoPKCS12"),
47      buttonsubmit3 = document.querySelector("#buttonsubmit3"),
48      decodificado = null,
49      certP12bag = null,
50      certificadoHexadecimal = null,
51      privateKeyRSASSAPKCS1v1_5 = null,
52      privateKeyRSAPSS = null,
53      publicKeyRSAPSS = null,
54      publicKeyRSASSAPKCS1v1_5 = null,
55      importarLlave = null;
56
57  /* ----- Funciones ----- */
58    // Función para convertir el certificado de ArrayBuffer a String
59    function convertirArrayBufferAString ( buffer ) {
60      let _certificadoEnString = '';     
61      let _bytes = new Uint8Array( buffer );
62      let _longitudDeCadena = _bytes.byteLength;
63      for (let i = 0; i < _longitudDeCadena; i++) {
64        _certificadoEnString += String.fromCharCode( _bytes[ i ] );
65      }
66      return _certificadoEnString;
67    }
68
69    // Función para convertir el certificado de String a ArrayBuffer
70    function convertirStringArrayBuffer ( data ) {
71      let _arrayBuffer = new ArrayBuffer ( data.length );
72      let writer = new Uint8Array ( _arrayBuffer );
73      for (let i = 0, len = data.length; i < len; i++) {
74        writer[i] = data.charCodeAt ( i );
75      }
76      return _arrayBuffer;
77    }
78
79    // Función para decodificar el .p12 convertido en string
80    function decodificarPKCS12 ( stringBase64 ) {
81      let pkcs12Asn1 = forge.asn1.fromDer( stringBase64 );
82      let pkcs12 = forge.pkcs12.pkcs12FromAsn1( pkcs12Asn1, false, password );
83      return pkcs12;
84    }
85
86     // Función para buscar la llave publica del PKCS#12
87    function buscarLlavePublica ( pkcs12 ) {
88      for ( var sci = 0; sci < pkcs12.safeContents.length; ++sci ) {
89        var safeContents = pkcs12.safeContents[ sci ];
90
91        for ( var sbi = 0; sbi < safeContents.safeBags.length; ++sbi ) {
92          var safeBag = safeContents.safeBags[sbi];
93          if (safeBag.cert != undefined) {
94            console.log("antes de llamar safeBag.cert.publicKey")
95            var publicKey = safeBag.cert.publicKey;
96            console.log("**** publickey ****");
97            console.log(publicKey);
98            console.log("**** publickey ****");
99            var publickeyPem = forge.pki.publicKeyToPem(publicKey);
100            console.log("**** publickeyPem ****");
101            console.log(publickeyPem);
102            console.log("**** publickeyPem ****");
103            var publickeyBytesHex = forge.util.bytesToHex(publickeyPem);
104            console.log("**** publickeyBytesHex ****");
105            console.log(publickeyBytesHex);
106            console.log("**** publickeyBytesHex ****");
107            return publicKey;
108            }
109        }
110      }
111    }
112
113    // Función para buscar la llave privada del PKCS#12
114    function buscarLlavePrivada ( pkcs12 ) {
115      for ( var sci = 0; sci < pkcs12.safeContents.length; ++sci ) {
116        var safeContents = pkcs12.safeContents[ sci ];
117
118        for ( var sbi = 0; sbi < safeContents.safeBags.length; ++sbi ) {
119          var safeBag = safeContents.safeBags[sbi];
120          if ( safeBag.type === forge.pki.oids.keyBag ) {
121            privateKey = safeBag.key;
122          } else if ( safeBag.type === forge.pki.oids.pkcs8ShroudedKeyBag ) {
123            privateKey = safeBag.key;
124          }
125        }
126      }
127      return privateKey;
128    }
129    // Función para convertir la llave publica a PKCS#8
130    function publicKeyToPkcs8 ( publicKeyP12 ) {
131      var rsaPublicKey = forge.pki.publicKeyToAsn1(publicKeyP12);
132      //var publicKeyInfo = forge.pki.wrapRsaPrivateKey(rsaPublicKey);
133      var publicKeyInfoDer = forge.asn1.toDer(rsaPublicKey).getBytes();
134      var publicKeyInfoDerBuff = convertirStringArrayBuffer(publicKeyInfoDer);
135      return publicKeyInfoDerBuff;
136    }
137
138    // Función para convertir la llave privada a PKCS#8
139    function privateKeyToPkcs8 ( privateKeyP12 ) {
140        console.log("function privateKeyToPkcs8 ( privateKeyP12 ) {");
141        console.log(privateKeyP12);
142        console.log("function privateKeyToPkcs8 ( privateKeyP12 ) {");
143      var rsaPrivateKey = forge.pki.privateKeyToAsn1(privateKeyP12);
144      var privateKeyInfo = forge.pki.wrapRsaPrivateKey(rsaPrivateKey);
145      var privateKeyInfoDer = forge.asn1.toDer(privateKeyInfo).getBytes();
146      var privateKeyInfoDerBuff = convertirStringArrayBuffer(privateKeyInfoDer);
147      return privateKeyInfoDerBuff;
148    }
149
150    // Función para convertir un Array Buffer a Hexadecimal
151    function buf2hex ( buffer ) {
152      return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
153    }
154
155    // Función para importar la llave privada with RSASSA-PKCS1-v1_5
156   
157    function importarLlavePrivada ( llavePrivada ) {
158      var qweasd = crypto.subtle.importKey(
159        "pkcs8", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
160        llavePrivada,
161        {   //these are the algorithm options
162          name: "RSASSA-PKCS1-v1_5",
163          hash: { name: "SHA-256" }, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
164        },
165        false, //whether the key is extractable (i.e. can be used in exportKey)
166        ["sign"] //"verify" for public key import, "sign" for private key imports
167      ).then(function(publicKey){
168        //returns a publicKey (or privateKey if you are importing a private key)
169        console.log(publicKey);
170        privateKeyRSASSAPKCS1v1_5 = publicKey;
171      })
172      .catch(function(err){
173        console.error(err);
174      });
175    }
176
177   /*
178    // Función para importar la llave privada with RSA-PSS
179    function importarLlavePrivada ( llavePrivada ) {
180        console.log("Clave privada");
181        console.log(llavePrivada);
182        console.log("Clave privada");
183      var qweasd = crypto.subtle.importKey(
184        "pkcs8", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
185        llavePrivada,
186        {   //these are the algorithm options
187          name: "RSA-PSS",
188          hash: { name: "SHA-256" }, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
189        },
190        false, //whether the key is extractable (i.e. can be used in exportKey)
191        ["sign"] //"verify" for public key import, "sign" for private key imports
192      ).then(function(publicKey){
193        //returns a publicKey (or privateKey if you are importing a private key)
194        console.log(publicKey);
195        privateKeyRSAPSS = publicKey;
196      })
197      .catch(function(err){
198        console.error(err);
199      });
200    }
201*/
202/*
203// Función para importar la llave publica with RSA-PSS
204    function importarLlavePublica ( llavePublica ) {
205        console.log("importarLlavePublica llavePublica");
206        console.log(llavePublica);
207        console.log("importarLlavePublica llavePublica");
208      var qweasd = crypto.subtle.importKey(
209        "spki", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
210        llavePublica,
211        {   //these are the algorithm options
212          name: "RSA-PSS",
213          hash: { name: "SHA-256" }, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
214        },
215        false, //whether the key is extractable (i.e. can be used in exportKey)
216        ["verify"] //"verify" for public key import, "sign" for private key imports
217      ).then(function(publicKey){
218        //returns a publicKey (or privateKey if you are importing a private key)}
219        console.log("llavePublica importada");
220        console.log(publicKey);
221        console.log("llavePublica importada");
222        publicKeyRSAPSS = publicKey;
223      })
224      .catch(function(err){
225        console.error(err);
226      });
227    }
228*/
229// Función para importar la llave publica with RSASSA-PKCS1-v1_5
230    function importarLlavePublica ( llavePublica ) {
231        console.log("importarLlavePublica llavePublica");
232        console.log(llavePublica);
233        console.log("importarLlavePublica llavePublica");
234      var qweasd = crypto.subtle.importKey(
235        "spki", //can be "jwk" (public or private), "spki" (public only), or "pkcs8" (private only)
236        llavePublica,
237        {   //these are the algorithm options
238          name: "RSASSA-PKCS1-v1_5",
239          hash: { name: "SHA-256" }, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
240        },
241        false, //whether the key is extractable (i.e. can be used in exportKey)
242        ["verify"] //"verify" for public key import, "sign" for private key imports
243      ).then(function(publicKey){
244        //returns a publicKey (or privateKey if you are importing a private key)}
245        console.log("llavePublica importada");
246        console.log(publicKey);
247        console.log("llavePublica importada");
248        publicKeyRSASSAPKCS1v1_5 = publicKey;
249      })
250      .catch(function(err){
251        console.error(err);
252      });
253    }
254    // Función para convertir el certificado .p12 en hexadecimal
255    function convertirPKCS12aHexadecimal ( pkcs12 ) {
256      for ( var sci = 0; sci < pkcs12.safeContents.length; ++sci ) {
257        var safeContents = pkcs12.safeContents[sci];
258        for(var sbi = 0; sbi < safeContents.safeBags.length; ++sbi) {
259          var safeBag = safeContents.safeBags[sbi];
260          if(safeBag.type === forge.pki.oids.keyBag) {
261            privateKey = safeBag.key;
262          } else if(safeBag.type === forge.pki.oids.pkcs8ShroudedKeyBag) {
263            privateKey = safeBag.key;
264          } else if(safeBag.type === forge.pki.oids.certBag) {
265            if(certP12bag == null) {
266              certP12bag = safeBag.cert;
267              var certpem = forge.pki.certificateToPem(certP12bag);
268              var certBytesHex = forge.util.bytesToHex(certpem);
269            }
270          } 
271        }
272      }
273      return certBytesHex;
274    }
275    // Función para leer el .p12 luego de cargarlo
276    function leerCertificadoPKCS12 () {
277      let archivoAdjuntado = this.files[0];
278
279      reader.onload = function(e) {
280        var
281          contents = e.target.result,
282          pkcs12Der = convertirArrayBufferAString( contents ),
283          pkcs12B64 = forge.util.encode64( pkcs12Der );
284        decodificado = decodificarPKCS12( pkcs12Der );
285        certificadoHexadecimal = convertirPKCS12aHexadecimal(decodificado);
286        var
287          llavePrivada = buscarLlavePrivada(decodificado),
288          llavePublica = buscarLlavePublica(decodificado),
289          convertirAPKCS8 = privateKeyToPkcs8(llavePrivada),
290          convertirAPuKCS8 = publicKeyToPkcs8(llavePublica);
291
292          importarLlavePrivada(convertirAPKCS8);
293          importarLlavePublica(convertirAPuKCS8);
294      }
295      reader.readAsArrayBuffer(archivoAdjuntado);
296    }
297
298  /* ----- Eventos ----- */
299    // 1. Al adjuntar el archivo .p12 se ejecuta la función que lo lee y se extrae su información
300    inputCertificadoPKCS12.addEventListener('change', leerCertificadoPKCS12, false);
301  /* ----- Eventos ----- */
302
303 
304function convertStringToArrayBufferView(str)
305{
306    var bytes = new Uint8Array(str.length);
307    for (var iii = 0; iii < str.length; iii++)
308    {
309        bytes[iii] = str.charCodeAt(iii);
310    }
311
312    return bytes;
313} 
314
315var crypto = window.crypto || window.msCrypto;
316
317var promise_key = null;
318
319var private_key_object = null;
320var public_key_object = null;
321var data = "7a42eea172776c7a6de6d57aa9958d9654410934f5cfbf483b6135a24543f51c";
322var encrypted_hash = null;
323var encrypt_promise = null;
324var signature = null;
325var decrypt_promise = null;
326
327// Usando el algoritmo  RSA-PSS
328/*
329if(crypto.subtle)
330{
331    console.log("Antes del alert");
332    alert("Cryptography API Supported");
333
334    promise_key = crypto.subtle.generateKey({name: "RSA-PSS", modulusLength: 2048, publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: {name: "SHA-256"}}, false, ["sign", "verify"]);
335
336    promise_key.then(function(key){
337        private_key_object = key.privateKey;
338        console.log("****** public_key_object ******");
339        console.log(public_key_object);
340        console.log("****** public_key_object ******");
341        public_key_object = key.publicKey;
342        console.log("****.. antes del encrypt_data()..****");
343        encrypt_data();
344    });
345
346    promise_key.catch = function(e){
347
348        console.log(e.message);
349    }
350   
351   
352}
353else
354{
355    alert("Cryptography API not Supported");
356}
357
358function encrypt_data()
359{
360    console.log("function encrypt_data()");
361    console.log("*** inicio private_key_object ***");
362    console.log(private_key_object);
363    console.log("*** fin private_key_object ***");
364    console.log("*** inicio privatekey ***");
365    console.log(privateKeyRSAPSS);
366    console.log("*** fin privatekey ***");
367
368    if(privateKeyRSAPSS==null) {
369        encrypt_promise = crypto.subtle.sign({name: "RSA-PSS", saltLength: 128, }, private_key_object, convertStringToArrayBufferView(data));
370
371        encrypt_promise.then(
372            function(result_signature){
373                signature = result_signature; //signature generated
374                console.log("**************************************");
375                console.log(signature);
376                console.log("**************************************");
377                console.log("****.. antes del decrypt_data()..****");
378                decrypt_data();
379            },
380            function(e){
381                console.log(e);
382            }
383        );
384    }
385    else {
386
387        encrypt_promise = crypto.subtle.sign({name: "RSA-PSS", saltLength: 128, }, privateKeyRSAPSS, convertStringToArrayBufferView(data));
388
389        encrypt_promise.then(
390            function(result_signature){
391                signature = result_signature; //signature generated
392                console.log("**************************************");
393                console.log(signature);
394                console.log("**************************************");
395                console.log("****.. antes del decrypt_data()..****");
396                decrypt_data();
397            },
398            function(e){
399                console.log(e);
400            }
401        );
402    }
403}
404
405function decrypt_data()
406{
407    if(publicKeyRSAPSS == null) {
408        console.log("function decrypt_data()");
409        console.log("****** public_key_object decrypt_data() ******");
410        console.log(public_key_object);
411        console.log("****** public_key_object decrypt_data() ******");
412        decrypt_promise = crypto.subtle.verify({name: "RSA-PSS", saltLength: 128, }, public_key_object, signature, convertStringToArrayBufferView(data));
413
414            decrypt_promise.then(
415                function(result){
416                    console.log(result);//true or false
417                },
418            function(e){
419                console.log(e.message);
420            }
421        );
422    }
423    else {
424        console.log("function decrypt_data()");
425        console.log("****** publicKeyRSAPSS decrypt_data() ******");
426        console.log(publicKeyRSAPSS);
427        console.log("****** publicKeyRSAPSS decrypt_data() ******");
428        decrypt_promise = crypto.subtle.verify({name: "RSA-PSS", saltLength: 128, }, publicKeyRSAPSS, signature, convertStringToArrayBufferView(data));
429        decrypt_promise.then(
430            function(result){
431                console.log(result);//true or false
432            },
433            function(e){
434                console.log(e.message);
435            }
436        );
437
438    }
439
440}
441
442*/
443// Usando el algoritmo  RSASSA-PKCS1-v1_5
444if(crypto.subtle)
445{
446    console.log("Antes del alert");
447    alert("Cryptography API Supported... Prueba 1 usando las claves generadas");
448
449    promise_key = crypto.subtle.generateKey({name: "RSASSA-PKCS1-v1_5", modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: {name: "SHA-256"}}, false, ["sign", "verify"]);
450
451    promise_key.then(function(key){
452        private_key_object = key.privateKey;
453        public_key_object = key.publicKey;
454        console.log("****.. antes del encrypt_data()..****");
455        encrypt_data();
456    });
457
458    promise_key.catch = function(e){
459
460        console.log(e.message);
461    }
462}
463else
464{
465    alert("Cryptography API not Supported");
466}
467
468//Función para realizar la firma del hash usando las claves asimetricas generdas por Cryptography y por la clave privada gestionado del archivo .p12
469//
470function encrypt_data()
471{
472    console.log("function encrypt_data()");
473    //encrypt_promise = crypto.subtle.sign({name: "RSASSA-PKCS1-v1_5"}, private_key_object, convertStringToArrayBufferView(data));
474    console.log("*** inicio private_key_object ***");
475    console.log(private_key_object);
476    console.log("*** fin private_key_object ***");
477    console.log("*** inicio privatekey ***");
478    console.log(privateKeyRSASSAPKCS1v1_5);
479    console.log("*** fin privatekey ***");
480    document.getElementById("seccion1").innerHTML = data;
481    //evalua si la clave privada extraída del .p12 es nula para firma usando la clave asimetrica generada con Cryptography API clave privada = private_key_object
482    if(privateKeyRSASSAPKCS1v1_5 == null) {
483        encrypt_promise = crypto.subtle.sign({name: "RSASSA-PKCS1-v1_5"}, private_key_object, convertStringToArrayBufferView(data));
484
485        encrypt_promise.then(
486            function(result_signature){
487                signature = result_signature; //signature generated
488                console.log("**************************************");
489                console.log(signature);
490                console.log("**************************************");
491                console.log("****.. antes del decrypt_data()..****");
492                document.getElementById("seccion2").innerHTML = signature; 
493                decrypt_data(); //Llamado para verificaar la firma (hash firmado)
494            },
495            function(e){
496                console.log(e);
497            }
498        );
499       
500    } else { //la clave privada del extraída .p12 no es null por lo tanto se realiza la firma usando la clave del archivo .p12
501         encrypt_promise = crypto.subtle.sign({name: "RSASSA-PKCS1-v1_5"}, privateKeyRSASSAPKCS1v1_5, convertStringToArrayBufferView(data));
502
503        encrypt_promise.then(
504            function(result_signature){
505                signature = result_signature; //signature generated
506                console.log("**************************************");
507                console.log(signature);
508                console.log("**************************************");
509                console.log("****.. antes del decrypt_data()..****");
510                document.getElementById("seccion2").innerHTML = signature; 
511                decrypt_data(); //Llamado para verificaar la firma (hash firmado)
512            },
513            function(e){
514                console.log(e);
515            }
516        ); 
517     
518    }
519}
520
521//Función para realizar la verificación de la firma del hash usando las claves asimetricas generdas por Cryptography y por la clave publica gestionado del archivo .p12
522//
523function decrypt_data()
524{
525  console.log("function decrypt_data()");
526  //evalua si la clave publica del .p12 esta vacia para realziar la verificación usando la clave asimetrica generada con Cryptography API clave privada = private_key_object
527  if(publicKeyRSASSAPKCS1v1_5 == null) { 
528     
529    console.log("****** public_key_object decrypt_data() ******");
530    console.log(public_key_object);
531    console.log("****** public_key_object decrypt_data() ******");
532    decrypt_promise = crypto.subtle.verify({name: "RSASSA-PKCS1-v1_5"}, public_key_object, signature, convertStringToArrayBufferView(data));
533
534    decrypt_promise.then(
535      function(result){
536        console.log(result);//true or false
537        document.getElementById("seccion3").innerHTML = result; 
538      },
539      function(e){
540        console.log(e.message);
541      }
542    );
543  document.getElementById("seccion4").innerHTML = "Para la segunda prueba carga el pdf y el archivo .p12 usando el formulaio"; 
544  } else { //evalua si la clave publica del .p12 no esta vacia para realizar la verificación usando la clave pública extraída del .p12
545   
546    console.log("****** publicKeyRSASSAPKCS1v1_5 decrypt_data() ******");
547    console.log(publicKeyRSASSAPKCS1v1_5);
548    console.log("****** publicKeyRSASSAPKCS1v1_5 decrypt_data() ******");
549
550    decrypt_promise = crypto.subtle.verify({name: "RSASSA-PKCS1-v1_5"}, publicKeyRSASSAPKCS1v1_5, signature, convertStringToArrayBufferView(data));
551
552    decrypt_promise.then(
553      function(result){
554        console.log(result);//true or false
555        document.getElementById("seccion3").innerHTML = result; 
556      },
557      function(e){
558        console.log(e.message);
559      }
560    ); 
561   document.getElementById("seccion4").innerHTML = "";   
562  }
563}
564
565  buttonsubmit3.addEventListener('click', function() {
566      encrypt_data();
567    }, true);
568
569</script>
570</body>
571</html>
Note: See TracBrowser for help on using the repository browser.