@ziffer-io/verify 0.1.0 → 0.2.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.
package/README.md CHANGED
@@ -1,121 +1,71 @@
1
1
  # @ziffer-io/verify
2
2
 
3
- The **third implementation** of ACP receipt verification. The first two live in the
4
- engine repository at the pin this workspace's `Cargo.toml` names: the Python reference
5
- (`reference/src/acp_executor.py`, the readable §9.3 checklist) and Rust
6
- (`crates/acp-decision`, the production decision path). This package lives in ziffer
7
- **only because the engine repository is publicly frozen and ziffer CI cannot reach new
8
- engine commits**; the mirrored corpus in `fixtures/` plus `tools/check-verify-mirror.py`
9
- is what keeps three copies of one rule honest. Engine-home for this package is revisited
10
- if the freeze lifts.
3
+ Verify a ZIFFER decision receipt in your own process, against a key you configured yourself.
4
+
5
+ ## Install
11
6
 
12
7
  ```bash
13
8
  npm install @ziffer-io/verify
14
9
  ```
15
10
 
16
- Most integrations do not install this directly. `@ziffer-io/client` depends on it and re-exports
17
- `verifyReceipt`, so there is one verifier in your dependency tree rather than two that can
18
- disagree. Install it on its own when you verify receipts and never call the API.
11
+ Node 22 or later. If you also call the ZIFFER API, install `@ziffer-io/client` instead. It
12
+ depends on this package and re-exports `verifyReceipt`, so one verifier is in your tree.
19
13
 
20
- ## What it does
14
+ ## Quickstart
21
15
 
22
16
  ```ts
23
- import { verifyReceipt, Refusal } from '@ziffer-io/verify';
24
-
25
- const verified = verifyReceipt(receiptJson, proposalBytes, {
26
- classical, // Ed25519 verification key, 32 bytes, from the signed bundle (PB-12)
27
- pq, // ML-DSA-65 verification key, 1,952 bytes, same home
28
- minSuite: 'hybrid-ed25519-mldsa65', // CR-4 floor, from the signed manifest
29
- });
30
- // throws Refusal on any defect; verified.proposalHash is the verifier's OWN hash
17
+ import { readFileSync } from 'node:fs';
18
+ import { verifyReceipt, type TrustAnchor } from '@ziffer-io/verify';
19
+
20
+ const keys = JSON.parse(readFileSync(process.env.ZIFFER_TRUST_ANCHOR, 'utf8'));
21
+ const anchor: TrustAnchor = {
22
+ classical: Buffer.from(keys.ed25519_pk_hex, 'hex'),
23
+ pq: Buffer.from(keys.mldsa65_pk_hex, 'hex'),
24
+ minSuite: process.env.ZIFFER_SUITE_FLOOR,
25
+ };
26
+
27
+ const proposalBytes = new TextEncoder().encode(JSON.stringify(proposal));
28
+ const verified = verifyReceipt(receipt, proposalBytes, anchor);
29
+ // It returned, so the receipt holds. verified.proposalHash is this verifier's own hash.
30
+ await bank.transfer(amount, toAccount); // your line, unchanged
31
31
  ```
32
32
 
33
- `verifyReceipt` runs exactly the **stateless** portion of the §9.3 checklist — the part
34
- answerable with only receipt + proposal + identity: AB-0 (receipt version 3 only),
35
- AB-5/AB-6 (signed-body exclusion and byte cap), CR-1/CR-4/CR-3 (suite known, floor by
36
- containment, hybrid **conjunctive** — every primitive must verify), 9.3-2 (decision
37
- domain), 9.3-3 (proposal hash **recomputed** from the caller's own bytes, never read
38
- from the message — RES-8), 9.3-5/L-14 (temporal position and window ceiling, over
39
- strictly parsed RFC 3339 UTC instants), WE-4/L-17 (nonce type and size).
40
-
41
- A pass means "the stateless set found nothing", never "the receipt may be consumed":
42
- steps 4 (policy basis), 6's CL-2 claim, 7 (grading recomputation), 7b (the quorum),
43
- 8 (tenant scoping) and 9–10 need the signed bundle, the attester registry, a ledger and
44
- a context store, and are deliberately absent rather than approximated. The module doc in
45
- `src/verify.ts` carries the full table and the R/B/T classification.
46
-
47
- Every refusal is a thrown `Refusal` whose `clause` is spelled **exactly as the engine's
48
- Rust clause constants** spell it (`AB-0`, `AB-6`, `CR-1`, `CR-4`, `AT-8a`, `9.3-1`,
49
- `9.3-2`, `9.3-3`, `9.3-5`, `L-14`, `WE-4`, `L-17`) — the clause is what the three
50
- implementations are compared on.
51
-
52
- ## What it does not do
53
-
54
- - **It is not a receipt gate.** A pass is "the stateless set found nothing", not "this receipt may
55
- be consumed" — the paragraph above lists the six §9.3 steps that need a signed bundle, an
56
- attester registry, a ledger and a context store, and are absent rather than approximated.
57
- - **It fetches nothing and trusts nothing you did not hand it.** The identity keys and the CR-4
58
- suite floor are arguments. It will not read them from the receipt, because a verifier that takes
59
- a derived security value from the party it is verifying is the defect class this specification
60
- has published five corrections for (RES-8).
61
- - **It does not hash your proposal for you.** You pass the bytes your own code passes to the API,
62
- and the verifier recomputes the hash from them. Handing it the hash would verify nothing.
63
- - **It has no `approve`, and no test mode that mints a receipt.** Signing lives behind keys this
64
- package never holds.
65
-
66
- ## Strict Ed25519, written out
67
-
68
- `@noble/curves`' `verify` with `{ zip215: false }` enforces canonical encodings but —
69
- like OpenSSL — does **not** refuse small-order points. The ACP-106 rule (a small-order
70
- public key or a small-order `R` makes the verification equation stop mentioning the
71
- message) is therefore written out in `src/ed25519.ts`, exactly as the Python reference
72
- writes it in `verify_prim` and Rust gets from `verify_strict`. The mirrored
73
- `fixtures/refused_ed25519.json` is the executable statement: every vector is accepted by
74
- RFC 8032 as OpenSSL implements it and refused by all three implementations. Deleting the
75
- guard here was observed to accept the corpus's `r_is_the_identity_point` vector.
76
-
77
- ## Canonicalization, proven not transcribed
78
-
79
- `src/canon.ts` reproduces the engine canon (sorted keys at every depth by **code
80
- point** — not JS's UTF-16 unit order — no whitespace, raw UTF-8). The proof is a
81
- triangle: `fixtures/canon_vectors.json` was generated by importing and executing the
82
- engine's own `acp_executor.canon` (`fixtures/gen_canon_vectors.py`), the TS tests assert
83
- byte-identity with the fixture on every case, and `tools/check-verify-mirror.py`
84
- re-derives every case against the engine at the pin.
85
-
86
- **Disclosed divergence (fail-closed):** the engine accepts a float *nested* in a signed
87
- structure (the ACP-75 bug-for-bug agreement between Python and Rust). This
88
- implementation refuses any non-integer number at any depth under `AT-8a`, because
89
- `JSON.parse` collapses `1000.0` and `1000` into one value and reproducing the engine's
90
- bytes would be a guess about bytes it never saw. Integers beyond `2^53−1` are refused
91
- for the same reason (the ACP-54 integer-domain family reached from the JS side). No
92
- conforming wire receipt carries either — every temporal field is an RFC 3339 string
93
- since v1.3.28 (ACP-167). Both refusals are pinned by tests so the divergence cannot
94
- vanish silently.
95
-
96
- ## Fixtures
97
-
98
- Byte-identical mirrors of engine files, each with a `.provenance.json` sidecar (source
99
- path, rev, sha256 — a header *inside* the JSON would change the bytes the identity claim
100
- is about): `refused_ed25519.json`, `python_signatures.json` (the reference's signatures,
101
- which this side must accept — the TS leg of `tests/python_interop.rs`' claim; its seeds
102
- also pin the test-key derivation mirror in `src/testkeys.ts`), and
103
- `instant-type-vectors.json` (this package is the shared instant corpus's fourth
104
- consumer). Plus the derived `canon_vectors.json` above. Re-mirror at a pin bump;
105
- `tools/check-verify-mirror.py` refuses a mirror whose provenance rev is not the
106
- workspace pin.
107
-
108
- ## Running
109
-
110
- ```sh
111
- pnpm --filter @ziffer-io/verify test # tsc -b && node --test (27 tests)
112
- python3 tools/check-verify-mirror.py # from the repo root; needs ACP_REPO_PATH at the pin
113
- ```
33
+ It reaches no network and trusts nothing it was not handed. The keys and the suite floor are
34
+ arguments you pass in. The proposal hash is recomputed from your bytes, never read from the
35
+ receipt.
36
+ Key order and spacing do not matter, because the verifier canonicalises your bytes itself.
37
+
38
+ `verifyReceipt` checks the answer. Your own `if` is what stops the action.
39
+
40
+ ## Configuration
41
+
42
+ | Variable | What it is | Where the value comes from |
43
+ | --- | --- | --- |
44
+ | `ZIFFER_TRUST_ANCHOR` | Path to the public key file your receipts are signed under. | We give you the file. Take it from us, never from the API you are checking. |
45
+ | `ZIFFER_SUITE_FLOOR` | The weakest signature suite you will accept. | You choose it. There is no default. |
46
+
47
+ ## When a request is refused
48
+
49
+ Every refusal is a thrown `Refusal` whose `clause` names the rule that fired; the table of every
50
+ clause, what it means and what to do is at https://ziffer.io/docs/refusals. Narrow with
51
+ `instanceof Refusal`, record the clause, and do not retry it.
52
+
53
+ ## Documentation
54
+
55
+ - Quickstart: https://ziffer.io/docs/quickstart
56
+ - Integrating the SDK: https://ziffer.io/docs/developers/sdk
57
+ - Every refusal: https://ziffer.io/docs/refusals
58
+ - The specification: https://ziffer.io/docs/specification
59
+ - Glossary: https://ziffer.io/docs/glossary
60
+
61
+ ## Support
62
+
63
+ Write to hello@ziffer.io. Your trust anchor file and your suite floor come from us. So does an
64
+ answer about a refusal you cannot explain.
114
65
 
115
- ## Licence
66
+ ## License
116
67
 
117
- Proprietary. Copyright (c) 2026 code75 SASU, Paris, France. ZIFFER is a registered trademark of code75
118
- SASU. This package is **not open source**: it is licensed for use with the ZIFFER service under
119
- your agreement with code75, on the terms in `LICENSE` beside this file. The third-party
120
- open-source components it redistributes are listed in `THIRD-PARTY-NOTICES` and are governed by
121
- their own licences.
68
+ Proprietary. Copyright (c) 2026 code75 SASU, Paris, France. ZIFFER is a registered trademark of
69
+ code75 SASU. This package is not open source. Its use is governed by your agreement with code75
70
+ and by `LICENSE` beside this file. The open-source components it redistributes are listed in
71
+ `THIRD-PARTY-NOTICES`, under their own licences.
package/dist/cbor.d.ts ADDED
@@ -0,0 +1,87 @@
1
+ /**
2
+ * AT-8a canonical CBOR (RFC 8949 §4.2) -- the ONE primitive this package did
3
+ * not already have, added for §8.6c and for nothing else.
4
+ *
5
+ * # Why a new module rather than a reused one
6
+ *
7
+ * `canon.ts` is the canonical JSON encoding, and it is the right preimage for
8
+ * every hash this verifier takes: the engine's `attestation_id` and AB-1 entry
9
+ * digest are `sha256:` over `acp_executor.canon` / `receipt.rs::canon`, both
10
+ * JSON, and this package reproduces those bytes. What CBOR is needed for is
11
+ * narrower and unavoidable: HM-3 says a human attester's assertion is canonical
12
+ * CBOR of `{authenticator_data, client_data_json, signature}`, and HM-1 says the
13
+ * credential's `public_key` is a COSE_Key, which is CBOR by RFC 9052. Those two
14
+ * byte strings arrive from the wire and must be DECODED; no JSON encoder can
15
+ * read them. So this is a decoder for two fixed shapes, not a general codec.
16
+ *
17
+ * The engine's twins are `crates/acp-crypto/src/cbor.rs` and
18
+ * `reference/src/acp_crypto.py`'s `_enc` / `_dec` / `decode_canonical`, and the
19
+ * rule this file takes from them verbatim is the last one:
20
+ *
21
+ * # Canonicity is proved by RE-ENCODING, not by a list of sub-rules
22
+ *
23
+ * {@link decodeCanonical} parses, re-encodes what it parsed, and refuses the
24
+ * input unless the two byte strings are identical. That single comparison
25
+ * carries every §4.2 requirement at once -- shortest-form arguments, definite
26
+ * lengths, map keys sorted by their ENCODED bytes, no duplicate keys -- and it
27
+ * cannot drift from the encoder the way a hand-written checklist of those rules
28
+ * can. The decoder still refuses the coarse violations itself (indefinite
29
+ * lengths, non-shortest arguments, reserved additional information) because a
30
+ * decoder that accepted them would have to invent a canonical form to compare
31
+ * against, and inventing one is normalising.
32
+ *
33
+ * Refused, never normalised (AT-8a): the AB-1 entry digest is taken over the
34
+ * bytes that arrived, so a second encoding of one assertion is a second digest
35
+ * for one human decision, and accepting both would put two receipt identities
36
+ * behind one approval -- the Z4 encoding split, reached through the assertion.
37
+ *
38
+ * # Floats and tags are absent on purpose
39
+ *
40
+ * Neither is encodable, so neither is decodable: a float has several
41
+ * representations of one value and no deterministic ordering story (WE-1), and
42
+ * a tag is a type this verifier has no shape for. They refuse as
43
+ * {@link CborError} rather than being skipped, because a decoder that silently
44
+ * ignores what it does not understand is a parser an attacker can steer.
45
+ */
46
+ /** The input is not canonical CBOR, or is not CBOR at all. */
47
+ export declare class CborError extends Error {
48
+ constructor(message: string);
49
+ }
50
+ /**
51
+ * What this decoder can produce. Deliberately NOT a general CBOR value type:
52
+ * a map key is an integer (COSE labels, RFC 9052 §7) or text (HM-3's three
53
+ * fields), and nothing here needs more.
54
+ */
55
+ export type Cbor = boolean | null | bigint | Uint8Array | string | Cbor[] | CborMap;
56
+ /**
57
+ * A CBOR map, kept as ordered entries rather than a JS object.
58
+ *
59
+ * An object would key everything by string and collapse the integer label `1`
60
+ * and the text key `"1"` into one entry -- two distinct CBOR values, and in
61
+ * COSE_Key the integer form is the only legal one. The order is the order the
62
+ * bytes carried, which the re-encode check has already proved canonical.
63
+ */
64
+ export interface CborMap {
65
+ readonly entries: readonly (readonly [Cbor, Cbor])[];
66
+ }
67
+ /** Whether a decoded value is a map -- the narrowing the callers need. */
68
+ export declare function cborIsMap(v: Cbor): v is CborMap;
69
+ /** A map's keys, in the (canonical) order the bytes carried. */
70
+ export declare function cborKeys(m: CborMap): Cbor[];
71
+ /** The value at an integer label, or undefined. COSE_Key's accessor. */
72
+ export declare function cborGetInt(m: CborMap, label: bigint): Cbor | undefined;
73
+ /** The value at a text key, or undefined. The assertion map's accessor. */
74
+ export declare function cborGetText(m: CborMap, key: string): Cbor | undefined;
75
+ /** A decoded value as bytes, or null if it is not a byte string. */
76
+ export declare function cborAsBytes(v: Cbor | undefined): Uint8Array | null;
77
+ /** The canonical CBOR bytes of a value. Used by {@link decodeCanonical}'s proof. */
78
+ export declare function cborEncode(value: Cbor): Uint8Array;
79
+ /**
80
+ * AT-8a: parse AND prove canonicity. Any input that is not byte-identical to
81
+ * the canonical encoding of what it decodes to is REFUSED, never normalised.
82
+ *
83
+ * The engine's `decode_canonical` in one sentence, and the same sentence is the
84
+ * whole specification of this function.
85
+ */
86
+ export declare function decodeCanonical(buf: Uint8Array): Cbor;
87
+ //# sourceMappingURL=cbor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cbor.d.ts","sourceRoot":"","sources":["../src/cbor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,8DAA8D;AAC9D,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAED;;;;GAIG;AACH,MAAM,MAAM,IAAI,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;AAEpF;;;;;;;GAOG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;CACtD;AAMD,0EAA0E;AAC1E,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,IAAI,OAAO,CAE/C;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,EAAE,CAE3C;AAED,wEAAwE;AACxE,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAGtE;AAED,2EAA2E;AAC3E,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAGrE;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,UAAU,GAAG,IAAI,CAElE;AAsHD,oFAAoF;AACpF,wBAAgB,UAAU,CAAC,KAAK,EAAE,IAAI,GAAG,UAAU,CAIlD;AA0FD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAQrD"}
package/dist/cbor.js ADDED
@@ -0,0 +1,326 @@
1
+ /**
2
+ * AT-8a canonical CBOR (RFC 8949 §4.2) -- the ONE primitive this package did
3
+ * not already have, added for §8.6c and for nothing else.
4
+ *
5
+ * # Why a new module rather than a reused one
6
+ *
7
+ * `canon.ts` is the canonical JSON encoding, and it is the right preimage for
8
+ * every hash this verifier takes: the engine's `attestation_id` and AB-1 entry
9
+ * digest are `sha256:` over `acp_executor.canon` / `receipt.rs::canon`, both
10
+ * JSON, and this package reproduces those bytes. What CBOR is needed for is
11
+ * narrower and unavoidable: HM-3 says a human attester's assertion is canonical
12
+ * CBOR of `{authenticator_data, client_data_json, signature}`, and HM-1 says the
13
+ * credential's `public_key` is a COSE_Key, which is CBOR by RFC 9052. Those two
14
+ * byte strings arrive from the wire and must be DECODED; no JSON encoder can
15
+ * read them. So this is a decoder for two fixed shapes, not a general codec.
16
+ *
17
+ * The engine's twins are `crates/acp-crypto/src/cbor.rs` and
18
+ * `reference/src/acp_crypto.py`'s `_enc` / `_dec` / `decode_canonical`, and the
19
+ * rule this file takes from them verbatim is the last one:
20
+ *
21
+ * # Canonicity is proved by RE-ENCODING, not by a list of sub-rules
22
+ *
23
+ * {@link decodeCanonical} parses, re-encodes what it parsed, and refuses the
24
+ * input unless the two byte strings are identical. That single comparison
25
+ * carries every §4.2 requirement at once -- shortest-form arguments, definite
26
+ * lengths, map keys sorted by their ENCODED bytes, no duplicate keys -- and it
27
+ * cannot drift from the encoder the way a hand-written checklist of those rules
28
+ * can. The decoder still refuses the coarse violations itself (indefinite
29
+ * lengths, non-shortest arguments, reserved additional information) because a
30
+ * decoder that accepted them would have to invent a canonical form to compare
31
+ * against, and inventing one is normalising.
32
+ *
33
+ * Refused, never normalised (AT-8a): the AB-1 entry digest is taken over the
34
+ * bytes that arrived, so a second encoding of one assertion is a second digest
35
+ * for one human decision, and accepting both would put two receipt identities
36
+ * behind one approval -- the Z4 encoding split, reached through the assertion.
37
+ *
38
+ * # Floats and tags are absent on purpose
39
+ *
40
+ * Neither is encodable, so neither is decodable: a float has several
41
+ * representations of one value and no deterministic ordering story (WE-1), and
42
+ * a tag is a type this verifier has no shape for. They refuse as
43
+ * {@link CborError} rather than being skipped, because a decoder that silently
44
+ * ignores what it does not understand is a parser an attacker can steer.
45
+ */
46
+ /** The input is not canonical CBOR, or is not CBOR at all. */
47
+ export class CborError extends Error {
48
+ constructor(message) {
49
+ super(message);
50
+ this.name = 'CborError';
51
+ }
52
+ }
53
+ function isCborMap(v) {
54
+ return typeof v === 'object' && v !== null && !Array.isArray(v) && !(v instanceof Uint8Array);
55
+ }
56
+ /** Whether a decoded value is a map -- the narrowing the callers need. */
57
+ export function cborIsMap(v) {
58
+ return isCborMap(v);
59
+ }
60
+ /** A map's keys, in the (canonical) order the bytes carried. */
61
+ export function cborKeys(m) {
62
+ return m.entries.map(([k]) => k);
63
+ }
64
+ /** The value at an integer label, or undefined. COSE_Key's accessor. */
65
+ export function cborGetInt(m, label) {
66
+ for (const [k, v] of m.entries)
67
+ if (typeof k === 'bigint' && k === label)
68
+ return v;
69
+ return undefined;
70
+ }
71
+ /** The value at a text key, or undefined. The assertion map's accessor. */
72
+ export function cborGetText(m, key) {
73
+ for (const [k, v] of m.entries)
74
+ if (typeof k === 'string' && k === key)
75
+ return v;
76
+ return undefined;
77
+ }
78
+ /** A decoded value as bytes, or null if it is not a byte string. */
79
+ export function cborAsBytes(v) {
80
+ return v instanceof Uint8Array ? v : null;
81
+ }
82
+ const MAJOR_UINT = 0;
83
+ const MAJOR_NINT = 1;
84
+ const MAJOR_BYTES = 2;
85
+ const MAJOR_TEXT = 3;
86
+ const MAJOR_ARRAY = 4;
87
+ const MAJOR_MAP = 5;
88
+ const MAJOR_SIMPLE = 7;
89
+ /**
90
+ * RFC 8949 §4.2.1: the argument MUST use the shortest form that holds it.
91
+ *
92
+ * `bigint` throughout rather than `number`, because a CBOR argument is a full
93
+ * 64-bit unsigned integer and `number` loses digits past 2^53-1 -- the same
94
+ * defect `canon.ts` refuses on the JSON side, and here it would mean re-encoding
95
+ * a length to different bytes than arrived and calling the input non-canonical
96
+ * for the decoder's own reason.
97
+ */
98
+ function encodeHead(major, value, out) {
99
+ const head = major << 5;
100
+ if (value < 24n) {
101
+ out.push(head | Number(value));
102
+ return;
103
+ }
104
+ let width;
105
+ if (value < 0x100n) {
106
+ out.push(head | 24);
107
+ width = 1;
108
+ }
109
+ else if (value < 0x10000n) {
110
+ out.push(head | 25);
111
+ width = 2;
112
+ }
113
+ else if (value < 0x100000000n) {
114
+ out.push(head | 26);
115
+ width = 4;
116
+ }
117
+ else if (value < 0x10000000000000000n) {
118
+ out.push(head | 27);
119
+ width = 8;
120
+ }
121
+ else {
122
+ throw new CborError('integer exceeds the 64-bit CBOR argument');
123
+ }
124
+ for (let i = width - 1; i >= 0; i -= 1) {
125
+ out.push(Number((value >> BigInt(i * 8)) & 0xffn));
126
+ }
127
+ }
128
+ function encodeInto(value, out) {
129
+ if (value === true) {
130
+ out.push(0xf5);
131
+ return;
132
+ }
133
+ if (value === false) {
134
+ out.push(0xf4);
135
+ return;
136
+ }
137
+ if (value === null) {
138
+ out.push(0xf6);
139
+ return;
140
+ }
141
+ if (typeof value === 'bigint') {
142
+ if (value >= 0n)
143
+ encodeHead(MAJOR_UINT, value, out);
144
+ else
145
+ encodeHead(MAJOR_NINT, -value - 1n, out);
146
+ return;
147
+ }
148
+ if (value instanceof Uint8Array) {
149
+ encodeHead(MAJOR_BYTES, BigInt(value.length), out);
150
+ for (const b of value)
151
+ out.push(b);
152
+ return;
153
+ }
154
+ if (typeof value === 'string') {
155
+ const bytes = new TextEncoder().encode(value);
156
+ encodeHead(MAJOR_TEXT, BigInt(bytes.length), out);
157
+ for (const b of bytes)
158
+ out.push(b);
159
+ return;
160
+ }
161
+ if (Array.isArray(value)) {
162
+ encodeHead(MAJOR_ARRAY, BigInt(value.length), out);
163
+ for (const item of value)
164
+ encodeInto(item, out);
165
+ return;
166
+ }
167
+ if (isCborMap(value)) {
168
+ // §4.2.1: keys sorted by their ENCODED bytes, bytewise lexicographic.
169
+ // Sorting by the decoded value would put the integer label -2 and the text
170
+ // key "x" in an order that depends on the comparison chosen rather than on
171
+ // the bytes, and the encoded order is the one the rule names.
172
+ const keyed = value.entries.map(([k, v]) => {
173
+ const kb = [];
174
+ encodeInto(k, kb);
175
+ return { kb, v };
176
+ });
177
+ keyed.sort((a, b) => compareBytes(a.kb, b.kb));
178
+ for (let i = 1; i < keyed.length; i += 1) {
179
+ const prev = keyed[i - 1];
180
+ const cur = keyed[i];
181
+ if (prev === undefined || cur === undefined)
182
+ continue; // unreachable; index in range
183
+ if (compareBytes(prev.kb, cur.kb) === 0)
184
+ throw new CborError('duplicate map key');
185
+ }
186
+ encodeHead(MAJOR_MAP, BigInt(keyed.length), out);
187
+ for (const { kb, v } of keyed) {
188
+ for (const b of kb)
189
+ out.push(b);
190
+ encodeInto(v, out);
191
+ }
192
+ return;
193
+ }
194
+ throw new CborError('value is not canonically encodable');
195
+ }
196
+ function compareBytes(a, b) {
197
+ const n = Math.min(a.length, b.length);
198
+ for (let i = 0; i < n; i += 1) {
199
+ const x = a[i];
200
+ const y = b[i];
201
+ if (x === undefined || y === undefined)
202
+ continue; // unreachable; index in range
203
+ if (x !== y)
204
+ return x - y;
205
+ }
206
+ return a.length - b.length;
207
+ }
208
+ /** The canonical CBOR bytes of a value. Used by {@link decodeCanonical}'s proof. */
209
+ export function cborEncode(value) {
210
+ const out = [];
211
+ encodeInto(value, out);
212
+ return Uint8Array.from(out);
213
+ }
214
+ function decodeAt(buf, start) {
215
+ if (start >= buf.length)
216
+ throw new CborError('truncated');
217
+ const ib = buf[start];
218
+ if (ib === undefined)
219
+ throw new CborError('truncated'); // unreachable; bound checked
220
+ const major = ib >> 5;
221
+ const ai = ib & 0x1f;
222
+ let i = start + 1;
223
+ let value;
224
+ if (ai < 24) {
225
+ value = BigInt(ai);
226
+ }
227
+ else if (ai <= 27) {
228
+ const width = 1 << (ai - 24);
229
+ if (i + width > buf.length)
230
+ throw new CborError('truncated argument');
231
+ value = 0n;
232
+ for (let k = 0; k < width; k += 1) {
233
+ const b = buf[i + k];
234
+ if (b === undefined)
235
+ throw new CborError('truncated argument'); // unreachable
236
+ value = (value << 8n) | BigInt(b);
237
+ }
238
+ i += width;
239
+ // Shortest form (§4.2.1). Refused here as well as by the re-encode proof,
240
+ // because the value that re-encodes shorter would otherwise be decoded
241
+ // first and any shape check above would run on attacker-chosen bytes.
242
+ const floor = ai === 24 ? 24n : 1n << BigInt((width / 2) * 8);
243
+ if (value < floor)
244
+ throw new CborError('non-shortest argument');
245
+ }
246
+ else if (ai === 31) {
247
+ throw new CborError('indefinite length forbidden in canonical CBOR');
248
+ }
249
+ else {
250
+ throw new CborError(`reserved additional information ${ai}`);
251
+ }
252
+ switch (major) {
253
+ case MAJOR_UINT:
254
+ return { value, next: i };
255
+ case MAJOR_NINT:
256
+ return { value: -value - 1n, next: i };
257
+ case MAJOR_BYTES:
258
+ case MAJOR_TEXT: {
259
+ const len = Number(value);
260
+ if (!Number.isSafeInteger(len) || i + len > buf.length) {
261
+ throw new CborError('truncated string');
262
+ }
263
+ const slice = buf.subarray(i, i + len);
264
+ if (major === MAJOR_BYTES)
265
+ return { value: Uint8Array.from(slice), next: i + len };
266
+ // fatal: true -- invalid UTF-8 is a refusal, not a run of U+FFFD. A
267
+ // replacement character would make two distinct byte strings decode to
268
+ // one text value, which the re-encode proof would then report as
269
+ // non-canonical for the wrong reason.
270
+ return { value: new TextDecoder('utf-8', { fatal: true }).decode(slice), next: i + len };
271
+ }
272
+ case MAJOR_ARRAY: {
273
+ const n = Number(value);
274
+ if (!Number.isSafeInteger(n) || n > buf.length - i)
275
+ throw new CborError('truncated array');
276
+ const items = [];
277
+ for (let k = 0; k < n; k += 1) {
278
+ const d = decodeAt(buf, i);
279
+ items.push(d.value);
280
+ i = d.next;
281
+ }
282
+ return { value: items, next: i };
283
+ }
284
+ case MAJOR_MAP: {
285
+ const n = Number(value);
286
+ if (!Number.isSafeInteger(n) || n > buf.length - i)
287
+ throw new CborError('truncated map');
288
+ const entries = [];
289
+ for (let k = 0; k < n; k += 1) {
290
+ const key = decodeAt(buf, i);
291
+ const val = decodeAt(buf, key.next);
292
+ entries.push([key.value, val.value]);
293
+ i = val.next;
294
+ }
295
+ return { value: { entries }, next: i };
296
+ }
297
+ case MAJOR_SIMPLE:
298
+ if (value === 20n)
299
+ return { value: false, next: i };
300
+ if (value === 21n)
301
+ return { value: true, next: i };
302
+ if (value === 22n)
303
+ return { value: null, next: i };
304
+ throw new CborError('float or unsupported simple value');
305
+ default:
306
+ throw new CborError(`unsupported major type ${major}`);
307
+ }
308
+ }
309
+ /**
310
+ * AT-8a: parse AND prove canonicity. Any input that is not byte-identical to
311
+ * the canonical encoding of what it decodes to is REFUSED, never normalised.
312
+ *
313
+ * The engine's `decode_canonical` in one sentence, and the same sentence is the
314
+ * whole specification of this function.
315
+ */
316
+ export function decodeCanonical(buf) {
317
+ const { value, next } = decodeAt(buf, 0);
318
+ if (next !== buf.length)
319
+ throw new CborError('trailing bytes');
320
+ const re = cborEncode(value);
321
+ if (re.length !== buf.length || !re.every((b, i) => b === buf[i])) {
322
+ throw new CborError('input is not the canonical encoding of its value');
323
+ }
324
+ return value;
325
+ }
326
+ //# sourceMappingURL=cbor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cbor.js","sourceRoot":"","sources":["../src/cbor.ts"],"names":[],"mappings":"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"}