@istvan.xyz/phc-format
Version:
An implementation of the PHC format.
74 lines (73 loc) • 2.92 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
// cspell:words phcobj, phcstr, Valto, strpar, pchstr, maxf, parstr
const patterns_1 = require("./patterns");
function objectToKeyValueString(object) {
return Object.entries(object)
.map(([key, value]) => [key, value].join('='))
.join(',');
}
/**
* Generates a PHC string using the data provided.
* @param {Object} opts Object that holds the data needed to generate the PHC
* string.
* @param {string} opts.id Symbolic name for the function.
* @param {Number} [opts.version] The version of the function.
* @param {Object} [opts.params] Parameters of the function.
* @param {Buffer} [opts.salt] The salt as a binary buffer.
* @param {Buffer} [opts.hash] The hash as a binary buffer.
* @return {string} The hash string adhering to the PHC format.
*/
function serialize(opts) {
const fields = [''];
if (!patterns_1.idRegex.test(opts.id)) {
throw new TypeError(`id must satisfy ${patterns_1.idRegex}`);
}
fields.push(opts.id);
if (typeof opts.version !== 'undefined') {
if (opts.version < 0 || !Number.isInteger(opts.version)) {
throw new TypeError('version must be a positive integer number');
}
fields.push(`v=${opts.version}`);
}
// Parameter Validation
const { params } = opts;
if (typeof params !== 'undefined') {
const pk = Object.keys(params);
if (!pk.every(p => patterns_1.nameRegex.test(p))) {
throw new TypeError(`params names must satisfy ${patterns_1.nameRegex}`);
}
// Convert Numbers into Numeric Strings and Buffers into B64 encoded strings.
pk.forEach(k => {
if (typeof params[k] === 'number') {
params[k] = params[k].toString();
}
else if (Buffer.isBuffer(params[k])) {
[params[k]] = params[k].toString('base64').split('=');
}
});
const pv = Object.values(params);
if (!pv.every(v => typeof v === 'string')) {
throw new TypeError('params values must be strings');
}
if (!pv.every(v => patterns_1.valueRegex.test(v))) {
throw new TypeError(`params values must satisfy ${patterns_1.valueRegex}`);
}
const strpar = objectToKeyValueString(params);
fields.push(strpar);
}
if (typeof opts.salt !== 'undefined') {
fields.push(opts.salt.toString('base64').split('=')[0]);
if (typeof opts.hash !== 'undefined') {
// Hash Validation
if (!Buffer.isBuffer(opts.hash)) {
throw new TypeError('hash must be a Buffer');
}
fields.push(opts.hash.toString('base64').split('=')[0]);
}
}
// Create the PHC formatted string
const phcString = fields.join('$');
return phcString;
}
exports.default = serialize;