@forestrie/receipt-verify 0.5.0 → 0.5.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.
@@ -1 +1 @@
1
- {"version":3,"file":"build-receipt-offline.d.ts","sourceRoot":"","sources":["../src/build-receipt-offline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAIL,mBAAmB,EAEnB,KAAK,eAAe,EAErB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,oBAAoB,CAAC;AAQ5B;;;;GAIG;AACH,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAC/B,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,oEAAoE;IACpE,YAAY,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,wEAAwE;IACxE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,cAAc,EAAE,UAAU,GAAG,IAAI,CAAC;CACnC,CAAC;AAEF,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,eAAe,EAAE,UAAU,GAAG,gBAAgB,CAqB7E;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,WAAW,EAAE,UAAU,CAAC;IACxB,eAAe,EAAE,UAAU,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,wBAAwB,GAC9B,UAAU,CA2EZ;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,mEAAmE;IACnE,IAAI,EAAE,UAAU,CAAC;IACjB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,SAAS,EAAE,UAAU,CAAC;CACvB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,WAAW,EAAE,UAAU,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAwBnC"}
1
+ {"version":3,"file":"build-receipt-offline.d.ts","sourceRoot":"","sources":["../src/build-receipt-offline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,OAAO,EAIL,mBAAmB,EAEnB,KAAK,eAAe,EAErB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,oBAAoB,CAAC;AAQ5B;;;;GAIG;AACH,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAC/B,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,oEAAoE;IACpE,YAAY,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,wEAAwE;IACxE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,cAAc,EAAE,UAAU,GAAG,IAAI,CAAC;CACnC,CAAC;AAEF,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,eAAe,EAAE,UAAU,GAAG,gBAAgB,CAqB7E;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,WAAW,EAAE,UAAU,CAAC;IACxB,eAAe,EAAE,UAAU,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,wBAAwB,GAC9B,UAAU,CA2EZ;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,mEAAmE;IACnE,IAAI,EAAE,UAAU,CAAC;IACjB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,SAAS,EAAE,UAAU,CAAC;CACvB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,WAAW,EAAE,UAAU,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAwBnC"}
@@ -14,7 +14,7 @@
14
14
  * at an externally attested tree size (e.g. Univocity `logState` on Base
15
15
  * Sepolia) and compare the computed peak with the published accumulator.
16
16
  */
17
- import { decode as decodeCbor, encode as encodeCbor } from "cbor-x";
17
+ import { decodeCborDeterministic, encodeCborDeterministic, } from "@forestrie/encoding";
18
18
  import { calculateRoot, inclusionProof, massifIndexFromMMRIndex, openMassifNodeStore, peakIndexForLeafProof, } from "@forestrie/merklelog";
19
19
  import { requireCoseSign1, toHeaderMap, unwrapCoseSign1Tag, } from "./parse-receipt.js";
20
20
  import { SubtleHasher } from "./subtle-hasher.js";
@@ -30,7 +30,7 @@ const VDP_CONSISTENCY_PROOF_KEY = -2;
30
30
  export { openMassifNodeStore };
31
31
  /** Parse a format-v3 checkpoint (`.sth`) COSE Sign1. */
32
32
  export function parseCheckpoint(checkpointBytes) {
33
- const decoded = decodeCbor(checkpointBytes);
33
+ const decoded = decodeCborDeterministic(checkpointBytes);
34
34
  const coseSign1 = requireCoseSign1(unwrapCoseSign1Tag(decoded));
35
35
  const unprotected = toHeaderMap(coseSign1[1]);
36
36
  const peakReceiptsRaw = unprotected.get(SEAL_PEAK_RECEIPTS_LABEL);
@@ -84,7 +84,7 @@ export function buildReceiptOffline(input) {
84
84
  if (!(receiptBytes instanceof Uint8Array)) {
85
85
  throw new Error(`checkpoint peak receipt slot ${peakIdx} is missing or not bstr`);
86
86
  }
87
- const receiptSign1 = requireCoseSign1(unwrapCoseSign1Tag(decodeCbor(receiptBytes)));
87
+ const receiptSign1 = requireCoseSign1(unwrapCoseSign1Tag(decodeCborDeterministic(receiptBytes)));
88
88
  const receiptUnprotected = toHeaderMap(receiptSign1[1]);
89
89
  if (checkpoint.delegationCert) {
90
90
  receiptUnprotected.set(DELEGATION_CERT_LABEL, checkpoint.delegationCert);
@@ -134,10 +134,7 @@ export async function computeAccumulatorPeak(opts) {
134
134
  }
135
135
  // --- helpers ---
136
136
  function cborBytes(value) {
137
- const encoded = encodeCbor(value);
138
- return encoded instanceof Uint8Array
139
- ? encoded
140
- : new Uint8Array(encoded);
137
+ return encodeCborDeterministic(value);
141
138
  }
142
139
  /**
143
140
  * Sealed mmr size from a format-v3 checkpoint: tree-size-2 of the consistency
@@ -152,7 +149,7 @@ function sealedSizeFromCheckpoint(unprotected) {
152
149
  const proofBstr = vdp.get(VDP_CONSISTENCY_PROOF_KEY);
153
150
  if (!(proofBstr instanceof Uint8Array))
154
151
  return null;
155
- const proof = decodeCbor(proofBstr);
152
+ const proof = decodeCborDeterministic(proofBstr);
156
153
  if (!Array.isArray(proof) || proof.length < 2)
157
154
  return null;
158
155
  const treeSize2 = proof[1];
@@ -1,5 +1,5 @@
1
1
  import { sha256 } from "@noble/hashes/sha256";
2
- import { decode as decodeCbor } from "cbor-x";
2
+ import { decodeCborDeterministic } from "@forestrie/encoding";
3
3
  import { HEADER_FORESTRIE_GRANT_V0, HEADER_IDTIMESTAMP, } from "./forest-genesis-labels.js";
4
4
  import { decodeGrantPayload } from "./grant-codec.js";
5
5
  const IDTIMESTAMP_BYTES = 8;
@@ -31,7 +31,7 @@ function digestEquals(a, b) {
31
31
  * Decode Forestrie-Grant COSE Sign1 (Custodian transparent statement profile).
32
32
  */
33
33
  export function decodeForestrieGrantCose(bytes) {
34
- const raw = decodeCbor(bytes);
34
+ const raw = decodeCborDeterministic(bytes);
35
35
  const arr = Array.isArray(raw) ? raw : null;
36
36
  if (!arr || arr.length !== 4) {
37
37
  throw new Error("Forestrie-Grant must be COSE Sign1 (array of 4)");
@@ -1,4 +1,4 @@
1
- import { decode as decodeCbor } from "cbor-x";
1
+ import { decodeCborDeterministic } from "@forestrie/encoding";
2
2
  import { COSE_ALG_ES256, COSE_CRV_P256, COSE_EC2_CRV, COSE_EC2_X, COSE_EC2_Y, COSE_KEY_ALG, COSE_KEY_KTY, COSE_KTY_EC2, } from "./cose-key.js";
3
3
  import { FOREST_GENESIS_LABEL_BOOTSTRAP_KEY, FOREST_GENESIS_LABEL_GENESIS_ALG, FOREST_GENESIS_LABEL_GENESIS_VERSION, FOREST_GENESIS_SCHEMA_V1, FOREST_GENESIS_SCHEMA_V2, } from "./forest-genesis-labels.js";
4
4
  import { decodeTrustRootCbor } from "./decode-trust-root-cbor.js";
@@ -26,7 +26,7 @@ function asGenesisUint8Array(v) {
26
26
  export async function decodeTrustRootFromGenesis(genesisCbor) {
27
27
  let raw;
28
28
  try {
29
- raw = decodeCbor(genesisCbor);
29
+ raw = decodeCborDeterministic(genesisCbor);
30
30
  }
31
31
  catch {
32
32
  throw new Error("genesis CBOR decode failed");
@@ -1 +1 @@
1
- {"version":3,"file":"grant-codec.d.ts","sourceRoot":"","sources":["../src/grant-codec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAuDjD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,KAAK,CAO3D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG;IACtD,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,UAAU,CAAC;CACzB,CAsBA;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,UAAU,CAa3D"}
1
+ {"version":3,"file":"grant-codec.d.ts","sourceRoot":"","sources":["../src/grant-codec.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAuDjD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,KAAK,CAO3D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG;IACtD,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,UAAU,CAAC;CACzB,CAsBA;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,UAAU,CAa3D"}
@@ -1,4 +1,4 @@
1
- import { decode as decodeCbor, encode as encodeCbor } from "cbor-x";
1
+ import { decodeCborDeterministic, encodeCborDeterministic, } from "@forestrie/encoding";
2
2
  import { grantDataToBytes } from "@forestrie/encoding";
3
3
  import { fromPaddedWire32, toPaddedWire32 } from "./uuid-bytes.js";
4
4
  const CBOR_KEY_IDTIMESTAMP = 0;
@@ -48,14 +48,14 @@ function mapToGrant(m) {
48
48
  export function decodeGrantPayload(bytes) {
49
49
  if (!bytes?.length)
50
50
  throw new Error("Grant payload is empty");
51
- const raw = decodeCbor(bytes);
51
+ const raw = decodeCborDeterministic(bytes);
52
52
  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
53
53
  throw new Error("Grant payload must be a CBOR map");
54
54
  }
55
55
  return mapToGrant(raw);
56
56
  }
57
57
  export function decodeGrantResponse(bytes) {
58
- const raw = decodeCbor(bytes);
58
+ const raw = decodeCborDeterministic(bytes);
59
59
  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
60
60
  throw new Error("Grant response must be a CBOR map");
61
61
  }
@@ -84,5 +84,5 @@ export function encodeGrantPayload(grant) {
84
84
  grantDataToBytes(grant.grantData ?? new Uint8Array(0)),
85
85
  ],
86
86
  ]);
87
- return new Uint8Array(encodeCbor(map));
87
+ return encodeCborDeterministic(map);
88
88
  }
@@ -1,4 +1,4 @@
1
- import { decode as decodeCbor } from "cbor-x";
1
+ import { decodeCborDeterministic } from "@forestrie/encoding";
2
2
  const VDS_COSE_RECEIPT_PROOFS_TAG = 396;
3
3
  export function unwrapCoseSign1Tag(value) {
4
4
  if (value && typeof value === "object" && !(value instanceof Map)) {
@@ -42,7 +42,7 @@ export function toHeaderMap(value) {
42
42
  return out;
43
43
  }
44
44
  export function parseReceipt(receiptBytes) {
45
- const decoded = decodeCbor(receiptBytes);
45
+ const decoded = decodeCborDeterministic(receiptBytes);
46
46
  const unwrapped = unwrapCoseSign1Tag(decoded);
47
47
  requireCoseSign1(unwrapped);
48
48
  const coseSign1 = requireCoseSign1(unwrapped);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forestrie/receipt-verify",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Offline SCITT grant receipt verification (ADR-0045)",
@@ -28,9 +28,8 @@
28
28
  ],
29
29
  "dependencies": {
30
30
  "@noble/hashes": "^1.7.1",
31
- "cbor-x": "^1.5.9",
32
31
  "@forestrie/merklelog": "0.1.0",
33
- "@forestrie/encoding": "0.2.0"
32
+ "@forestrie/encoding": "0.3.0"
34
33
  },
35
34
  "devDependencies": {
36
35
  "esbuild": "^0.24.0",
@@ -15,7 +15,10 @@
15
15
  * Sepolia) and compare the computed peak with the published accumulator.
16
16
  */
17
17
 
18
- import { decode as decodeCbor, encode as encodeCbor } from "cbor-x";
18
+ import {
19
+ decodeCborDeterministic,
20
+ encodeCborDeterministic,
21
+ } from "@forestrie/encoding";
19
22
  import {
20
23
  calculateRoot,
21
24
  inclusionProof,
@@ -58,7 +61,7 @@ export type ParsedCheckpoint = {
58
61
 
59
62
  /** Parse a format-v3 checkpoint (`.sth`) COSE Sign1. */
60
63
  export function parseCheckpoint(checkpointBytes: Uint8Array): ParsedCheckpoint {
61
- const decoded = decodeCbor(checkpointBytes) as unknown;
64
+ const decoded = decodeCborDeterministic(checkpointBytes);
62
65
  const coseSign1 = requireCoseSign1(unwrapCoseSign1Tag(decoded));
63
66
  const unprotected = toHeaderMap(coseSign1[1]);
64
67
 
@@ -143,7 +146,7 @@ export function buildReceiptOffline(
143
146
  }
144
147
 
145
148
  const receiptSign1 = requireCoseSign1(
146
- unwrapCoseSign1Tag(decodeCbor(receiptBytes) as unknown),
149
+ unwrapCoseSign1Tag(decodeCborDeterministic(receiptBytes)),
147
150
  );
148
151
  const receiptUnprotected = toHeaderMap(receiptSign1[1]);
149
152
 
@@ -220,10 +223,7 @@ export async function computeAccumulatorPeak(opts: {
220
223
  // --- helpers ---
221
224
 
222
225
  function cborBytes(value: unknown): Uint8Array {
223
- const encoded = encodeCbor(value);
224
- return encoded instanceof Uint8Array
225
- ? encoded
226
- : new Uint8Array(encoded as ArrayLike<number>);
226
+ return encodeCborDeterministic(value);
227
227
  }
228
228
 
229
229
  /**
@@ -239,7 +239,7 @@ function sealedSizeFromCheckpoint(
239
239
  const vdp = toHeaderMap(vdpRaw as Map<number, unknown>);
240
240
  const proofBstr = vdp.get(VDP_CONSISTENCY_PROOF_KEY);
241
241
  if (!(proofBstr instanceof Uint8Array)) return null;
242
- const proof = decodeCbor(proofBstr) as unknown;
242
+ const proof = decodeCborDeterministic(proofBstr);
243
243
  if (!Array.isArray(proof) || proof.length < 2) return null;
244
244
  const treeSize2 = proof[1];
245
245
  if (typeof treeSize2 === "bigint") return treeSize2;
@@ -1,5 +1,5 @@
1
1
  import { sha256 } from "@noble/hashes/sha256";
2
- import { decode as decodeCbor } from "cbor-x";
2
+ import { decodeCborDeterministic } from "@forestrie/encoding";
3
3
  import type { Grant } from "@forestrie/encoding";
4
4
  import {
5
5
  HEADER_FORESTRIE_GRANT_V0,
@@ -42,7 +42,7 @@ export function decodeForestrieGrantCose(bytes: Uint8Array): {
42
42
  grant: Grant;
43
43
  idtimestampBe8: Uint8Array;
44
44
  } {
45
- const raw = decodeCbor(bytes) as unknown;
45
+ const raw = decodeCborDeterministic(bytes);
46
46
  const arr = Array.isArray(raw) ? raw : null;
47
47
  if (!arr || arr.length !== 4) {
48
48
  throw new Error("Forestrie-Grant must be COSE Sign1 (array of 4)");
@@ -1,4 +1,4 @@
1
- import { decode as decodeCbor } from "cbor-x";
1
+ import { decodeCborDeterministic } from "@forestrie/encoding";
2
2
  import {
3
3
  COSE_ALG_ES256,
4
4
  COSE_CRV_P256,
@@ -45,7 +45,7 @@ export async function decodeTrustRootFromGenesis(
45
45
  ): Promise<RootVerifyKey> {
46
46
  let raw: unknown;
47
47
  try {
48
- raw = decodeCbor(genesisCbor);
48
+ raw = decodeCborDeterministic(genesisCbor);
49
49
  } catch {
50
50
  throw new Error("genesis CBOR decode failed");
51
51
  }
@@ -1,4 +1,7 @@
1
- import { decode as decodeCbor, encode as encodeCbor } from "cbor-x";
1
+ import {
2
+ decodeCborDeterministic,
3
+ encodeCborDeterministic,
4
+ } from "@forestrie/encoding";
2
5
  import type { Grant } from "@forestrie/encoding";
3
6
  import { grantDataToBytes } from "@forestrie/encoding";
4
7
  import { fromPaddedWire32, toPaddedWire32 } from "./uuid-bytes.js";
@@ -56,7 +59,7 @@ function mapToGrant(m: Map<number, unknown> | Record<number, unknown>): Grant {
56
59
 
57
60
  export function decodeGrantPayload(bytes: Uint8Array): Grant {
58
61
  if (!bytes?.length) throw new Error("Grant payload is empty");
59
- const raw = decodeCbor(bytes) as unknown;
62
+ const raw = decodeCborDeterministic(bytes);
60
63
  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
61
64
  throw new Error("Grant payload must be a CBOR map");
62
65
  }
@@ -67,7 +70,7 @@ export function decodeGrantResponse(bytes: Uint8Array): {
67
70
  grant: Grant;
68
71
  idtimestamp: Uint8Array;
69
72
  } {
70
- const raw = decodeCbor(bytes) as unknown;
73
+ const raw = decodeCborDeterministic(bytes);
71
74
  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
72
75
  throw new Error("Grant response must be a CBOR map");
73
76
  }
@@ -102,5 +105,5 @@ export function encodeGrantPayload(grant: Grant): Uint8Array {
102
105
  grantDataToBytes(grant.grantData ?? new Uint8Array(0)),
103
106
  ],
104
107
  ]);
105
- return new Uint8Array(encodeCbor(map));
108
+ return encodeCborDeterministic(map);
106
109
  }
@@ -1,4 +1,4 @@
1
- import { decode as decodeCbor } from "cbor-x";
1
+ import { decodeCborDeterministic } from "@forestrie/encoding";
2
2
  import type { Proof } from "@forestrie/merklelog";
3
3
 
4
4
  const VDS_COSE_RECEIPT_PROOFS_TAG = 396;
@@ -62,7 +62,7 @@ export function parseReceipt(receiptBytes: Uint8Array): {
62
62
  receiptCbor: Uint8Array;
63
63
  coseSign1: CoseSign1;
64
64
  } {
65
- const decoded = decodeCbor(receiptBytes) as unknown;
65
+ const decoded = decodeCborDeterministic(receiptBytes);
66
66
  const unwrapped = unwrapCoseSign1Tag(decoded);
67
67
  requireCoseSign1(unwrapped);
68
68