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 }