保誠-保戶業務員媒合平台
HelenHuang
2022-06-09 9bdb95c9e34cef640534e5e5a1e2225a80442000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/**
 * 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`);
  }
};