Spaces:
Sleeping
Sleeping
import cluster from "node:cluster"; | |
import { createHmac, randomBytes } from "node:crypto"; | |
const generateSalt = () => { | |
if (cluster.isPrimary) | |
return randomBytes(64); | |
return null; | |
} | |
let rateSalt = generateSalt(); | |
let streamSalt = generateSalt(); | |
export const syncSecrets = () => { | |
return new Promise((resolve, reject) => { | |
if (cluster.isPrimary) { | |
let remaining = Object.values(cluster.workers).length; | |
const handleReady = (worker, m) => { | |
if (m.ready) | |
worker.send({ rateSalt, streamSalt }); | |
if (!--remaining) | |
resolve(); | |
} | |
for (const worker of Object.values(cluster.workers)) { | |
worker.once( | |
'message', | |
(m) => handleReady(worker, m) | |
); | |
} | |
} else if (cluster.isWorker) { | |
if (rateSalt || streamSalt) | |
return reject(); | |
process.send({ ready: true }); | |
process.once('message', (message) => { | |
if (rateSalt || streamSalt) | |
return reject(); | |
if (message.rateSalt && message.streamSalt) { | |
streamSalt = Buffer.from(message.streamSalt); | |
rateSalt = Buffer.from(message.rateSalt); | |
resolve(); | |
} | |
}); | |
} else reject(); | |
}); | |
} | |
export const hashHmac = (value, type) => { | |
let salt; | |
if (type === 'rate') | |
salt = rateSalt; | |
else if (type === 'stream') | |
salt = streamSalt; | |
else | |
throw "unknown salt"; | |
return createHmac("sha256", salt).update(value).digest(); | |
} | |