@prosopo/provider 5.20.1 → 5.20.2
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.
- package/.turbo/turbo-build$colon$cjs.log +5 -1
- package/.turbo/turbo-build$colon$tsc.log +34 -28
- package/.turbo/turbo-build.log +7 -6
- package/CHANGELOG.md +25 -0
- package/dist/api/captcha/submitPoWCaptchaSolution.js +1 -1
- package/package.json +4 -4
- package/dist/fingerprint/dist/merkle.js +0 -69
- package/dist/fingerprint/dist/proof.js +0 -95
- package/dist/fingerprint/dist/summary.js +0 -73
|
@@ -25,6 +25,8 @@ ViteCommonJSConfig: .
|
|
|
25
25
|
'/home/runner/work/captcha/captcha/packages/datasets/tsconfig.json',
|
|
26
26
|
'/home/runner/work/captcha/captcha/packages/icon-order-assets/tsconfig.json',
|
|
27
27
|
'/home/runner/work/captcha/captcha/packages/load-balancer/tsconfig.json',
|
|
28
|
+
'/home/runner/work/captcha/captcha/packages/fingerprint/tsconfig.json',
|
|
29
|
+
'/home/runner/work/captcha/captcha/packages/fingerprintjs/tsconfig.json',
|
|
28
30
|
'/home/runner/work/captcha/captcha/packages/web-bot-auth/tsconfig.json'
|
|
29
31
|
]
|
|
30
32
|
}
|
|
@@ -53,6 +55,8 @@ ViteCommonJSConfig: .
|
|
|
53
55
|
'@prosopo/datasets',
|
|
54
56
|
'@prosopo/icon-order-assets',
|
|
55
57
|
'@prosopo/load-balancer',
|
|
58
|
+
'@prosopo/fingerprint',
|
|
59
|
+
'@prosopo/fingerprintjs',
|
|
56
60
|
'@prosopo/web-bot-auth'
|
|
57
61
|
]
|
|
58
62
|
}
|
|
@@ -205,7 +209,7 @@ dist/cjs/tasks/captchaManager.cjs 26
|
|
|
205
209
|
dist/cjs/tasks/powCaptcha/powTasks.cjs 26.90 kB │ gzip: 6.49 kB
|
|
206
210
|
dist/cjs/tasks/imgCaptcha/imgCaptchaTasks.cjs 29.43 kB │ gzip: 6.66 kB
|
|
207
211
|
|
|
208
|
-
[32m✓ built in
|
|
212
|
+
[32m✓ built in 204ms[39m
|
|
209
213
|
[copy-plugin] copying /home/runner/work/captcha/captcha/packages/provider/src/tasks/detection/decodeBehavior.js to /home/runner/work/captcha/captcha/packages/provider/dist/cjs/tasks/detection/decodeBehavior.js
|
|
210
214
|
[copy-plugin] copying /home/runner/work/captcha/captcha/packages/provider/src/tasks/detection/decodePayload.js to /home/runner/work/captcha/captcha/packages/provider/dist/cjs/tasks/detection/decodePayload.js
|
|
211
215
|
[copy-plugin] copying /home/runner/work/captcha/captcha/packages/provider/src/tasks/detection/decodeSimd.js to /home/runner/work/captcha/captcha/packages/provider/dist/cjs/tasks/detection/decodeSimd.js
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
$ tsc --build --verbose
|
|
2
|
-
|
|
2
|
+
9:34:00 PM - Projects in this build:
|
|
3
3
|
* ../../dev/config/tsconfig.json
|
|
4
4
|
* ../util/tsconfig.json
|
|
5
5
|
* ../locale/tsconfig.json
|
|
@@ -24,60 +24,66 @@ $ tsc --build --verbose
|
|
|
24
24
|
* ../datasets/tsconfig.json
|
|
25
25
|
* ../icon-order-assets/tsconfig.json
|
|
26
26
|
* ../load-balancer/tsconfig.json
|
|
27
|
+
* ../fingerprintjs/tsconfig.json
|
|
28
|
+
* ../fingerprint/tsconfig.json
|
|
27
29
|
* ../web-bot-auth/tsconfig.json
|
|
28
30
|
* tsconfig.json
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
9:34:00 PM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/vite/vite-plugin-modify-exports-files.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
9:34:00 PM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
9:34:00 PM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/tsconfig.tsbuildinfo'
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
9:34:00 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'
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
9:34:00 PM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/types.test-d.ts' is older than output '../types/tsconfig.tsbuildinfo'
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
9:34:00 PM - Project '../api/tsconfig.json' is up to date because newest input '../api/src/index.ts' is older than output '../api/tsconfig.tsbuildinfo'
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
9:34:00 PM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/logger.ts' is older than output '../logger/tsconfig.tsbuildinfo'
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
9:34:00 PM - Project '../api-route/tsconfig.json' is up to date because newest input '../api-route/src/apiRoutes.ts' is older than output '../api-route/tsconfig.tsbuildinfo'
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
9:34:00 PM - Project '../common/tsconfig.json' is up to date because newest input '../common/src/tests/errorSites.unit.test.ts' is older than output '../common/tsconfig.tsbuildinfo'
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
9:34:00 PM - Project '../ipinfo/tsconfig.json' is up to date because newest input '../ipinfo/src/types.ts' is older than output '../ipinfo/tsconfig.tsbuildinfo'
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
9:34:00 PM - Project '../redis-client/tsconfig.json' is up to date because newest input '../redis-client/src/index.ts' is older than output '../redis-client/tsconfig.tsbuildinfo'
|
|
51
53
|
|
|
52
|
-
|
|
54
|
+
9:34:01 PM - Project '../user-access-policy/tsconfig.json' is up to date because newest input '../user-access-policy/src/transformRule.ts' is older than output '../user-access-policy/tsconfig.tsbuildinfo'
|
|
53
55
|
|
|
54
|
-
|
|
56
|
+
9:34:01 PM - Project '../types-database/tsconfig.json' is up to date because newest input '../types-database/src/types/provider.ts' is older than output '../types-database/tsconfig.tsbuildinfo'
|
|
55
57
|
|
|
56
|
-
|
|
58
|
+
9:34:01 PM - Project '../database/tsconfig.json' is up to date because newest input '../database/src/tests/mongoGlobalSetup.ts' is older than output '../database/tsconfig.tsbuildinfo'
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
9:34:01 PM - Project '../keyring/tsconfig.json' is up to date because newest input '../keyring/src/errorSites.ts' is older than output '../keyring/tsconfig.tsbuildinfo'
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
9:34:01 PM - Project '../types-env/tsconfig.json' is up to date because newest input '../types-env/src/index.ts' is older than output '../types-env/tsconfig.tsbuildinfo'
|
|
61
63
|
|
|
62
|
-
|
|
64
|
+
9:34:01 PM - Project '../env/tsconfig.json' is up to date because newest input '../env/src/errorSites.ts' is older than output '../env/tsconfig.tsbuildinfo'
|
|
63
65
|
|
|
64
|
-
|
|
66
|
+
9:34:01 PM - Project '../api-express-router/tsconfig.json' is up to date because newest input '../api-express-router/src/errorHandler.ts' is older than output '../api-express-router/tsconfig.tsbuildinfo'
|
|
65
67
|
|
|
66
|
-
|
|
68
|
+
9:34:01 PM - Project '../puzzle-assets/tsconfig.json' is up to date because newest input '../puzzle-assets/src/background.ts' is older than output '../puzzle-assets/tsconfig.tsbuildinfo'
|
|
67
69
|
|
|
68
|
-
|
|
70
|
+
9:34:01 PM - Project '../audio-assets/tsconfig.json' is up to date because newest input '../audio-assets/src/distort.ts' is older than output '../audio-assets/tsconfig.tsbuildinfo'
|
|
69
71
|
|
|
70
|
-
|
|
72
|
+
9:34:01 PM - Project '../captcha-severity/tsconfig.json' is up to date because newest input '../captcha-severity/src/index.test.ts' is older than output '../captcha-severity/tsconfig.tsbuildinfo'
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
9:34:01 PM - Project '../datasets/tsconfig.json' is up to date because newest input '../datasets/src/tests/mocks/data/captchas.ts' is older than output '../datasets/tsconfig.tsbuildinfo'
|
|
73
75
|
|
|
74
|
-
|
|
76
|
+
9:34:01 PM - Project '../icon-order-assets/tsconfig.json' is up to date because newest input '../icon-order-assets/src/background.ts' is older than output '../icon-order-assets/tsconfig.tsbuildinfo'
|
|
75
77
|
|
|
76
|
-
|
|
78
|
+
9:34:01 PM - Project '../load-balancer/tsconfig.json' is up to date because newest input '../load-balancer/src/tests/productionProviderList.unit.test.ts' is older than output '../load-balancer/tsconfig.tsbuildinfo'
|
|
77
79
|
|
|
78
|
-
|
|
80
|
+
9:34:01 PM - Project '../fingerprintjs/tsconfig.json' is up to date because newest input '../fingerprintjs/src/utils/browser.ts' is older than output '../fingerprintjs/tsconfig.tsbuildinfo'
|
|
79
81
|
|
|
80
|
-
|
|
82
|
+
9:34:01 PM - Project '../fingerprint/tsconfig.json' is up to date because newest input '../fingerprint/src/index.test.ts' is older than output '../fingerprint/tsconfig.tsbuildinfo'
|
|
81
83
|
|
|
82
|
-
|
|
84
|
+
9:34:01 PM - Project '../web-bot-auth/tsconfig.json' is up to date because newest input '../web-bot-auth/src/base64.ts' is older than output '../web-bot-auth/tsconfig.tsbuildinfo'
|
|
85
|
+
|
|
86
|
+
9:34:01 PM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
|
|
87
|
+
|
|
88
|
+
9:34:01 PM - Building project '/home/runner/work/captcha/captcha/packages/provider/tsconfig.json'...
|
|
83
89
|
|
package/.turbo/turbo-build.log
CHANGED
|
@@ -26,6 +26,8 @@ ViteEsmConfig: .
|
|
|
26
26
|
'/home/runner/work/captcha/captcha/packages/datasets/tsconfig.json',
|
|
27
27
|
'/home/runner/work/captcha/captcha/packages/icon-order-assets/tsconfig.json',
|
|
28
28
|
'/home/runner/work/captcha/captcha/packages/load-balancer/tsconfig.json',
|
|
29
|
+
'/home/runner/work/captcha/captcha/packages/fingerprint/tsconfig.json',
|
|
30
|
+
'/home/runner/work/captcha/captcha/packages/fingerprintjs/tsconfig.json',
|
|
29
31
|
'/home/runner/work/captcha/captcha/packages/web-bot-auth/tsconfig.json'
|
|
30
32
|
]
|
|
31
33
|
}
|
|
@@ -54,6 +56,8 @@ ViteEsmConfig: .
|
|
|
54
56
|
'@prosopo/datasets',
|
|
55
57
|
'@prosopo/icon-order-assets',
|
|
56
58
|
'@prosopo/load-balancer',
|
|
59
|
+
'@prosopo/fingerprint',
|
|
60
|
+
'@prosopo/fingerprintjs',
|
|
57
61
|
'@prosopo/web-bot-auth'
|
|
58
62
|
]
|
|
59
63
|
}
|
|
@@ -61,7 +65,7 @@ ViteEsmConfig: .
|
|
|
61
65
|
[36mvite v8.1.6 [32mbuilding ssr environment for production...[36m[39m
|
|
62
66
|
Bundle build started
|
|
63
67
|
[2K
|
|
64
|
-
✓
|
|
68
|
+
✓ 141 modules transformed.
|
|
65
69
|
rendering chunks...
|
|
66
70
|
computing gzip size...
|
|
67
71
|
dist/_virtual/_rolldown/runtime.js 0.04 kB │ gzip: 0.06 kB
|
|
@@ -152,11 +156,9 @@ dist/tasks/puzzle/puzzleDifficulty.js 2.50 k
|
|
|
152
156
|
dist/api/forwardVerify.js 2.59 kB │ gzip: 1.10 kB
|
|
153
157
|
dist/tasks/iconOrderCaptcha/iconOrderTasks.js 2.59 kB │ gzip: 0.98 kB
|
|
154
158
|
dist/utils/mobileSignals.js 2.60 kB │ gzip: 0.97 kB
|
|
155
|
-
dist/fingerprint/dist/merkle.js 2.69 kB │ gzip: 1.08 kB
|
|
156
159
|
dist/tasks/frictionless/ipMatch.js 2.72 kB │ gzip: 1.34 kB
|
|
157
160
|
dist/api/captcha/submitImageCaptchaSolution.js 2.73 kB │ gzip: 1.07 kB
|
|
158
161
|
dist/api/admin/apiAdminRoutesProvider.js 2.78 kB │ gzip: 0.55 kB
|
|
159
|
-
dist/fingerprint/dist/summary.js 2.90 kB │ gzip: 1.27 kB
|
|
160
162
|
dist/index.js 3.04 kB │ gzip: 0.83 kB
|
|
161
163
|
dist/api/admin/apiDnsEventEndpoint.js 3.05 kB │ gzip: 1.18 kB
|
|
162
164
|
dist/tasks/detection/getBotScore.js 3.29 kB │ gzip: 1.32 kB
|
|
@@ -170,7 +172,6 @@ dist/tasks/puzzleCaptcha/puzzleTasks.js 3.67 k
|
|
|
170
172
|
dist/tasks/spam/evaluateEmailSpamRules.js 3.84 kB │ gzip: 1.59 kB
|
|
171
173
|
dist/api/admin/apiToggleMaintenanceModeEndpoint.js 3.85 kB │ gzip: 1.44 kB
|
|
172
174
|
dist/compositeIpAddress.js 3.87 kB │ gzip: 1.66 kB
|
|
173
|
-
dist/fingerprint/dist/proof.js 3.96 kB │ gzip: 1.64 kB
|
|
174
175
|
dist/tasks/tasks.js 3.98 kB │ gzip: 1.09 kB
|
|
175
176
|
dist/services/ipComparison.js 4.04 kB │ gzip: 1.21 kB
|
|
176
177
|
dist/tasks/spam/checkSpamEmail.js 4.12 kB │ gzip: 1.12 kB
|
|
@@ -194,7 +195,7 @@ dist/api/healthzGeo.js 6.86 k
|
|
|
194
195
|
dist/tasks/spam/checkTrafficFilter.js 8.49 kB │ gzip: 2.84 kB
|
|
195
196
|
dist/tasks/detection/bundlePool.js 8.86 kB │ gzip: 3.34 kB
|
|
196
197
|
dist/api/captcha/getFrictionlessCaptchaChallenge/decisionMachine.js 9.52 kB │ gzip: 1.85 kB
|
|
197
|
-
dist/api/captcha/submitPoWCaptchaSolution.js 9.
|
|
198
|
+
dist/api/captcha/submitPoWCaptchaSolution.js 9.70 kB │ gzip: 2.92 kB
|
|
198
199
|
dist/api/startProviderApi.js 10.42 kB │ gzip: 3.58 kB
|
|
199
200
|
dist/tasks/client/clientTasks.js 12.17 kB │ gzip: 3.24 kB
|
|
200
201
|
dist/tasks/decisionMachine/decisionMachineRunner.js 12.17 kB │ gzip: 3.84 kB
|
|
@@ -209,7 +210,7 @@ dist/tasks/powCaptcha/powTasks.js 25.37 k
|
|
|
209
210
|
dist/tasks/captchaManager.js 25.56 kB │ gzip: 7.55 kB
|
|
210
211
|
dist/tasks/imgCaptcha/imgCaptchaTasks.js 27.89 kB │ gzip: 6.60 kB
|
|
211
212
|
|
|
212
|
-
[32m✓ built in
|
|
213
|
+
[32m✓ built in 230ms[39m
|
|
213
214
|
[copy-plugin] copying /home/runner/work/captcha/captcha/packages/provider/src/tasks/detection/decodeBehavior.js to /home/runner/work/captcha/captcha/packages/provider/dist/tasks/detection/decodeBehavior.js
|
|
214
215
|
[copy-plugin] copying /home/runner/work/captcha/captcha/packages/provider/src/tasks/detection/decodePayload.js to /home/runner/work/captcha/captcha/packages/provider/dist/tasks/detection/decodePayload.js
|
|
215
216
|
[copy-plugin] copying /home/runner/work/captcha/captcha/packages/provider/src/tasks/detection/decodeSimd.js to /home/runner/work/captcha/captcha/packages/provider/dist/tasks/detection/decodeSimd.js
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @prosopo/provider
|
|
2
2
|
|
|
3
|
+
## 5.20.2
|
|
4
|
+
### Patch Changes
|
|
5
|
+
|
|
6
|
+
- 749fe8a: Finish holding express at 4, and build `@prosopo/fingerprint` before the
|
|
7
|
+
provider that imports it.
|
|
8
|
+
|
|
9
|
+
v3.8.37 pinned `@prosopo/locale` back to express 4 because the i18next
|
|
10
|
+
middleware has no express 5 typings, but left `provider`, `cli`,
|
|
11
|
+
`api-express-router` and the two demos on express 5. That split the workspace:
|
|
12
|
+
`provider` takes the middleware handler from `locale`, which is now typed for
|
|
13
|
+
express 4, and hands it to its own express 5 `app.use`, which does not accept
|
|
14
|
+
it. All six are on express 4 now.
|
|
15
|
+
|
|
16
|
+
Separately, `packages/provider` gained a dependency on `@prosopo/fingerprint`
|
|
17
|
+
without a matching tsconfig project reference, so `tsc --build` did not build
|
|
18
|
+
it first. A full build hid this because something else built fingerprint
|
|
19
|
+
earlier; a partial build of just the packages a consumer needs did not, and
|
|
20
|
+
failed with "Cannot find module '@prosopo/fingerprint/summary'". The reference
|
|
21
|
+
is now declared.
|
|
22
|
+
|
|
23
|
+
Lift the express pins together with the dependabot ignore once the middleware
|
|
24
|
+
ships express 5 typings.
|
|
25
|
+
- Updated dependencies [749fe8a]
|
|
26
|
+
- @prosopo/api-express-router@3.3.2
|
|
27
|
+
|
|
3
28
|
## 5.20.1
|
|
4
29
|
### Patch Changes
|
|
5
30
|
|
|
@@ -7,12 +7,12 @@ import { Tasks } from "../../tasks/tasks.js";
|
|
|
7
7
|
import { getMaintenanceMode } from "../admin/apiToggleMaintenanceModeEndpoint.js";
|
|
8
8
|
import { resolveTestSiteKeyVerdict } from "../testSiteKey.js";
|
|
9
9
|
import { summariseRequestBody } from "../requestBodySummary.js";
|
|
10
|
-
import { summariseFingerprintProof } from "../../fingerprint/dist/summary.js";
|
|
11
10
|
import { ProsopoError, isProsopoError, isSevereError } from "@prosopo/common";
|
|
12
11
|
import { CaptchaType, SubmitPowCaptchaSolutionBody, imageMaxRoundsDefault, resolveAllowedCaptchaTypes } from "@prosopo/types";
|
|
13
12
|
import { flatten, getIPAddress } from "@prosopo/util";
|
|
14
13
|
import { resolveMaxEscalationLevel, severityToPuzzleDifficulty } from "@prosopo/captcha-severity";
|
|
15
14
|
import { DEFAULT_RENDER_SETTINGS } from "@prosopo/puzzle-assets";
|
|
15
|
+
import { summariseFingerprintProof } from "@prosopo/fingerprint/summary";
|
|
16
16
|
//#region src/api/captcha/submitPoWCaptchaSolution.ts
|
|
17
17
|
var submitPoWCaptchaSolution_default = (env) => async (req, res, next) => {
|
|
18
18
|
if (getMaintenanceMode()) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prosopo/provider",
|
|
3
|
-
"version": "5.20.
|
|
3
|
+
"version": "5.20.2",
|
|
4
4
|
"author": "PROSOPO LIMITED <info@prosopo.io>",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"@noble/hashes": "2.4.0",
|
|
12
12
|
"@polkadot/util": "14.0.3",
|
|
13
13
|
"@prosopo/api": "4.7.5",
|
|
14
|
-
"@prosopo/api-express-router": "3.3.
|
|
14
|
+
"@prosopo/api-express-router": "3.3.2",
|
|
15
15
|
"@prosopo/api-route": "2.6.65",
|
|
16
16
|
"@prosopo/audio-assets": "0.2.2",
|
|
17
17
|
"@prosopo/captcha-severity": "1.3.3",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@prosopo/util-crypto": "13.6.1",
|
|
40
40
|
"@prosopo/web-bot-auth": "0.1.4",
|
|
41
41
|
"cron": "3.1.7",
|
|
42
|
-
"express": "
|
|
42
|
+
"express": "4.22.2",
|
|
43
43
|
"express-rate-limit": "7.4.0",
|
|
44
44
|
"geolib": "4.0.0",
|
|
45
45
|
"i18next": "26.4.4",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@noble/curves": "2.4.0",
|
|
54
54
|
"@prosopo/config": "3.5.0",
|
|
55
55
|
"@types/cors": "2.8.19",
|
|
56
|
-
"@types/express": "
|
|
56
|
+
"@types/express": "4.17.25",
|
|
57
57
|
"@types/node": "22.5.5",
|
|
58
58
|
"@types/pg": "8.23.1",
|
|
59
59
|
"@types/uuid": "11.0.0",
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { hexHashArray } from "@prosopo/util-crypto";
|
|
2
|
-
//#region ../fingerprint/dist/merkle.js
|
|
3
|
-
var at = (arr, index) => {
|
|
4
|
-
const value = arr[index];
|
|
5
|
-
if (value === void 0) throw new Error(`merkle: index ${index} out of range (length ${arr.length})`);
|
|
6
|
-
return value;
|
|
7
|
-
};
|
|
8
|
-
/** Hash a pair of child hashes into their parent. */
|
|
9
|
-
var hashMerklePair = (left, right) => hexHashArray([left, right]);
|
|
10
|
-
/**
|
|
11
|
-
* Build every layer of the Merkle tree, bottom-up. Layer 0 is the leaf hashes,
|
|
12
|
-
* the final layer is `[root]`. An odd node at the end of a layer is paired with
|
|
13
|
-
* itself.
|
|
14
|
-
*/
|
|
15
|
-
var buildMerkleLayers = (leafHashes) => {
|
|
16
|
-
if (leafHashes.length === 0) throw new Error("merkle: cannot build a tree with no leaves");
|
|
17
|
-
const layers = [[...leafHashes]];
|
|
18
|
-
let current = leafHashes;
|
|
19
|
-
while (current.length > 1) {
|
|
20
|
-
const next = [];
|
|
21
|
-
for (let i = 0; i < current.length; i += 2) {
|
|
22
|
-
const left = at(current, i);
|
|
23
|
-
const right = i + 1 < current.length ? at(current, i + 1) : left;
|
|
24
|
-
next.push(hashMerklePair(left, right));
|
|
25
|
-
}
|
|
26
|
-
layers.push(next);
|
|
27
|
-
current = next;
|
|
28
|
-
}
|
|
29
|
-
return layers;
|
|
30
|
-
};
|
|
31
|
-
var merkleRootFromLayers = (layers) => at(at(layers, layers.length - 1), 0);
|
|
32
|
-
/** Produce the sibling path proving `leafHash` belongs to the tree. */
|
|
33
|
-
var 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) throw new Error("merkle: leaf hash not present in layer");
|
|
40
|
-
let partnerIndex = index % 2 === 1 ? index - 1 : index + 1;
|
|
41
|
-
if (partnerIndex > layer.length - 1) partnerIndex = index;
|
|
42
|
-
const partner = at(layer, partnerIndex);
|
|
43
|
-
const pair = partnerIndex > index ? [hash, partner] : [partner, hash];
|
|
44
|
-
proof.push(pair);
|
|
45
|
-
hash = hashMerklePair(pair[0], pair[1]);
|
|
46
|
-
}
|
|
47
|
-
return [...proof, [merkleRootFromLayers(layers)]];
|
|
48
|
-
};
|
|
49
|
-
/** Verify a leaf + sibling path recomputes to the proof's embedded root. */
|
|
50
|
-
var verifyMerkleProof = (leafHash, proof) => {
|
|
51
|
-
try {
|
|
52
|
-
const firstLayer = proof[0];
|
|
53
|
-
if (firstLayer === void 0 || firstLayer.indexOf(leafHash) === -1) return false;
|
|
54
|
-
if (proof.length === 1) return at(firstLayer, 0) === leafHash;
|
|
55
|
-
const root = at(at(proof, proof.length - 1), 0);
|
|
56
|
-
let hash = leafHash;
|
|
57
|
-
for (let i = 0; i < proof.length - 1; i++) {
|
|
58
|
-
const layer = at(proof, i);
|
|
59
|
-
if (layer.indexOf(hash) === -1) return false;
|
|
60
|
-
hash = hashMerklePair(at(layer, 0), at(layer, 1));
|
|
61
|
-
if (at(proof, i + 1).indexOf(hash) === -1) return false;
|
|
62
|
-
}
|
|
63
|
-
return hash === root;
|
|
64
|
-
} catch {
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
//#endregion
|
|
69
|
-
export { buildMerkleLayers, hashMerklePair, merkleProofFromLayers, merkleRootFromLayers, verifyMerkleProof };
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { buildMerkleLayers, merkleProofFromLayers, merkleRootFromLayers, verifyMerkleProof } from "./merkle.js";
|
|
2
|
-
import { hexHash } from "@prosopo/util-crypto";
|
|
3
|
-
/**
|
|
4
|
-
* The fixed set of components the client discloses in a proof of fingerprint.
|
|
5
|
-
* Disclosing every component (the previous default) made the proof enormous —
|
|
6
|
-
* each disclosure carries a full Merkle path and its raw value, and components
|
|
7
|
-
* like webgl/audio/fonts have very large values. Selective disclosure keeps the
|
|
8
|
-
* commitment (`root`) over the whole component set while only these cheap,
|
|
9
|
-
* stable scalar components carry a path + value, shrinking the payload ~10x.
|
|
10
|
-
*
|
|
11
|
-
* The provider-side validator's bounds MUST be a subset of these keys: a bounded
|
|
12
|
-
* key that isn't disclosed would always fail validation as `missing:<key>`.
|
|
13
|
-
*/
|
|
14
|
-
var FINGERPRINT_DISCLOSURE_KEYS = [
|
|
15
|
-
"colorDepth",
|
|
16
|
-
"cookiesEnabled",
|
|
17
|
-
"sessionStorage",
|
|
18
|
-
"localStorage",
|
|
19
|
-
"timezone",
|
|
20
|
-
"hardwareConcurrency",
|
|
21
|
-
"languages",
|
|
22
|
-
"architecture",
|
|
23
|
-
"deviceBucket"
|
|
24
|
-
];
|
|
25
|
-
var escapeKey = (key) => key.replace(/([:|\\])/g, "\\$1");
|
|
26
|
-
var componentLeafContent = (key, component) => {
|
|
27
|
-
const serialized = "error" in component ? "error" : JSON.stringify(component.value);
|
|
28
|
-
return `${escapeKey(key)}:${serialized}`;
|
|
29
|
-
};
|
|
30
|
-
var disclosureLeafContent = (disclosure) => {
|
|
31
|
-
const serialized = disclosure.error ? "error" : JSON.stringify(disclosure.value);
|
|
32
|
-
return `${escapeKey(disclosure.key)}:${serialized}`;
|
|
33
|
-
};
|
|
34
|
-
var leafHashForContent = (content) => hexHash(content);
|
|
35
|
-
/**
|
|
36
|
-
* Build a {@link FingerprintProof} from an already-resolved FingerprintJS
|
|
37
|
-
* components map. The commitment always covers every component (in sorted key
|
|
38
|
-
* order); `discloseKeys` selects which components are revealed (defaulting to
|
|
39
|
-
* all). Keys that are not present in the fingerprint are skipped — a validator
|
|
40
|
-
* should treat an expected-but-absent disclosure as a failure.
|
|
41
|
-
*/
|
|
42
|
-
var buildFingerprintProofFromComponents = (components, discloseKeys) => {
|
|
43
|
-
const keys = Object.keys(components).sort();
|
|
44
|
-
if (keys.length === 0) throw new Error("fingerprint proof: no components to commit to");
|
|
45
|
-
const leafHashes = keys.map((key) => {
|
|
46
|
-
const component = components[key];
|
|
47
|
-
if (component === void 0) throw new Error(`fingerprint proof: missing component ${key}`);
|
|
48
|
-
return leafHashForContent(componentLeafContent(key, component));
|
|
49
|
-
});
|
|
50
|
-
const layers = buildMerkleLayers(leafHashes);
|
|
51
|
-
const root = merkleRootFromLayers(layers);
|
|
52
|
-
const disclose = discloseKeys ?? keys;
|
|
53
|
-
const disclosures = [];
|
|
54
|
-
for (const key of disclose) {
|
|
55
|
-
const index = keys.indexOf(key);
|
|
56
|
-
if (index === -1) continue;
|
|
57
|
-
const component = components[key];
|
|
58
|
-
const leafHash = leafHashes[index];
|
|
59
|
-
if (component === void 0 || leafHash === void 0) continue;
|
|
60
|
-
const proof = merkleProofFromLayers(layers, leafHash);
|
|
61
|
-
disclosures.push("error" in component ? {
|
|
62
|
-
key,
|
|
63
|
-
error: true,
|
|
64
|
-
proof
|
|
65
|
-
} : {
|
|
66
|
-
key,
|
|
67
|
-
value: component.value,
|
|
68
|
-
proof
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
return {
|
|
72
|
-
v: 1,
|
|
73
|
-
root,
|
|
74
|
-
disclosures
|
|
75
|
-
};
|
|
76
|
-
};
|
|
77
|
-
/**
|
|
78
|
-
* Structural verification of a proof: every disclosed `(key, value)` re-hashes
|
|
79
|
-
* to a leaf that is proven to belong to the single committed `root`. This is
|
|
80
|
-
* the non-secret half of validation — the value-bounding rules live in the
|
|
81
|
-
* provider-side (closed-source) validator and are layered on top of this.
|
|
82
|
-
*/
|
|
83
|
-
var verifyFingerprintProofStructure = (proof) => {
|
|
84
|
-
if (proof.v !== 1) return false;
|
|
85
|
-
if (typeof proof.root !== "string" || proof.disclosures.length === 0) return false;
|
|
86
|
-
for (const disclosure of proof.disclosures) {
|
|
87
|
-
if (!verifyMerkleProof(leafHashForContent(disclosureLeafContent(disclosure)), disclosure.proof)) return false;
|
|
88
|
-
const rootLayer = disclosure.proof[disclosure.proof.length - 1];
|
|
89
|
-
if (rootLayer === void 0 || rootLayer[0] !== proof.root) return false;
|
|
90
|
-
}
|
|
91
|
-
return true;
|
|
92
|
-
};
|
|
93
|
-
var encodeFingerprintProof = (proof) => JSON.stringify(proof);
|
|
94
|
-
//#endregion
|
|
95
|
-
export { FINGERPRINT_DISCLOSURE_KEYS, buildFingerprintProofFromComponents, encodeFingerprintProof, leafHashForContent, verifyFingerprintProofStructure };
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { verifyFingerprintProofStructure } from "./proof.js";
|
|
2
|
-
import { hexHash } from "@prosopo/util-crypto";
|
|
3
|
-
//#region ../fingerprint/dist/summary.js
|
|
4
|
-
/**
|
|
5
|
-
* The disclosed keys that are fixed by the installation and the host. A hash
|
|
6
|
-
* over them names a cohort of devices.
|
|
7
|
-
*
|
|
8
|
-
* `colorDepth` and `hardwareConcurrency` are disclosed too but kept out of the
|
|
9
|
-
* hash and stored beside it, so that the values can be read per cohort rather
|
|
10
|
-
* than only folded into it.
|
|
11
|
-
*/
|
|
12
|
-
var GROUP_KEYS = [
|
|
13
|
-
"cookiesEnabled",
|
|
14
|
-
"sessionStorage",
|
|
15
|
-
"localStorage",
|
|
16
|
-
"timezone",
|
|
17
|
-
"languages",
|
|
18
|
-
"architecture"
|
|
19
|
-
];
|
|
20
|
-
var asNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
21
|
-
/**
|
|
22
|
-
* Reduce an encoded proof to the fields worth storing, or `undefined` when it
|
|
23
|
-
* is absent, unparseable, or fails structural verification.
|
|
24
|
-
*
|
|
25
|
-
* Structural verification is not optional here: an unverified disclosure is a
|
|
26
|
-
* client-asserted value with a decorative Merkle path beside it, and storing
|
|
27
|
-
* one would put a forgeable field into an aggregation that reads as
|
|
28
|
-
* tamper-evident. Whether the values are *plausible* is a separate concern and
|
|
29
|
-
* stays in the routing machine's validator; this only refuses what does not
|
|
30
|
-
* hash together.
|
|
31
|
-
*/
|
|
32
|
-
var summariseFingerprintProof = (encoded) => {
|
|
33
|
-
if (!encoded) return void 0;
|
|
34
|
-
let proof;
|
|
35
|
-
try {
|
|
36
|
-
proof = JSON.parse(encoded);
|
|
37
|
-
} catch {
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
if (typeof proof !== "object" || proof === null || typeof proof.root !== "string" || !Array.isArray(proof.disclosures)) return;
|
|
41
|
-
if (!verifyFingerprintProofStructure(proof)) return void 0;
|
|
42
|
-
const byKey = /* @__PURE__ */ new Map();
|
|
43
|
-
for (const disclosure of proof.disclosures) if (!disclosure.error) byKey.set(disclosure.key, disclosure.value);
|
|
44
|
-
const groupInput = GROUP_KEYS.map((key) => `${key}:${JSON.stringify(byKey.get(key) ?? null)}`).join("|");
|
|
45
|
-
const disclosed = {};
|
|
46
|
-
const timezone = byKey.get("timezone");
|
|
47
|
-
if (typeof timezone === "string") disclosed.timezone = timezone;
|
|
48
|
-
const languages = byKey.get("languages");
|
|
49
|
-
if (languages !== void 0) disclosed.languages = JSON.stringify(languages);
|
|
50
|
-
const architecture = asNumber(byKey.get("architecture"));
|
|
51
|
-
if (architecture !== void 0) disclosed.architecture = architecture;
|
|
52
|
-
for (const key of [
|
|
53
|
-
"cookiesEnabled",
|
|
54
|
-
"sessionStorage",
|
|
55
|
-
"localStorage"
|
|
56
|
-
]) {
|
|
57
|
-
const value = byKey.get(key);
|
|
58
|
-
if (typeof value === "boolean") disclosed[key] = value;
|
|
59
|
-
}
|
|
60
|
-
const bucketId = byKey.get("deviceBucket");
|
|
61
|
-
const colorDepth = asNumber(byKey.get("colorDepth"));
|
|
62
|
-
const hardwareConcurrency = asNumber(byKey.get("hardwareConcurrency"));
|
|
63
|
-
return {
|
|
64
|
-
root: proof.root,
|
|
65
|
-
groupHash: hexHash(groupInput),
|
|
66
|
-
...typeof bucketId === "string" && bucketId !== "" && { bucketId },
|
|
67
|
-
...colorDepth !== void 0 && { colorDepth },
|
|
68
|
-
...hardwareConcurrency !== void 0 && { hardwareConcurrency },
|
|
69
|
-
...Object.keys(disclosed).length > 0 && { disclosed }
|
|
70
|
-
};
|
|
71
|
-
};
|
|
72
|
-
//#endregion
|
|
73
|
-
export { summariseFingerprintProof };
|