Outils pour utilisateurs

Outils du site


notes:webcrypto

Ceci est une ancienne révision du document !


WebCrypto

Cette page résume des opérations similaires entre WebCrypto et d'autres outils

RSA-PSS pour signature

Conversion de clés

OpenSSL

Pour importer une clé en JavaScript, le format PKCS#8 est préféré

$ openssl pkcs8 -topk8 -nocrypt -in rsakey.pem -out rsakey.pkcs8 # converti pkcs8

JavaScript

Convertir une clé PKCS#8 format PEM vers un ArrayBuffer utilisable avec crypto.subtle.importKey

  function b64Decode (text) {
     let s = atob(text.trim().replace(/\r?\n|\r/g, ''))
     const buffer = new ArrayBuffer(s.length)
     const bview = new Uint8Array(buffer)
     for (let i = 0; i < s.length; i++) {
       bview[i] = s.charCodeAt(i)
     }
     return buffer
   }
 
   function readPEM (text) {
     const pemRegex = /^-----BEGIN (?:PRIVATE|PUBLIC) KEY-----$([a-zA-Z0-9\/\+=\r\n]*)^-----END (?:PRIVATE|PUBLIC) KEY-----$/mg
     let m = pemRegex.exec(text)
     if (m && m.length > 1) {
       return b64Decode(m[1])
     }
     return undefined
   }

Convertir un ArrayBuffer obtenu avec crypto.subtle.exportKey (avec une mise en forme similaire à OpenSSL)

   function b64Encode (buffer) {
     let txt = ''
     let b64 = btoa(String.fromCharCode.apply(null, new Uint8Array(buffer)))
     for (let i = 0; i < (Math.ceil(b64.length / 64)); i++) {
       txt += b64.substring(i * 64, (i + 1) * 64) + "\n"
     }
     return txt
   }
 
   function writePEM (buffer, priv = false) {
     let txt = `-----BEGIN ${priv ? 'PRIVATE' : 'PUBLIC'} KEY-----` + "\n"
     txt += b64Encode(buffer)
     return txt + `-----END ${priv ? 'PRIVATE' : 'PUBLIC'} KEY-----`
   }

Génération de clés

OpenSSL

OpenSSL génère, avec genrsa, une clé au format pkcs#1 codé avec PEM

$ openssl genrsa -F4 2048 > rsakey.pem # clé privée 2048bits pkcs1
$ openssl rsa -in rsakey.pem -pubout > rsapub.pem # clé publique

JavaScript

   function genKeyPair() {
     return new Promise((resolve, reject) => {
       /* same as openssl genrsa -F4 2048 */
       crypto.subtle.generateKey(
         {
           name: 'RSA-PSS',
           hash: 'SHA-256',
           modulusLength: 2048,
           publicExponent: new Uint8Array([1, 0, 1])
         },
         true,
         ['sign', 'verify']).then((key) => {
           Promise.all([
             crypto.subtle.exportKey('pkcs8', key.privateKey),
             crypto.subtle.exportKey('spki', key.publicKey)
           ]).then((keys) => {
             resolve([writePEM(keys[0], true), writePEM(keys[1], false)])
           })
         })
     })
   }

Création de signature

OpenSSL

echo -n "Texte à signer" | openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:0 -sign fromjs.key  -out - - | base64

JavaScript

   function signFromPKCS8 (text, privkey) {
     return new Promise((resolve, reject) => {
       const key = readPEM(privkey)
       if (key) {
         crypto.subtle.importKey(
           'pkcs8',
           key,
           {
             name: 'RSA-PSS',
             hash: { name: 'SHA-256' }
           },
           false,
           [ 'sign' ]
         ).then((key) => {
           crypto.subtle.sign(
             {
               name: 'RSA-PSS', saltLength: 0
             },
             key,
             (new TextEncoder).encode(text)
           ).then((signed) => {
             resolve(b64Encode(signed))
           })
         })
       }
     })
   }

Vérification de signature

OpenSSL

$ base64 -d < fromjs.sig - > fromjs.bin.sig
$ echo -n "Texte à signer" | openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:0 -verify fromjs.pem -signature fromjs.bin.sig -

JavaScript

   function verifyFromPKCS8 (text, signature, pubkey) {
     return new Promise((resolve, reject) => {
       const cert = readPEM(pubkey)
       if (cert) {
         crypto.subtle.importKey(
           'spki',
           cert,
           {
             name: 'RSA-PSS',
             hash: { name: 'SHA-256' }
           },
           false,
           [ 'verify' ]
         ).then((key) => {
           crypto.subtle.verify(
             {
               name: 'RSA-PSS', saltLength: 0
             },
             key,
             b64Decode(signature),
             (new TextEncoder).encode(text)
           ).then((verified) => {
             resolve(verified)
           })
         })
       }
     })
   }
notes/webcrypto.1582733863.txt.gz · Dernière modification: 2020/02/26 17:17 de etienne