12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- /**
- * Node.js constant object hash module.
- * @exports node-object-hash
- * @type {Function}
- */
- 'use strict';
- const crypto = require('crypto');
- /**
- * Sorts object fields
- * @param {Object|Array|string|function} obj Initial object
- * @param {Object} options Options
- * @param {boolean} [options.coerce=true] Perform coercion
- * @param {boolean} [options.sort=true] Perform Array, Set, Object sorting
- * @returns {string}
- */
- exports.sortedObjectString = (obj, options) => {
- const coerce = typeof options.coerce == 'undefined' ? true : options.coerce;
- const sort = typeof options.sort == 'undefined' ? true : options.sort;
- if (typeof obj == 'object') {
- if (Array.isArray(obj)) {
- let tmp = [...obj];
- tmp.forEach((it, idx) => {
- tmp[idx] = exports.sortedObjectString(it, {coerce, sort})
- });
- return sort ? `[${tmp.sort().toString()}]` : `[${tmp.toString()}]`;
- }
- if (obj === null) {
- return `null`;
- }
- if (obj instanceof Map) {
- return `Map[${[...obj].toString()}]`;
- }
- if (obj instanceof Set) {
- return sort ? `Set[${[...obj].sort().toString()}]` : `Set[${[...obj].toString()}]`;
- }
- const sortedObj = new Map();
- const keys = sort ? Object.keys(obj).sort() : Object.keys(obj);
- keys.forEach((key) => {
- sortedObj.set(key, exports.sortedObjectString(obj[key], {coerce, sort}));
- });
- return `{${[...sortedObj].toString()}}`;
- }
- if (typeof obj == 'function') {
- return `${obj.name}=>${obj.toString()}`;
- }
- if (coerce) {
- if (typeof obj == 'boolean') {
- return `${Number(obj)}`;
- }
- } else {
- if (typeof obj == 'string') {
- return `"${obj}"`
- }
- }
- if (coerce && typeof obj == 'boolean') {
- return `${Number(obj)}`;
- }
- return obj;
- };
- /**
- * Calculates object hash
- * @param {Object} obj Object to hash
- * @param {Object} [options] Options
- * @param {string} [options.alg="sha256"] Crypto algorithm to use
- * @param {string} [options.enc="hex"] Hash string encoding
- * @param {boolean} [options.coerce=true] Perform coercion
- * @param {boolean} [options.sort=true] Perform Array, Set, Object sorting
- * @returns {string} Hash string
- */
- exports.hash = (obj, options) => {
- options = options || {};
- const alg = options.alg || 'sha256';
- const enc = options.enc || 'hex';
- const coerce = typeof options.coerce == 'undefined' ? true : options.coerce;
- const sort = typeof options.sort == 'undefined' ? true : options.sort;
- if (~crypto.getHashes().indexOf(alg)) {
- const sorted = exports.sortedObjectString(obj, {coerce, sort});
- return crypto.createHash(alg)
- .update(sorted)
- .digest(enc);
- } else {
- throw new Error(`Algorithm ${alg} not supported by "ctypto" module`);
- }
- };
|