-
Notifications
You must be signed in to change notification settings - Fork 1
/
kdf.js
114 lines (93 loc) · 2.67 KB
/
kdf.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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// const { randomBytes } = require('./random-bytes')
const isBuffer = require('is-buffer')
/* eslint-disable camelcase */
const {
crypto_kdf_CONTEXTBYTES,
crypto_kdf_BYTES_MAX,
crypto_kdf_BYTES_MIN,
crypto_kdf_PRIMITIVE,
crypto_kdf_KEYBYTES,
crypto_kdf_derive_from_key,
crypto_kdf_keygen,
} = require('./sodium')
/**
* Generates a master key.
*
* @public
* @param {?(Buffer)} [key]
* @returns {Buffer}
* @throws TypeError
*/
function keygen(key) {
if (key && false === isBuffer(key)) {
throw new TypeError('kdf.keygen: Expecting key to be a buffer.')
}
if (undefined === key) {
key = Buffer.allocUnsafe(crypto_kdf_KEYBYTES)
}
if (crypto_kdf_KEYBYTES !== key.length) {
throw new TypeError(`kdf.keygen: Invalid key length: ${key.length}`)
}
crypto_kdf_keygen(key)
return key
}
/**
* Derives a subkey using the master key and context.
*
* @public
* @param {?(Buffer)} [subkey]
* @param {?(Number)} [subkeyId]
* @param {Buffer} ctx
* @param {Buffer} key
* @return {Buffer}
* @throws TypeError
*/
function derive(subkey, subkeyId, ctx, key) {
// Handle subkey
if (subkey && false === isBuffer(subkey)) {
throw new TypeError('kdf.derive: Expecting subkey to be a buffer.')
}
if (undefined === subkey) {
subkey = Buffer.allocUnsafe(crypto_kdf_KEYBYTES)
}
if (crypto_kdf_BYTES_MIN > subkey.length || crypto_kdf_BYTES_MAX < subkey.length) {
throw new TypeError(`kdf.derive: Invalid subkey length: ${subkey.length}`)
}
// Handle subkey ID
if (subkeyId && 'number' !== typeof subkeyId) {
throw new TypeError('kdf.derive: Expecting subkeyId to be a number.')
}
if (undefined === subkeyId) {
subkeyId = 0
}
if (subkeyId < 0 || subkeyId > 2**64 - 1) {
throw new TypeError('kdf.derive: Expecting subkeyId to be between 0 and (2^64)-1.')
}
// Handle context
if (ctx && false === isBuffer(ctx)) {
throw new TypeError('kdf.derive: Expecting context to be a buffer.')
}
if (undefined === ctx) {
throw new TypeError('kdf.derive: Expecting context to be defined.')
}
if (crypto_kdf_CONTEXTBYTES !== ctx.length) {
throw new TypeError(`kdf.derive: Invalid context length: ${ctx.length}`)
}
// Handle master key
if (key && false === isBuffer(key)) {
throw new TypeError('kdf.derive: Expecting master key to be a buffer.')
}
if (undefined === key) {
throw new TypeError('kdf.derive: Expecting master key to be defined.')
}
if (crypto_kdf_KEYBYTES !== key.length) {
throw new TypeError(`kdf.derive: Invalid master key length: ${key.length}`)
}
// derive subkey
crypto_kdf_derive_from_key(subkey, subkeyId, ctx, key)
return subkey
}
module.exports = {
derive,
keygen,
}