-
Notifications
You must be signed in to change notification settings - Fork 3
/
sharedSecretGenerator.js
84 lines (73 loc) · 2.25 KB
/
sharedSecretGenerator.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
const crypto = require('crypto')
const base64 = require('./base64')
const { create: createKSUID } = require('./ksuid')
const funcs = {
/**
* Generate a random shared secret.
*
* @param {number} size - The size of the shared secret.
* @returns {Promise<Buffer>} The shared secret.
*/
generateSharedSecret: async (size = 32) => {
return new Promise((resolve, reject) => {
let masterKey
let iv
crypto.randomBytes(size, (err, buf) => {
if (err) {
return reject(err)
}
masterKey = buf
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(new Error(`Could not generate an IV: ${err}.`))
}
iv = buf
crypto.scrypt(masterKey, iv, size, (err, secret) => {
if (err) {
return reject(new Error(`Could not generate a secret: ${err}.`))
}
return resolve(secret)
})
})
})
})
},
/**
* Convert a shared secret to a JSON Web Key.
*
* @param {Buffer|string} secret - The shared secret to package in a JWK.
* @param {string} [keyId - The key identifier to assign.
* @returns {Promise<Object>} The JSON Web Key.
*/
convertSharedSecretToJwk: async (secret, keyId = undefined) => {
return new Promise(async resolve => {
const sharedSecret = Buffer.isBuffer(secret) ? secret : Buffer.from(secret)
const kid = keyId !== undefined ? keyId : await createKSUID()
const encoded = await base64.urlEncode(sharedSecret)
const jsonWebKey = {
k: encoded,
kty: 'oct',
kid: kid
}
return resolve(jsonWebKey)
})
},
/**
* Generate a shared secret and return it as a JSON Web Key.
*
* @param {number} size - The size of the key.
* @returns {Promise<Object>} The shared secret.
*/
generateSharedSecretAsJwk: async (size = 32) => {
return new Promise(async (resolve, reject) => {
try {
const sharedSecret = await funcs.generateSharedSecret(size)
const jwk = await funcs.convertSharedSecretToJwk(sharedSecret)
return resolve(jwk)
} catch (e) {
return reject(new Error(`Unable to generate shared secret: ${e}.`))
}
})
}
}
module.exports = funcs