etherpad-lite/src/node/utils/crypto.js
2023-07-03 21:01:28 +02:00

43 lines
1.2 KiB
JavaScript

'use strict';
const {Buffer} = require('buffer');
const crypto = require('crypto');
const util = require('util');
// TODO: Delete this once support for Node.js < 15.0.0 is dropped.
const hkdfFallback = async (digest, ikm, salt, info, keylen) => {
// https://datatracker.ietf.org/doc/html/rfc5869#section-2.2
const prkHmac = crypto.createHmac(digest, salt);
prkHmac.update(ikm);
const prk = prkHmac.digest();
// https://datatracker.ietf.org/doc/html/rfc5869#section-2.3
let len = 0;
const t = [Buffer.alloc(0)];
while (len < keylen) {
const hmac = crypto.createHmac(digest, prk);
hmac.update(t[t.length - 1]);
hmac.update(info);
hmac.update(Buffer.from([t.length % 256]));
const tn = hmac.digest();
t.push(tn);
len += tn.length;
}
const buf = Buffer.concat(t);
return (buf.byteOffset === 0 && buf.buffer.byteLength === keylen
? buf : Uint8Array.prototype.slice.call(buf, 0, keylen)).buffer;
};
/**
* Promisified version of Node.js's crypto.hkdf.
*/
exports.hkdf = crypto.hkdf ? util.promisify(crypto.hkdf) : hkdfFallback;
/**
* Promisified version of Node.js's crypto.randomBytes
*/
exports.randomBytes = util.promisify(crypto.randomBytes);
exports.exportedForTesting = {
hkdfFallback,
};