@motebit/crypto 1.2.0 → 1.2.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/dist/index.js +6732 -1075
- package/dist/suite-dispatch.js +3223 -189
- package/package.json +1 -1
- package/dist/artifacts.js +0 -1158
- package/dist/artifacts.js.map +0 -1
- package/dist/credential-anchor.js +0 -200
- package/dist/credential-anchor.js.map +0 -1
- package/dist/credentials.js +0 -212
- package/dist/credentials.js.map +0 -1
- package/dist/deletion-certificate.js +0 -562
- package/dist/deletion-certificate.js.map +0 -1
- package/dist/hardware-attestation.js +0 -400
- package/dist/hardware-attestation.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/merkle.js +0 -84
- package/dist/merkle.js.map +0 -1
- package/dist/signing.js +0 -314
- package/dist/signing.js.map +0 -1
- package/dist/skills.js +0 -228
- package/dist/skills.js.map +0 -1
- package/dist/suite-dispatch.js.map +0 -1
- package/dist/witness-omission-dispute.js +0 -237
- package/dist/witness-omission-dispute.js.map +0 -1
|
@@ -1,237 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"witness-omission-dispute.js","sourceRoot":"","sources":["../src/witness-omission-dispute.ts"],"names":[],"mappings":"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"}
|