-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.js
More file actions
47 lines (36 loc) · 1.67 KB
/
Copy pathindex.js
File metadata and controls
47 lines (36 loc) · 1.67 KB
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
const crypto = require('crypto')
function isArrayBufferOrTypedArray (input) {
return (typeof input.byteLength === 'number' && typeof input.slice === 'function')
}
function hmac (hash, key, input) {
return crypto.createHmac(hash, key).update(input).digest()
}
const hashLengths = {
sha256: 32,
sha384: 48,
sha512: 64
}
module.exports = function hkdf (salt, input, info, keylen, digest) {
if (!isArrayBufferOrTypedArray(salt)) throw new TypeError('Expected "salt" to be an ArrayBuffer, Uint8Array or Buffer')
if (!isArrayBufferOrTypedArray(input)) throw new TypeError('Expected "input" to be an ArrayBuffer, Uint8Array or Buffer')
if (!isArrayBufferOrTypedArray(info)) throw new TypeError('Expected "info" to be an ArrayBuffer, Uint8Array or Buffer')
if (digest !== 'SHA-256' && digest !== 'SHA-384' && digest !== 'SHA-512') throw new TypeError('Expected "digest" to be one of "SHA-256", "SHA-384" or "SHA-512"')
salt = Buffer.from(salt)
input = Buffer.from(input)
info = Buffer.from(info)
digest = digest.replace('SHA-', 'sha')
const hashLength = hashLengths[digest]
const iterations = Math.ceil(keylen / hashLength)
if (iterations > 0xff) {
throw new RangeError('Key length "keylen" exceeds maximum key length for this "digest" parameter')
}
return Promise.resolve().then(function () {
const prk = hmac(digest, salt, input)
const parts = [Buffer.from('')]
for (let i = 0; i < iterations; i++) {
parts.push(hmac(digest, prk, Buffer.concat([parts[i], info, Buffer.from([i + 1])])))
}
const result = Buffer.concat(parts).slice(0, keylen)
return result.buffer.slice(result.byteOffset, result.byteOffset + result.byteLength)
})
}