cryptopals

Matasano's cryptopals challenges (cryptopals.com).
git clone git://git.jtobin.io/cryptopals.git
Log | Files | Refs | README | LICENSE

hmac.js (1664B)


      1 const sha1 = require('js-sha1')
      2 const crypto = require('crypto')
      3 
      4 // hmac utils /////////////////////////////////////////////////////////////////
      5 
      6 const buf2hex = buf =>
      7   Buffer.from(buf).toString('hex')
      8 
      9 const hex2buf = hex =>
     10   Buffer.from(hex, 'hex')
     11 
     12 const bufs2buf = (a, b) =>
     13   Buffer.concat([a, b])
     14 
     15 // returns hex
     16 const gen_key = () => {
     17   const arr = crypto.getRandomValues(new Uint8Array(16))
     18   return buf2hex(arr)
     19 }
     20 
     21 // expects hex, returns hex
     22 const pad = (hex, siz) =>
     23   hex.padEnd(siz, '0')
     24 
     25 // expects buffer, returns hex
     26 const compute_sized_key = (key, hash, siz) =>
     27     key.length > siz ?
     28     hash(key) :
     29     key.length < siz ?
     30     pad(buf2hex(key), siz * 2) : // bytes, not length
     31     buf2hex(key)
     32 
     33 // expects hex, returns hex
     34 const hmac_sha1 = (k, m) => {
     35   const bk = hex2buf(k)
     36   const bm = hex2buf(m)
     37 
     38   const sized_key = hex2buf(compute_sized_key(bk, sha1, 64))
     39 
     40   const okey_pad = sized_key.map(x => x ^ 0x5c)
     41   const ikey_pad = sized_key.map(x => x ^ 0x36)
     42 
     43   const inner  = bufs2buf(ikey_pad, bm)
     44   const hinner = hex2buf(sha1(inner))
     45   const outer  = bufs2buf(okey_pad, hinner)
     46 
     47   return sha1(outer)
     48 }
     49 
     50 const verify_hmac_sha1 = (key, msg, mac) =>
     51   hmac_sha1(key, msg) == mac
     52 
     53 async function insecure_compare(key, msg, mac, del) {
     54   const bcal = Buffer.from(hmac_sha1(key, msg), 'hex')
     55   const bmac = Buffer.from(mac, 'hex')
     56 
     57   const idxs = Array(bcal.length).fill().map((el, idx) => idx)
     58 
     59   for await (const idx of idxs) {
     60     if (bcal[idx] != bmac[idx]) {
     61       return false
     62     }
     63     await new Promise(r => setTimeout(r, del))
     64   }
     65 
     66   return true
     67 }
     68 
     69 module.exports = {
     70   gen_key,
     71   hmac_sha1,
     72   verify_hmac_sha1,
     73   insecure_compare
     74 }