@motebit/crypto 1.0.0 → 1.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.
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Witness-omission dispute — sign + verify (retention phase 4b-3).
3
+ *
4
+ * Permissive floor (Apache-2.0). Zero monorepo deps beyond
5
+ * `@motebit/protocol` types. Routes signing through
6
+ * `@motebit/crypto/suite-dispatch`.
7
+ *
8
+ * Path A quorum's soft-accountability layer for `append_only_horizon`
9
+ * certs: a peer who believes `cert.witnessed_by[]` wrongly omits them
10
+ * files this dispute within 24h of `cert.issued_at`. Two evidence
11
+ * shapes:
12
+ *
13
+ * - `inclusion_proof` — disputant proves their peer pubkey is in
14
+ * the cert's `federation_graph_anchor.merkle_root` via a Merkle
15
+ * inclusion proof. The verifier reconstructs against the cert's
16
+ * anchor root.
17
+ *
18
+ * - `alternative_peering` — disputant supplies a signed peering
19
+ * artifact from the cert issuer (today: a federation Heartbeat,
20
+ * `motebit-concat-ed25519-hex-v1`) whose timestamp window covers
21
+ * `cert.horizon_ts ± 5 min` (mirrors heartbeat suspension
22
+ * threshold). The cert's published anchor is claimed incomplete.
23
+ *
24
+ * The verifier returns a per-step result; certificates remain
25
+ * TERMINAL per `retention-policy.md` decision 5 — a sustained dispute
26
+ * is a reputation hit on the issuer, not a cert invalidation.
27
+ */
28
+ import type { DeletionCertificate, WitnessOmissionDispute } from "@motebit/protocol";
29
+ /** Result of verifying a witness-omission dispute. Fail-closed: any failure → `valid: false`. */
30
+ export interface WitnessOmissionDisputeVerifyResult {
31
+ readonly valid: boolean;
32
+ readonly errors: string[];
33
+ /** Per-step breakdown — useful for adjudication audit display. */
34
+ readonly steps: {
35
+ /**
36
+ * Window check (two gates, both must pass):
37
+ * A. `now - cert.issued_at <= WITNESS_OMISSION_DISPUTE_WINDOW_MS`
38
+ * B. `dispute.filed_at ∈ [cert.issued_at, cert.issued_at + WINDOW_MS]`
39
+ */
40
+ readonly window_open: boolean;
41
+ /** Dispute pins the disputed cert (`cert_issuer` + `cert_signature` match). */
42
+ readonly cert_binding_valid: boolean;
43
+ /** Disputant's Ed25519 signature over the dispute body. */
44
+ readonly disputant_signature_valid: boolean;
45
+ /** Evidence-shape verification. `null` when prior checks already failed. */
46
+ readonly evidence_valid: boolean | null;
47
+ };
48
+ }
49
+ /**
50
+ * Resolver context for `verifyWitnessOmissionDispute`. The caller
51
+ * supplies the cert (resolved from its local store via the dispute's
52
+ * `cert_signature` pointer), the issuer's pubkey (for verifying the
53
+ * cert binding and any alternative-peering artifact), the disputant's
54
+ * pubkey, and a `now` clock.
55
+ */
56
+ export interface WitnessOmissionDisputeVerifyContext {
57
+ /** The disputed cert, resolved by the caller from `dispute.cert_signature`. */
58
+ readonly cert: Extract<DeletionCertificate, {
59
+ kind: "append_only_horizon";
60
+ }>;
61
+ /** Cert issuer's Ed25519 public key (32 bytes). */
62
+ readonly issuerPublicKey: Uint8Array;
63
+ /** Disputant peer's Ed25519 public key (32 bytes). `null` → unknown disputant, fail-closed. */
64
+ readonly disputantPublicKey: Uint8Array | null;
65
+ /** Wall-clock at validation time, in unix ms. */
66
+ readonly now: number;
67
+ }
68
+ /**
69
+ * Compute the canonical signing bytes for a `WitnessOmissionDispute`.
70
+ * Strips `signature` so the disputant signs every other field —
71
+ * including `cert_signature`, `cert_issuer`, and the evidence body.
72
+ */
73
+ export declare function canonicalizeWitnessOmissionDispute(dispute: WitnessOmissionDispute): Uint8Array;
74
+ /**
75
+ * Sign a `WitnessOmissionDispute` as the disputant. Caller provides
76
+ * the unsigned body (everything except `suite` and `signature`); this
77
+ * function appends both.
78
+ */
79
+ export declare function signWitnessOmissionDispute(body: Omit<WitnessOmissionDispute, "suite" | "signature">, privateKey: Uint8Array): Promise<WitnessOmissionDispute>;
80
+ /**
81
+ * Verify a `WitnessOmissionDispute` against the disputed cert.
82
+ *
83
+ * Step ladder (fail-closed throughout):
84
+ * 1. Window: `now - cert.issued_at <= WINDOW` AND
85
+ * `filed_at ∈ [cert.issued_at, cert.issued_at + WINDOW]`.
86
+ * 2. Cert binding: `dispute.cert_signature === cert.signature` and
87
+ * `dispute.cert_issuer` matches the cert's subject.
88
+ * 3. Disputant signature over `canonicalJson(dispute minus signature)`.
89
+ * 4. Evidence: dispatched by `evidence.kind` —
90
+ * - `inclusion_proof`: requires cert has a `federation_graph_anchor`;
91
+ * verifies the Merkle proof against `anchor.merkle_root`.
92
+ * - `alternative_peering`: dispatches on `peering_artifact`'s
93
+ * self-described shape (today: federation Heartbeat); verifies
94
+ * the embedded signature against the issuer pubkey and the
95
+ * timestamp window covers `cert.horizon_ts`.
96
+ */
97
+ export declare function verifyWitnessOmissionDispute(dispute: WitnessOmissionDispute, ctx: WitnessOmissionDisputeVerifyContext): Promise<WitnessOmissionDisputeVerifyResult>;
98
+ //# sourceMappingURL=witness-omission-dispute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"witness-omission-dispute.d.ts","sourceRoot":"","sources":["../src/witness-omission-dispute.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,sBAAsB,EAEvB,MAAM,mBAAmB,CAAC;AAuB3B,iGAAiG;AACjG,MAAM,WAAW,kCAAkC;IACjD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAC1B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE;QACd;;;;WAIG;QACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;QAC9B,+EAA+E;QAC/E,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;QACrC,2DAA2D;QAC3D,QAAQ,CAAC,yBAAyB,EAAE,OAAO,CAAC;QAC5C,4EAA4E;QAC5E,QAAQ,CAAC,cAAc,EAAE,OAAO,GAAG,IAAI,CAAC;KACzC,CAAC;CACH;AAID;;;;;;GAMG;AACH,MAAM,WAAW,mCAAmC;IAClD,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,mBAAmB,EAAE;QAAE,IAAI,EAAE,qBAAqB,CAAA;KAAE,CAAC,CAAC;IAC7E,mDAAmD;IACnD,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAC;IACrC,+FAA+F;IAC/F,QAAQ,CAAC,kBAAkB,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/C,iDAAiD;IACjD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAID;;;;GAIG;AACH,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,sBAAsB,GAAG,UAAU,CAI9F;AAID;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,IAAI,CAAC,sBAAsB,EAAE,OAAO,GAAG,WAAW,CAAC,EACzD,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,sBAAsB,CAAC,CASjC;AAID;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,4BAA4B,CAChD,OAAO,EAAE,sBAAsB,EAC/B,GAAG,EAAE,mCAAmC,GACvC,OAAO,CAAC,kCAAkC,CAAC,CA4F7C"}
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Witness-omission dispute — sign + verify (retention phase 4b-3).
3
+ *
4
+ * Permissive floor (Apache-2.0). Zero monorepo deps beyond
5
+ * `@motebit/protocol` types. Routes signing through
6
+ * `@motebit/crypto/suite-dispatch`.
7
+ *
8
+ * Path A quorum's soft-accountability layer for `append_only_horizon`
9
+ * certs: a peer who believes `cert.witnessed_by[]` wrongly omits them
10
+ * files this dispute within 24h of `cert.issued_at`. Two evidence
11
+ * shapes:
12
+ *
13
+ * - `inclusion_proof` — disputant proves their peer pubkey is in
14
+ * the cert's `federation_graph_anchor.merkle_root` via a Merkle
15
+ * inclusion proof. The verifier reconstructs against the cert's
16
+ * anchor root.
17
+ *
18
+ * - `alternative_peering` — disputant supplies a signed peering
19
+ * artifact from the cert issuer (today: a federation Heartbeat,
20
+ * `motebit-concat-ed25519-hex-v1`) whose timestamp window covers
21
+ * `cert.horizon_ts ± 5 min` (mirrors heartbeat suspension
22
+ * threshold). The cert's published anchor is claimed incomplete.
23
+ *
24
+ * The verifier returns a per-step result; certificates remain
25
+ * TERMINAL per `retention-policy.md` decision 5 — a sustained dispute
26
+ * is a reputation hit on the issuer, not a cert invalidation.
27
+ */
28
+ import { canonicalJson, fromBase64Url, hexToBytes, toBase64Url } from "./signing.js";
29
+ import { signBySuite, verifyBySuite } from "./suite-dispatch.js";
30
+ import { verifyMerkleInclusion } from "./merkle.js";
31
+ import { WITNESS_OMISSION_DISPUTE_WINDOW_MS } from "./deletion-certificate.js";
32
+ // ── Constants ────────────────────────────────────────────────────────
33
+ const WITNESS_OMISSION_DISPUTE_SUITE = "motebit-jcs-ed25519-b64-v1";
34
+ const FEDERATION_HEARTBEAT_SUITE = "motebit-concat-ed25519-hex-v1";
35
+ /**
36
+ * Heartbeat-as-peering-evidence freshness window. A heartbeat whose
37
+ * `timestamp` is within ±5 min of `cert.horizon_ts` proves the issuer
38
+ * was alive on that peering relationship at the horizon — mirrors
39
+ * `HEARTBEAT_REMOVE_THRESHOLD = 5` × `heartbeat_interval = 60s` in
40
+ * `services/relay/src/federation.ts`.
41
+ */
42
+ const HEARTBEAT_FRESHNESS_WINDOW_MS = 5 * 60 * 1000;
43
+ // ── Canonicalization ─────────────────────────────────────────────────
44
+ /**
45
+ * Compute the canonical signing bytes for a `WitnessOmissionDispute`.
46
+ * Strips `signature` so the disputant signs every other field —
47
+ * including `cert_signature`, `cert_issuer`, and the evidence body.
48
+ */
49
+ export function canonicalizeWitnessOmissionDispute(dispute) {
50
+ const { signature, ...body } = dispute;
51
+ void signature;
52
+ return new TextEncoder().encode(canonicalJson(body));
53
+ }
54
+ // ── Signing ──────────────────────────────────────────────────────────
55
+ /**
56
+ * Sign a `WitnessOmissionDispute` as the disputant. Caller provides
57
+ * the unsigned body (everything except `suite` and `signature`); this
58
+ * function appends both.
59
+ */
60
+ export async function signWitnessOmissionDispute(body, privateKey) {
61
+ const withSuite = {
62
+ ...body,
63
+ suite: WITNESS_OMISSION_DISPUTE_SUITE,
64
+ signature: "",
65
+ };
66
+ const bytes = canonicalizeWitnessOmissionDispute(withSuite);
67
+ const sig = await signBySuite(WITNESS_OMISSION_DISPUTE_SUITE, bytes, privateKey);
68
+ return { ...withSuite, signature: toBase64Url(sig) };
69
+ }
70
+ // ── Verifier ─────────────────────────────────────────────────────────
71
+ /**
72
+ * Verify a `WitnessOmissionDispute` against the disputed cert.
73
+ *
74
+ * Step ladder (fail-closed throughout):
75
+ * 1. Window: `now - cert.issued_at <= WINDOW` AND
76
+ * `filed_at ∈ [cert.issued_at, cert.issued_at + WINDOW]`.
77
+ * 2. Cert binding: `dispute.cert_signature === cert.signature` and
78
+ * `dispute.cert_issuer` matches the cert's subject.
79
+ * 3. Disputant signature over `canonicalJson(dispute minus signature)`.
80
+ * 4. Evidence: dispatched by `evidence.kind` —
81
+ * - `inclusion_proof`: requires cert has a `federation_graph_anchor`;
82
+ * verifies the Merkle proof against `anchor.merkle_root`.
83
+ * - `alternative_peering`: dispatches on `peering_artifact`'s
84
+ * self-described shape (today: federation Heartbeat); verifies
85
+ * the embedded signature against the issuer pubkey and the
86
+ * timestamp window covers `cert.horizon_ts`.
87
+ */
88
+ export async function verifyWitnessOmissionDispute(dispute, ctx) {
89
+ const errors = [];
90
+ const { cert } = ctx;
91
+ // ── Step 1: window (two gates) ────────────────────────────────────
92
+ const windowEnd = cert.issued_at + WITNESS_OMISSION_DISPUTE_WINDOW_MS;
93
+ const wallClockOpen = ctx.now <= windowEnd;
94
+ const filedAtInRange = dispute.filed_at >= cert.issued_at && dispute.filed_at <= windowEnd;
95
+ const windowOpen = wallClockOpen && filedAtInRange;
96
+ if (!wallClockOpen) {
97
+ errors.push(`dispute window expired: now (${ctx.now}) > cert.issued_at + ${WITNESS_OMISSION_DISPUTE_WINDOW_MS}ms`);
98
+ }
99
+ if (!filedAtInRange) {
100
+ errors.push("dispute.filed_at outside [cert.issued_at, cert.issued_at + WINDOW] — disputant-attested clock cannot widen window");
101
+ }
102
+ // ── Step 2: cert binding ──────────────────────────────────────────
103
+ let certBindingValid = true;
104
+ if (dispute.cert_signature !== cert.signature) {
105
+ errors.push("dispute.cert_signature does not match cert.signature");
106
+ certBindingValid = false;
107
+ }
108
+ const certSubjectId = cert.subject.kind === "motebit"
109
+ ? cert.subject.motebit_id
110
+ : cert.subject.operator_id;
111
+ if (dispute.cert_issuer !== certSubjectId) {
112
+ errors.push(`dispute.cert_issuer (${dispute.cert_issuer}) does not match cert subject (${certSubjectId})`);
113
+ certBindingValid = false;
114
+ }
115
+ // ── Step 3: disputant signature ───────────────────────────────────
116
+ let disputantSignatureValid = false;
117
+ if (ctx.disputantPublicKey === null) {
118
+ errors.push("disputant public key not resolvable");
119
+ }
120
+ else if (dispute.suite !== WITNESS_OMISSION_DISPUTE_SUITE) {
121
+ errors.push(`unexpected suite: ${String(dispute.suite)}`);
122
+ }
123
+ else {
124
+ const bytes = canonicalizeWitnessOmissionDispute(dispute);
125
+ let sigBytes;
126
+ try {
127
+ sigBytes = fromBase64Url(dispute.signature);
128
+ }
129
+ catch {
130
+ sigBytes = new Uint8Array(0);
131
+ }
132
+ if (sigBytes.length === 0) {
133
+ errors.push("dispute.signature decode failed");
134
+ }
135
+ else {
136
+ disputantSignatureValid = await verifyBySuite(dispute.suite, bytes, sigBytes, ctx.disputantPublicKey);
137
+ if (!disputantSignatureValid)
138
+ errors.push("dispute.signature does not verify");
139
+ }
140
+ }
141
+ // Short-circuit evidence verification when prior gates already failed.
142
+ // The dispute is invalid; the evidence-step result is meaningless.
143
+ if (!windowOpen || !certBindingValid || !disputantSignatureValid) {
144
+ return {
145
+ valid: false,
146
+ errors,
147
+ steps: {
148
+ window_open: windowOpen,
149
+ cert_binding_valid: certBindingValid,
150
+ disputant_signature_valid: disputantSignatureValid,
151
+ evidence_valid: null,
152
+ },
153
+ };
154
+ }
155
+ // ── Step 4: evidence dispatch ─────────────────────────────────────
156
+ const evidenceValid = await verifyEvidence(dispute.evidence, cert, ctx, errors);
157
+ return {
158
+ valid: errors.length === 0,
159
+ errors,
160
+ steps: {
161
+ window_open: windowOpen,
162
+ cert_binding_valid: certBindingValid,
163
+ disputant_signature_valid: disputantSignatureValid,
164
+ evidence_valid: evidenceValid,
165
+ },
166
+ };
167
+ }
168
+ async function verifyEvidence(evidence, cert, ctx, errors) {
169
+ if (evidence.kind === "inclusion_proof") {
170
+ const anchor = cert.federation_graph_anchor;
171
+ if (anchor === undefined) {
172
+ errors.push("inclusion_proof evidence requires cert.federation_graph_anchor — none present");
173
+ return false;
174
+ }
175
+ if (anchor.leaf_count === 0) {
176
+ errors.push("inclusion_proof evidence rejected: cert is self-witnessed (anchor.leaf_count=0)");
177
+ return false;
178
+ }
179
+ const ok = await verifyMerkleInclusion(evidence.leaf_hash, evidence.proof.leaf_index, evidence.proof.siblings, evidence.proof.layer_sizes, anchor.merkle_root);
180
+ if (!ok)
181
+ errors.push("inclusion proof does not reconstruct to anchor.merkle_root");
182
+ return ok;
183
+ }
184
+ // alternative_peering — closed union; TS narrows after the if-branch.
185
+ return verifyAlternativePeeringArtifact(evidence.peering_artifact, cert, ctx, errors);
186
+ }
187
+ /**
188
+ * Verify a peering artifact embedded in `alternative_peering` evidence.
189
+ * Today: federation Heartbeat is the canonical shape — the only
190
+ * recurring signed peering attestation in `relay-federation-v1`.
191
+ *
192
+ * Heartbeat signing payload (FEDERATION_SUITE = motebit-concat-ed25519-hex-v1):
193
+ * `${relay_id}|${timestamp}|${suite}` — UTF-8 concatenation, hex sig.
194
+ *
195
+ * The verifier dispatches on the artifact's self-described shape:
196
+ * presence of `relay_id` (string) + `timestamp` (number) + `signature`
197
+ * (hex string) identifies the heartbeat shape. Future: PeeringConfirm
198
+ * or other peering attestations land as additive dispatch arms.
199
+ */
200
+ async function verifyAlternativePeeringArtifact(artifact, cert, ctx, errors) {
201
+ const relayId = artifact["relay_id"];
202
+ const timestamp = artifact["timestamp"];
203
+ const signatureHex = artifact["signature"];
204
+ if (typeof relayId !== "string" ||
205
+ typeof timestamp !== "number" ||
206
+ typeof signatureHex !== "string") {
207
+ errors.push("alternative_peering artifact unrecognized — expected federation Heartbeat shape (relay_id, timestamp, signature)");
208
+ return false;
209
+ }
210
+ const certSubjectId = cert.subject.kind === "motebit"
211
+ ? cert.subject.motebit_id
212
+ : cert.subject.operator_id;
213
+ if (relayId !== certSubjectId) {
214
+ errors.push(`peering artifact relay_id (${relayId}) does not match cert issuer (${certSubjectId})`);
215
+ return false;
216
+ }
217
+ if (Math.abs(timestamp - cert.horizon_ts) > HEARTBEAT_FRESHNESS_WINDOW_MS) {
218
+ errors.push(`peering artifact timestamp (${timestamp}) outside ±${HEARTBEAT_FRESHNESS_WINDOW_MS}ms of cert.horizon_ts (${cert.horizon_ts})`);
219
+ return false;
220
+ }
221
+ let sigBytes;
222
+ /* c8 ignore start -- defensive catch; `hexToBytes` (signing.ts) uses parseInt which silently returns NaN for non-hex chars rather than throwing, so this catch is unreachable today. Keep for forward-compat: a future hex-decode primitive that throws (e.g. native Uint8Array.fromHex) would route through this branch and fail closed rather than passing garbage bytes through to verifyBySuite. */
223
+ try {
224
+ sigBytes = hexToBytes(signatureHex);
225
+ }
226
+ catch {
227
+ errors.push("peering artifact signature is not valid hex");
228
+ return false;
229
+ }
230
+ /* c8 ignore stop */
231
+ const payload = new TextEncoder().encode(`${relayId}|${timestamp}|${FEDERATION_HEARTBEAT_SUITE}`);
232
+ const ok = await verifyBySuite(FEDERATION_HEARTBEAT_SUITE, payload, sigBytes, ctx.issuerPublicKey);
233
+ if (!ok)
234
+ errors.push("peering artifact signature does not verify against cert issuer pubkey");
235
+ return ok;
236
+ }
237
+ //# sourceMappingURL=witness-omission-dispute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"witness-omission-dispute.js","sourceRoot":"","sources":["../src/witness-omission-dispute.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@motebit/crypto",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Sign and verify every Motebit artifact — identity files, execution receipts, credentials, delegations, succession records, credential anchors. Ed25519 today, cryptosuite-agile for post-quantum tomorrow. Apache-2.0, zero monorepo dependencies.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -64,7 +64,7 @@
64
64
  "tsup": "^8.0.0",
65
65
  "typescript": "^5.6.0",
66
66
  "vitest": "^2.1.0",
67
- "@motebit/protocol": "1.0.0"
67
+ "@motebit/protocol": "1.2.0"
68
68
  },
69
69
  "engines": {
70
70
  "node": ">=20"