-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhmac-sha3.js
57 lines (55 loc) · 2.42 KB
/
hmac-sha3.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/* eslint-disable camelcase */
'use strict'
/*
HMAC(K, M) = H( (K' ^ opad) || H((K' ^ ipad) || m ) )
H为密码散列函数(如MD5或SHA-1)
K为密钥(secret key)
m是要认证的消息
K'是从原始密钥K导出的另一个密钥(如果K短于散列函数的输入块大小,则向右填充(Padding)零;如果比该块大小更长,则对K进行散列)
|| 代表串接
⊕ 代表异或(XOR)
opad 是外部填充(0x5c5c5c…5c5c,一段十六进制常量)
ipad 是内部填充(0x363636…3636,一段十六进制常量)
*/
const sha224 = require('./qKeccak.js').sha3_224
const sha256 = require('./qKeccak.js').sha3_256
const sha384 = require('./qKeccak.js').sha3_384
const sha512 = require('./qKeccak.js').sha3_512
const funcs = { sha224, sha256, sha384, sha512 }
const BLOCKSIZE = { 224: 144, 256: 136, 384: 104, 512: 72 }
const padUnit = String.fromCharCode(0)
const ipadUnit = String.fromCharCode(0x36)
const opadUnit = String.fromCharCode(0x5c)
const bufferXOR = (a, b) => {
if (a.length !== b.length) throw new Error('Cannot handle input with different length')
let res = ''
for (let i = 0, length = a.length; i < length; i++) {
res += String.fromCharCode(a.charCodeAt(i) ^ b.charCodeAt(i))
}
return res
}
const hexBytesToString = (hexStr) => { // convert string of hex numbers to a string of chars (eg '616263' -> 'abc').
return hexStr === '' ? '' : hexStr.match(/.{2}/g).map(byte => String.fromCharCode(parseInt(byte, 16))).join('')
}
function hmac (type = 224) {
if (!funcs[`sha${type}`]) throw new Error('Invalid function type')
let hash = funcs[`sha${type}`]
return (key = '', message = '') => {
message = unescape(encodeURIComponent(message + ''))
let encodeKey = unescape(encodeURIComponent(key + ''))
key = encodeKey.length > BLOCKSIZE[type] ? hexBytesToString(hash(key)) : encodeKey
key += [...Array.from({ length: BLOCKSIZE[type] - key.length }).fill(padUnit)].join('')
let ipad = [...Array.from({ length: BLOCKSIZE[type] }).fill(ipadUnit)].join('')
let opad = [...Array.from({ length: BLOCKSIZE[type] }).fill(opadUnit)].join('')
let i_key_pad = bufferXOR(ipad, key)
let o_key_pad = bufferXOR(opad, key)
let digest = hexBytesToString(hash(i_key_pad + message, { format: 'utf-8' }))
return hash(o_key_pad + digest, { format: 'utf-8' })
}
}
module.exports = {
hmac224: hmac(224),
hmac256: hmac(256),
hmac384: hmac(384),
hmac512: hmac(512)
}