@prosopo/fingerprint 2.6.31 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,33 @@
1
1
 
2
- > @prosopo/fingerprint@2.6.31 build:cjs
2
+ > @prosopo/fingerprint@2.7.0 build:cjs
3
3
  > NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV
4
4
 
5
5
  ViteCommonJSConfig: .
6
6
  {
7
7
  tsConfigPaths: [
8
- '/home/runner/work/captcha/captcha/packages/fingerprintjs/tsconfig.json'
8
+ '/home/runner/work/captcha/captcha/packages/fingerprintjs/tsconfig.json',
9
+ '/home/runner/work/captcha/captcha/packages/types/tsconfig.json',
10
+ '/home/runner/work/captcha/captcha/packages/locale/tsconfig.json',
11
+ '/home/runner/work/captcha/captcha/packages/util/tsconfig.json',
12
+ '/home/runner/work/captcha/captcha/packages/util-crypto/tsconfig.json'
13
+ ]
14
+ }
15
+ {
16
+ externals: [
17
+ '@prosopo/fingerprintjs',
18
+ '@prosopo/types',
19
+ '@prosopo/locale',
20
+ '@prosopo/util',
21
+ '@prosopo/util-crypto'
9
22
  ]
10
23
  }
11
- { externals: [ '@prosopo/fingerprintjs' ] }
12
24
  vite v6.4.1 building SSR bundle for production...
13
25
  Bundle build started
14
26
  transforming...
15
27
  Build end
16
- ✓ 1 modules transformed.
28
+ ✓ 3 modules transformed.
17
29
  rendering chunks...
18
- dist/cjs/index.cjs 2.14 kB
19
- ✓ built in 127ms
30
+ dist/cjs/merkle.cjs 2.72 kB
31
+ dist/cjs/proof.cjs 3.17 kB
32
+ dist/cjs/index.cjs 3.38 kB
33
+ ✓ built in 163ms
@@ -1,17 +1,29 @@
1
1
 
2
- > @prosopo/fingerprint@2.6.31 build:tsc
2
+ > @prosopo/fingerprint@2.7.0 build:tsc
3
3
  > tsc --build --verbose
4
4
 
5
- 8:14:09 AM - Projects in this build:
5
+ 12:05:39 PM - Projects in this build:
6
6
  * ../../dev/config/tsconfig.json
7
7
  * ../fingerprintjs/tsconfig.json
8
+ * ../locale/tsconfig.json
9
+ * ../util/tsconfig.json
10
+ * ../util-crypto/tsconfig.json
11
+ * ../types/tsconfig.json
8
12
  * tsconfig.json
9
13
 
10
- 8:14:10 AM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/webpack/webpack.config.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
14
+ 12:05:39 PM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/vite/NodejsPolarsNativeFilePlugin.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
11
15
 
12
- 8:14:10 AM - Project '../fingerprintjs/tsconfig.json' is up to date because newest input '../fingerprintjs/src/sources/webgl.ts' is older than output '../fingerprintjs/tsconfig.tsbuildinfo'
16
+ 12:05:39 PM - Project '../fingerprintjs/tsconfig.json' is up to date because newest input '../fingerprintjs/src/utils/async.ts' is older than output '../fingerprintjs/tsconfig.tsbuildinfo'
13
17
 
14
- 8:14:10 AM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
18
+ 12:05:39 PM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/tsconfig.tsbuildinfo'
15
19
 
16
- 8:14:10 AM - Building project '/home/runner/work/captcha/captcha/packages/fingerprint/tsconfig.json'...
20
+ 12:05:39 PM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
21
+
22
+ 12:05:39 PM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/tsconfig.tsbuildinfo'
23
+
24
+ 12:05:39 PM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/keyring/keyring/types.ts' is older than output '../types/tsconfig.tsbuildinfo'
25
+
26
+ 12:05:39 PM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
27
+
28
+ 12:05:39 PM - Building project '/home/runner/work/captcha/captcha/packages/fingerprint/tsconfig.json'...
17
29
 
@@ -1,23 +1,37 @@
1
1
 
2
- > @prosopo/fingerprint@2.6.31 build
2
+ > @prosopo/fingerprint@2.7.0 build
3
3
  > npm run build:cross-env -- --mode ${NODE_ENV:-development}
4
4
 
5
5
 
6
- > @prosopo/fingerprint@2.6.31 build:cross-env
6
+ > @prosopo/fingerprint@2.7.0 build:cross-env
7
7
  > vite build --config vite.esm.config.ts --mode production
8
8
 
9
9
  ViteEsmConfig: .
10
10
  {
11
11
  tsConfigPaths: [
12
- '/home/runner/work/captcha/captcha/packages/fingerprintjs/tsconfig.json'
12
+ '/home/runner/work/captcha/captcha/packages/fingerprintjs/tsconfig.json',
13
+ '/home/runner/work/captcha/captcha/packages/types/tsconfig.json',
14
+ '/home/runner/work/captcha/captcha/packages/locale/tsconfig.json',
15
+ '/home/runner/work/captcha/captcha/packages/util/tsconfig.json',
16
+ '/home/runner/work/captcha/captcha/packages/util-crypto/tsconfig.json'
17
+ ]
18
+ }
19
+ {
20
+ externals: [
21
+ '@prosopo/fingerprintjs',
22
+ '@prosopo/types',
23
+ '@prosopo/locale',
24
+ '@prosopo/util',
25
+ '@prosopo/util-crypto'
13
26
  ]
14
27
  }
15
- { externals: [ '@prosopo/fingerprintjs' ] }
16
28
  vite v6.4.1 building SSR bundle for production...
17
29
  Bundle build started
18
30
  transforming...
19
31
  Build end
20
- ✓ 1 modules transformed.
32
+ ✓ 3 modules transformed.
21
33
  rendering chunks...
22
- dist/index.js 0.85 kB
23
- ✓ built in 117ms
34
+ dist/index.js 1.92 kB
35
+ dist/merkle.js 2.50 kB
36
+ dist/proof.js 2.92 kB
37
+ ✓ built in 148ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @prosopo/fingerprint
2
2
 
3
+ ## 2.7.0
4
+ ### Minor Changes
5
+
6
+ - dde23e8: Internal bot-detection signal improvements.
7
+
8
+ ### Patch Changes
9
+
10
+ - Updated dependencies [3a46191]
11
+ - Updated dependencies [dde23e8]
12
+ - @prosopo/types@4.7.0
13
+
3
14
  ## 2.6.31
4
15
  ### Patch Changes
5
16
 
@@ -22,13 +22,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
22
  mod
23
23
  ));
24
24
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
25
+ const proof = require("./proof.cjs");
26
+ const merkle = require("./merkle.cjs");
25
27
  const EXCLUDED_SOURCES = ["webGlExtensions"];
26
28
  const FingerprintJSImport = async () => import("@prosopo/fingerprintjs");
27
- let fingerprintCache = null;
28
- const getFingerprint = async () => {
29
- if (!fingerprintCache) {
30
- fingerprintCache = (async () => {
31
- const { sources, loadSources, hashComponents, prepareForSources } = await FingerprintJSImport();
29
+ let componentsCache = null;
30
+ const loadComponents = () => {
31
+ if (!componentsCache) {
32
+ const pending = (async () => {
33
+ const { sources, loadSources, prepareForSources } = await FingerprintJSImport();
32
34
  await prepareForSources();
33
35
  const sourceOptions = {
34
36
  cache: {}
@@ -38,16 +40,43 @@ const getFingerprint = async () => {
38
40
  sourceOptions,
39
41
  EXCLUDED_SOURCES
40
42
  );
41
- const components = await getComponents();
42
- return hashComponents(components);
43
+ return getComponents();
43
44
  })();
45
+ componentsCache = pending;
46
+ pending.catch(() => {
47
+ if (componentsCache === pending) {
48
+ componentsCache = null;
49
+ }
50
+ });
44
51
  }
45
- return fingerprintCache;
52
+ return componentsCache;
53
+ };
54
+ const getFingerprint = async () => {
55
+ const [{ hashComponents }, components] = await Promise.all([
56
+ FingerprintJSImport(),
57
+ loadComponents()
58
+ ]);
59
+ return hashComponents(components);
60
+ };
61
+ const getFingerprintProof = async (discloseKeys) => {
62
+ const components = await loadComponents();
63
+ return proof.buildFingerprintProofFromComponents(components, discloseKeys);
46
64
  };
47
65
  const prefetchFingerprint = () => {
48
- getFingerprint().catch(() => {
49
- fingerprintCache = null;
66
+ loadComponents().catch(() => {
50
67
  });
51
68
  };
69
+ exports.FINGERPRINT_DISCLOSURE_KEYS = proof.FINGERPRINT_DISCLOSURE_KEYS;
70
+ exports.FINGERPRINT_PROOF_VERSION = proof.FINGERPRINT_PROOF_VERSION;
71
+ exports.buildFingerprintProofFromComponents = proof.buildFingerprintProofFromComponents;
72
+ exports.encodeFingerprintProof = proof.encodeFingerprintProof;
73
+ exports.leafHashForContent = proof.leafHashForContent;
74
+ exports.verifyFingerprintProofStructure = proof.verifyFingerprintProofStructure;
75
+ exports.buildMerkleLayers = merkle.buildMerkleLayers;
76
+ exports.hashMerklePair = merkle.hashMerklePair;
77
+ exports.merkleProofFromLayers = merkle.merkleProofFromLayers;
78
+ exports.merkleRootFromLayers = merkle.merkleRootFromLayers;
79
+ exports.verifyMerkleProof = merkle.verifyMerkleProof;
52
80
  exports.getFingerprint = getFingerprint;
81
+ exports.getFingerprintProof = getFingerprintProof;
53
82
  exports.prefetchFingerprint = prefetchFingerprint;
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const utilCrypto = require("@prosopo/util-crypto");
4
+ const at = (arr, index) => {
5
+ const value = arr[index];
6
+ if (value === void 0) {
7
+ throw new Error(
8
+ `merkle: index ${index} out of range (length ${arr.length})`
9
+ );
10
+ }
11
+ return value;
12
+ };
13
+ const hashMerklePair = (left, right) => utilCrypto.hexHashArray([left, right]);
14
+ const buildMerkleLayers = (leafHashes) => {
15
+ if (leafHashes.length === 0) {
16
+ throw new Error("merkle: cannot build a tree with no leaves");
17
+ }
18
+ const layers = [[...leafHashes]];
19
+ let current = leafHashes;
20
+ while (current.length > 1) {
21
+ const next = [];
22
+ for (let i = 0; i < current.length; i += 2) {
23
+ const left = at(current, i);
24
+ const right = i + 1 < current.length ? at(current, i + 1) : left;
25
+ next.push(hashMerklePair(left, right));
26
+ }
27
+ layers.push(next);
28
+ current = next;
29
+ }
30
+ return layers;
31
+ };
32
+ const merkleRootFromLayers = (layers) => at(at(layers, layers.length - 1), 0);
33
+ const merkleProofFromLayers = (layers, leafHash) => {
34
+ const proof = [];
35
+ let hash = leafHash;
36
+ for (let layerNum = 0; layerNum < layers.length - 1; layerNum++) {
37
+ const layer = at(layers, layerNum);
38
+ const index = layer.indexOf(hash);
39
+ if (index === -1) {
40
+ throw new Error("merkle: leaf hash not present in layer");
41
+ }
42
+ let partnerIndex = index % 2 === 1 ? index - 1 : index + 1;
43
+ if (partnerIndex > layer.length - 1) {
44
+ partnerIndex = index;
45
+ }
46
+ const partner = at(layer, partnerIndex);
47
+ const pair = partnerIndex > index ? [hash, partner] : [partner, hash];
48
+ proof.push(pair);
49
+ hash = hashMerklePair(pair[0], pair[1]);
50
+ }
51
+ return [...proof, [merkleRootFromLayers(layers)]];
52
+ };
53
+ const verifyMerkleProof = (leafHash, proof) => {
54
+ try {
55
+ const firstLayer = proof[0];
56
+ if (firstLayer === void 0 || firstLayer.indexOf(leafHash) === -1) {
57
+ return false;
58
+ }
59
+ if (proof.length === 1) {
60
+ return at(firstLayer, 0) === leafHash;
61
+ }
62
+ const root = at(at(proof, proof.length - 1), 0);
63
+ let hash = leafHash;
64
+ for (let i = 0; i < proof.length - 1; i++) {
65
+ const layer = at(proof, i);
66
+ if (layer.indexOf(hash) === -1) {
67
+ return false;
68
+ }
69
+ hash = hashMerklePair(at(layer, 0), at(layer, 1));
70
+ if (at(proof, i + 1).indexOf(hash) === -1) {
71
+ return false;
72
+ }
73
+ }
74
+ return hash === root;
75
+ } catch {
76
+ return false;
77
+ }
78
+ };
79
+ exports.buildMerkleLayers = buildMerkleLayers;
80
+ exports.hashMerklePair = hashMerklePair;
81
+ exports.merkleProofFromLayers = merkleProofFromLayers;
82
+ exports.merkleRootFromLayers = merkleRootFromLayers;
83
+ exports.verifyMerkleProof = verifyMerkleProof;
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const utilCrypto = require("@prosopo/util-crypto");
4
+ const merkle = require("./merkle.cjs");
5
+ const FINGERPRINT_PROOF_VERSION = 1;
6
+ const FINGERPRINT_DISCLOSURE_KEYS = [
7
+ "colorDepth",
8
+ "cookiesEnabled",
9
+ "sessionStorage",
10
+ "localStorage",
11
+ "timezone",
12
+ "hardwareConcurrency",
13
+ "languages",
14
+ "architecture"
15
+ ];
16
+ const escapeKey = (key) => key.replace(/([:|\\])/g, "\\$1");
17
+ const componentLeafContent = (key, component) => {
18
+ const serialized = "error" in component ? "error" : JSON.stringify(component.value);
19
+ return `${escapeKey(key)}:${serialized}`;
20
+ };
21
+ const disclosureLeafContent = (disclosure) => {
22
+ const serialized = disclosure.error ? "error" : JSON.stringify(disclosure.value);
23
+ return `${escapeKey(disclosure.key)}:${serialized}`;
24
+ };
25
+ const leafHashForContent = (content) => utilCrypto.hexHash(content);
26
+ const buildFingerprintProofFromComponents = (components, discloseKeys) => {
27
+ const keys = Object.keys(components).sort();
28
+ if (keys.length === 0) {
29
+ throw new Error("fingerprint proof: no components to commit to");
30
+ }
31
+ const leafHashes = keys.map((key) => {
32
+ const component = components[key];
33
+ if (component === void 0) {
34
+ throw new Error(`fingerprint proof: missing component ${key}`);
35
+ }
36
+ return leafHashForContent(componentLeafContent(key, component));
37
+ });
38
+ const layers = merkle.buildMerkleLayers(leafHashes);
39
+ const root = merkle.merkleRootFromLayers(layers);
40
+ const disclose = discloseKeys ?? keys;
41
+ const disclosures = [];
42
+ for (const key of disclose) {
43
+ const index = keys.indexOf(key);
44
+ if (index === -1) {
45
+ continue;
46
+ }
47
+ const component = components[key];
48
+ const leafHash = leafHashes[index];
49
+ if (component === void 0 || leafHash === void 0) {
50
+ continue;
51
+ }
52
+ const proof = merkle.merkleProofFromLayers(layers, leafHash);
53
+ disclosures.push(
54
+ "error" in component ? { key, error: true, proof } : { key, value: component.value, proof }
55
+ );
56
+ }
57
+ return { v: FINGERPRINT_PROOF_VERSION, root, disclosures };
58
+ };
59
+ const verifyFingerprintProofStructure = (proof) => {
60
+ if (proof.v !== FINGERPRINT_PROOF_VERSION) {
61
+ return false;
62
+ }
63
+ if (typeof proof.root !== "string" || proof.disclosures.length === 0) {
64
+ return false;
65
+ }
66
+ for (const disclosure of proof.disclosures) {
67
+ const leafHash = leafHashForContent(disclosureLeafContent(disclosure));
68
+ if (!merkle.verifyMerkleProof(leafHash, disclosure.proof)) {
69
+ return false;
70
+ }
71
+ const rootLayer = disclosure.proof[disclosure.proof.length - 1];
72
+ if (rootLayer === void 0 || rootLayer[0] !== proof.root) {
73
+ return false;
74
+ }
75
+ }
76
+ return true;
77
+ };
78
+ const encodeFingerprintProof = (proof) => JSON.stringify(proof);
79
+ exports.FINGERPRINT_DISCLOSURE_KEYS = FINGERPRINT_DISCLOSURE_KEYS;
80
+ exports.FINGERPRINT_PROOF_VERSION = FINGERPRINT_PROOF_VERSION;
81
+ exports.buildFingerprintProofFromComponents = buildFingerprintProofFromComponents;
82
+ exports.encodeFingerprintProof = encodeFingerprintProof;
83
+ exports.leafHashForContent = leafHashForContent;
84
+ exports.verifyFingerprintProofStructure = verifyFingerprintProofStructure;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,8 @@
1
+ import { type FingerprintProof } from "./proof.js";
1
2
  export declare const getFingerprint: () => Promise<string>;
3
+ export declare const getFingerprintProof: (discloseKeys?: readonly string[]) => Promise<FingerprintProof>;
2
4
  export declare const prefetchFingerprint: () => void;
5
+ export type { FingerprintLeafDisclosure, FingerprintProof } from "./proof.js";
6
+ export { FINGERPRINT_DISCLOSURE_KEYS, FINGERPRINT_PROOF_VERSION, buildFingerprintProofFromComponents, encodeFingerprintProof, leafHashForContent, verifyFingerprintProofStructure, } from "./proof.js";
7
+ export { buildMerkleLayers, hashMerklePair, merkleProofFromLayers, merkleRootFromLayers, verifyMerkleProof, } from "./merkle.js";
3
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,cAAc,QAAa,OAAO,CAAC,MAAM,CAsBrD,CAAC;AAEF,eAAO,MAAM,mBAAmB,QAAO,IAItC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,EACN,KAAK,gBAAgB,EAErB,MAAM,YAAY,CAAC;AA2CpB,eAAO,MAAM,cAAc,QAAa,OAAO,CAAC,MAAM,CAMrD,CAAC;AASF,eAAO,MAAM,mBAAmB,kBAChB,SAAS,MAAM,EAAE,KAC9B,OAAO,CAAC,gBAAgB,CAG1B,CAAC;AAEF,eAAO,MAAM,mBAAmB,QAAO,IAItC,CAAC;AAEF,YAAY,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,EACN,2BAA2B,EAC3B,yBAAyB,EACzB,mCAAmC,EACnC,sBAAsB,EACtB,kBAAkB,EAClB,+BAA+B,GAC/B,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,GACjB,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,10 +1,13 @@
1
+ import { buildFingerprintProofFromComponents } from "./proof.js";
2
+ import { FINGERPRINT_DISCLOSURE_KEYS, FINGERPRINT_PROOF_VERSION, encodeFingerprintProof, leafHashForContent, verifyFingerprintProofStructure } from "./proof.js";
3
+ import { buildMerkleLayers, hashMerklePair, merkleProofFromLayers, merkleRootFromLayers, verifyMerkleProof } from "./merkle.js";
1
4
  const EXCLUDED_SOURCES = ["webGlExtensions"];
2
5
  const FingerprintJSImport = async () => import("@prosopo/fingerprintjs");
3
- let fingerprintCache = null;
4
- const getFingerprint = async () => {
5
- if (!fingerprintCache) {
6
- fingerprintCache = (async () => {
7
- const { sources, loadSources, hashComponents, prepareForSources } = await FingerprintJSImport();
6
+ let componentsCache = null;
7
+ const loadComponents = () => {
8
+ if (!componentsCache) {
9
+ const pending = (async () => {
10
+ const { sources, loadSources, prepareForSources } = await FingerprintJSImport();
8
11
  await prepareForSources();
9
12
  const sourceOptions = {
10
13
  cache: {}
@@ -14,18 +17,45 @@ const getFingerprint = async () => {
14
17
  sourceOptions,
15
18
  EXCLUDED_SOURCES
16
19
  );
17
- const components = await getComponents();
18
- return hashComponents(components);
20
+ return getComponents();
19
21
  })();
22
+ componentsCache = pending;
23
+ pending.catch(() => {
24
+ if (componentsCache === pending) {
25
+ componentsCache = null;
26
+ }
27
+ });
20
28
  }
21
- return fingerprintCache;
29
+ return componentsCache;
30
+ };
31
+ const getFingerprint = async () => {
32
+ const [{ hashComponents }, components] = await Promise.all([
33
+ FingerprintJSImport(),
34
+ loadComponents()
35
+ ]);
36
+ return hashComponents(components);
37
+ };
38
+ const getFingerprintProof = async (discloseKeys) => {
39
+ const components = await loadComponents();
40
+ return buildFingerprintProofFromComponents(components, discloseKeys);
22
41
  };
23
42
  const prefetchFingerprint = () => {
24
- getFingerprint().catch(() => {
25
- fingerprintCache = null;
43
+ loadComponents().catch(() => {
26
44
  });
27
45
  };
28
46
  export {
47
+ FINGERPRINT_DISCLOSURE_KEYS,
48
+ FINGERPRINT_PROOF_VERSION,
49
+ buildFingerprintProofFromComponents,
50
+ buildMerkleLayers,
51
+ encodeFingerprintProof,
29
52
  getFingerprint,
30
- prefetchFingerprint
53
+ getFingerprintProof,
54
+ hashMerklePair,
55
+ leafHashForContent,
56
+ merkleProofFromLayers,
57
+ merkleRootFromLayers,
58
+ prefetchFingerprint,
59
+ verifyFingerprintProofStructure,
60
+ verifyMerkleProof
31
61
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,MAAM,gBAAgB,GAAG,CAAC,iBAAiB,CAAU,CAAC;AAEtD,MAAM,mBAAmB,GAAG,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC;AAEzE,IAAI,gBAAgB,GAA2B,IAAI,CAAC;AAEpD,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,IAAqB,EAAE;IACzD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvB,gBAAgB,GAAG,CAAC,KAAK,IAAI,EAAE;YAC9B,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,GAChE,MAAM,mBAAmB,EAAE,CAAC;YAC7B,MAAM,iBAAiB,EAAE,CAAC;YAG1B,MAAM,aAAa,GAClB;gBACC,KAAK,EAAE,EAAE;aACT,CAAC;YACH,MAAM,aAAa,GAAG,WAAW,CAChC,OAAO,EACP,aAAa,EACb,gBAAgB,CAChB,CAAC;YACF,MAAM,UAAU,GAAG,MAAM,aAAa,EAAE,CAAC;YACzC,OAAO,cAAc,CAAC,UAAU,CAAC,CAAC;QACnC,CAAC,CAAC,EAAE,CAAC;IACN,CAAC;IACD,OAAO,gBAAgB,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAS,EAAE;IAC7C,cAAc,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;QAC3B,gBAAgB,GAAG,IAAI,CAAC;IACzB,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAEN,mCAAmC,GACnC,MAAM,YAAY,CAAC;AAKpB,MAAM,gBAAgB,GAAG,CAAC,iBAAiB,CAAU,CAAC;AAEtD,MAAM,mBAAmB,GAAG,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC;AAIzE,IAAI,eAAe,GAAsC,IAAI,CAAC;AAE9D,MAAM,cAAc,GAAG,GAA+B,EAAE;IACvD,IAAI,CAAC,eAAe,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,GAChD,MAAM,mBAAmB,EAAE,CAAC;YAC7B,MAAM,iBAAiB,EAAE,CAAC;YAG1B,MAAM,aAAa,GAClB;gBACC,KAAK,EAAE,EAAE;aACT,CAAC;YACH,MAAM,aAAa,GAAG,WAAW,CAChC,OAAO,EACP,aAAa,EACb,gBAAgB,CAChB,CAAC;YACF,OAAO,aAAa,EAAE,CAAC;QACxB,CAAC,CAAC,EAAE,CAAC;QACL,eAAe,GAAG,OAAO,CAAC;QAE1B,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE;YAClB,IAAI,eAAe,KAAK,OAAO,EAAE,CAAC;gBACjC,eAAe,GAAG,IAAI,CAAC;YACxB,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,eAAe,CAAC;AACxB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,IAAqB,EAAE;IACzD,MAAM,CAAC,EAAE,cAAc,EAAE,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1D,mBAAmB,EAAE;QACrB,cAAc,EAAE;KAChB,CAAC,CAAC;IACH,OAAO,cAAc,CAAC,UAAU,CAAC,CAAC;AACnC,CAAC,CAAC;AASF,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EACvC,YAAgC,EACJ,EAAE;IAC9B,MAAM,UAAU,GAAG,MAAM,cAAc,EAAE,CAAC;IAC1C,OAAO,mCAAmC,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;AACtE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAS,EAAE;IAC7C,cAAc,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;IAE5B,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC;AAGF,OAAO,EACN,2BAA2B,EAC3B,yBAAyB,EACzB,mCAAmC,EACnC,sBAAsB,EACtB,kBAAkB,EAClB,+BAA+B,GAC/B,MAAM,YAAY,CAAC;AACpB,OAAO,EACN,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,GACjB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { MerkleLeaf, MerkleProof } from "@prosopo/types";
2
+ export declare const hashMerklePair: (left: string, right: string) => string;
3
+ export declare const buildMerkleLayers: (leafHashes: string[]) => string[][];
4
+ export declare const merkleRootFromLayers: (layers: string[][]) => string;
5
+ export declare const merkleProofFromLayers: (layers: string[][], leafHash: MerkleLeaf) => MerkleProof;
6
+ export declare const verifyMerkleProof: (leafHash: MerkleLeaf, proof: MerkleProof) => boolean;
7
+ //# sourceMappingURL=merkle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merkle.d.ts","sourceRoot":"","sources":["../src/merkle.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAoB,MAAM,gBAAgB,CAAC;AAqBhF,eAAO,MAAM,cAAc,SAAU,MAAM,SAAS,MAAM,KAAG,MACjC,CAAC;AAO7B,eAAO,MAAM,iBAAiB,eAAgB,MAAM,EAAE,KAAG,MAAM,EAAE,EAiBhE,CAAC;AAEF,eAAO,MAAM,oBAAoB,WAAY,MAAM,EAAE,EAAE,KAAG,MACrB,CAAC;AAGtC,eAAO,MAAM,qBAAqB,WACzB,MAAM,EAAE,EAAE,YACR,UAAU,KAClB,WAqBF,CAAC;AAGF,eAAO,MAAM,iBAAiB,aACnB,UAAU,SACb,WAAW,KAChB,OA0BF,CAAC"}
package/dist/merkle.js ADDED
@@ -0,0 +1,83 @@
1
+ import { hexHashArray } from "@prosopo/util-crypto";
2
+ const at = (arr, index) => {
3
+ const value = arr[index];
4
+ if (value === void 0) {
5
+ throw new Error(
6
+ `merkle: index ${index} out of range (length ${arr.length})`
7
+ );
8
+ }
9
+ return value;
10
+ };
11
+ const hashMerklePair = (left, right) => hexHashArray([left, right]);
12
+ const buildMerkleLayers = (leafHashes) => {
13
+ if (leafHashes.length === 0) {
14
+ throw new Error("merkle: cannot build a tree with no leaves");
15
+ }
16
+ const layers = [[...leafHashes]];
17
+ let current = leafHashes;
18
+ while (current.length > 1) {
19
+ const next = [];
20
+ for (let i = 0; i < current.length; i += 2) {
21
+ const left = at(current, i);
22
+ const right = i + 1 < current.length ? at(current, i + 1) : left;
23
+ next.push(hashMerklePair(left, right));
24
+ }
25
+ layers.push(next);
26
+ current = next;
27
+ }
28
+ return layers;
29
+ };
30
+ const merkleRootFromLayers = (layers) => at(at(layers, layers.length - 1), 0);
31
+ const merkleProofFromLayers = (layers, leafHash) => {
32
+ const proof = [];
33
+ let hash = leafHash;
34
+ for (let layerNum = 0; layerNum < layers.length - 1; layerNum++) {
35
+ const layer = at(layers, layerNum);
36
+ const index = layer.indexOf(hash);
37
+ if (index === -1) {
38
+ throw new Error("merkle: leaf hash not present in layer");
39
+ }
40
+ let partnerIndex = index % 2 === 1 ? index - 1 : index + 1;
41
+ if (partnerIndex > layer.length - 1) {
42
+ partnerIndex = index;
43
+ }
44
+ const partner = at(layer, partnerIndex);
45
+ const pair = partnerIndex > index ? [hash, partner] : [partner, hash];
46
+ proof.push(pair);
47
+ hash = hashMerklePair(pair[0], pair[1]);
48
+ }
49
+ return [...proof, [merkleRootFromLayers(layers)]];
50
+ };
51
+ const verifyMerkleProof = (leafHash, proof) => {
52
+ try {
53
+ const firstLayer = proof[0];
54
+ if (firstLayer === void 0 || firstLayer.indexOf(leafHash) === -1) {
55
+ return false;
56
+ }
57
+ if (proof.length === 1) {
58
+ return at(firstLayer, 0) === leafHash;
59
+ }
60
+ const root = at(at(proof, proof.length - 1), 0);
61
+ let hash = leafHash;
62
+ for (let i = 0; i < proof.length - 1; i++) {
63
+ const layer = at(proof, i);
64
+ if (layer.indexOf(hash) === -1) {
65
+ return false;
66
+ }
67
+ hash = hashMerklePair(at(layer, 0), at(layer, 1));
68
+ if (at(proof, i + 1).indexOf(hash) === -1) {
69
+ return false;
70
+ }
71
+ }
72
+ return hash === root;
73
+ } catch {
74
+ return false;
75
+ }
76
+ };
77
+ export {
78
+ buildMerkleLayers,
79
+ hashMerklePair,
80
+ merkleProofFromLayers,
81
+ merkleRootFromLayers,
82
+ verifyMerkleProof
83
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merkle.js","sourceRoot":"","sources":["../src/merkle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { UnknownComponents } from "@prosopo/fingerprintjs";
2
+ import type { MerkleProof } from "@prosopo/types";
3
+ export declare const FINGERPRINT_PROOF_VERSION = 1;
4
+ export declare const FINGERPRINT_DISCLOSURE_KEYS: readonly string[];
5
+ export interface FingerprintLeafDisclosure {
6
+ key: string;
7
+ value?: unknown;
8
+ error?: boolean;
9
+ proof: MerkleProof;
10
+ }
11
+ export interface FingerprintProof {
12
+ v: number;
13
+ root: string;
14
+ disclosures: FingerprintLeafDisclosure[];
15
+ }
16
+ export declare const leafHashForContent: (content: string) => string;
17
+ export declare const buildFingerprintProofFromComponents: (components: UnknownComponents, discloseKeys?: readonly string[]) => FingerprintProof;
18
+ export declare const verifyFingerprintProofStructure: (proof: FingerprintProof) => boolean;
19
+ export declare const encodeFingerprintProof: (proof: FingerprintProof) => string;
20
+ //# sourceMappingURL=proof.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proof.d.ts","sourceRoot":"","sources":["../src/proof.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAa,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AASlD,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAa3C,eAAO,MAAM,2BAA2B,EAAE,SAAS,MAAM,EASxD,CAAC;AASF,MAAM,WAAW,yBAAyB;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,WAAW,CAAC;CACnB;AASD,MAAM,WAAW,gBAAgB;IAChC,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,yBAAyB,EAAE,CAAC;CACzC;AA2BD,eAAO,MAAM,kBAAkB,YAAa,MAAM,KAAG,MAA0B,CAAC;AAShF,eAAO,MAAM,mCAAmC,eACnC,iBAAiB,iBACd,SAAS,MAAM,EAAE,KAC9B,gBAsCF,CAAC;AAQF,eAAO,MAAM,+BAA+B,UACpC,gBAAgB,KACrB,OAkBF,CAAC;AAEF,eAAO,MAAM,sBAAsB,UAAW,gBAAgB,KAAG,MAC3C,CAAC"}