UNPKG

@istvan.xyz/phc-format

Version:

An implementation of the PHC format.

74 lines (73 loc) 2.92 kB
"use strict"; 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;