@emilia-protocol/verify 1.0.0 → 1.0.1
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/index.js +37 -2
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -27,8 +27,43 @@ function sha256(input) {
|
|
|
27
27
|
return crypto.createHash('sha256').update(input, 'utf8').digest('hex');
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
// Recursive canonical JSON — depth-first key sort at every level.
|
|
31
|
+
//
|
|
32
|
+
// The previous implementation
|
|
33
|
+
//
|
|
34
|
+
// JSON.stringify(obj, Object.keys(obj).sort())
|
|
35
|
+
//
|
|
36
|
+
// was a SHALLOW canonicalization. The second argument to JSON.stringify
|
|
37
|
+
// in array form is a property allowlist filter, NOT a sort order, and it
|
|
38
|
+
// does NOT recurse into nested objects to enforce key order at depth.
|
|
39
|
+
// Worse, it filters nested keys to only those names present in the
|
|
40
|
+
// top-level allowlist.
|
|
41
|
+
//
|
|
42
|
+
// Net effect of the shallow pattern: a verifier and a signer that both
|
|
43
|
+
// "sort keys before signing" could compute different canonical bytes for
|
|
44
|
+
// the same logical document, producing a false-negative signature
|
|
45
|
+
// failure. And nested fields (e.g. claim.context.risk_signals or
|
|
46
|
+
// claim.context.change.after_bank_hash) were not deterministically
|
|
47
|
+
// included in the signed material under the shallow algorithm.
|
|
48
|
+
//
|
|
49
|
+
// The fix below is the same recursive canonicalize() used by
|
|
50
|
+
// lib/guard-policies.js (hashCanonicalAction) on the server side, so
|
|
51
|
+
// signer and verifier produce byte-identical canonical material for any
|
|
52
|
+
// arbitrarily-nested object.
|
|
53
|
+
//
|
|
54
|
+
// Bug history: shipped in 1.0.0, fixed in 1.0.1. See package.json.
|
|
55
|
+
function canonicalize(value) {
|
|
56
|
+
if (value === null || value === undefined) return JSON.stringify(value);
|
|
57
|
+
if (Array.isArray(value)) {
|
|
58
|
+
return `[${value.map(canonicalize).join(',')}]`;
|
|
59
|
+
}
|
|
60
|
+
if (typeof value === 'object') {
|
|
61
|
+
return `{${Object.keys(value)
|
|
62
|
+
.sort()
|
|
63
|
+
.map((k) => JSON.stringify(k) + ':' + canonicalize(value[k]))
|
|
64
|
+
.join(',')}}`;
|
|
65
|
+
}
|
|
66
|
+
return JSON.stringify(value);
|
|
32
67
|
}
|
|
33
68
|
|
|
34
69
|
function hashPair(a, b) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@emilia-protocol/verify",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Zero-dependency standalone verification for EP trust receipts, Merkle anchors, and commitment proofs. Uses only Node.js built-in crypto. No EP infrastructure required.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|