@atlasauth/pca-mpc 0.3.0 → 0.4.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.
Files changed (85) hide show
  1. package/README.md +81 -3
  2. package/dist/beaver.js +4 -0
  3. package/dist/beaver.js.map +1 -1
  4. package/dist/compose.d.ts +9 -2
  5. package/dist/compose.js +24 -1
  6. package/dist/compose.js.map +1 -1
  7. package/dist/ec.d.ts +6 -3
  8. package/dist/ec.js +27 -9
  9. package/dist/ec.js.map +1 -1
  10. package/dist/enc.d.ts +46 -0
  11. package/dist/enc.js +88 -0
  12. package/dist/enc.js.map +1 -0
  13. package/dist/endemic-ot.js +24 -1
  14. package/dist/endemic-ot.js.map +1 -1
  15. package/dist/hybrid-ot.js +3 -0
  16. package/dist/hybrid-ot.js.map +1 -1
  17. package/dist/kem-ot.js +2 -0
  18. package/dist/kem-ot.js.map +1 -1
  19. package/dist/mascot.d.ts +81 -30
  20. package/dist/mascot.js +232 -113
  21. package/dist/mascot.js.map +1 -1
  22. package/dist/net/certs.d.ts +14 -0
  23. package/dist/net/certs.js +30 -0
  24. package/dist/net/certs.js.map +1 -0
  25. package/dist/net/faults.d.ts +49 -0
  26. package/dist/net/faults.js +222 -0
  27. package/dist/net/faults.js.map +1 -0
  28. package/dist/net/forensics.d.ts +81 -0
  29. package/dist/net/forensics.js +181 -0
  30. package/dist/net/forensics.js.map +1 -0
  31. package/dist/net/gadget.d.ts +44 -0
  32. package/dist/net/gadget.js +102 -0
  33. package/dist/net/gadget.js.map +1 -0
  34. package/dist/net/index.d.ts +11 -0
  35. package/dist/net/index.js +28 -0
  36. package/dist/net/index.js.map +1 -0
  37. package/dist/net/launch-local.d.ts +53 -0
  38. package/dist/net/launch-local.js +190 -0
  39. package/dist/net/launch-local.js.map +1 -0
  40. package/dist/net/launch-support.d.ts +6 -0
  41. package/dist/net/launch-support.js +65 -0
  42. package/dist/net/launch-support.js.map +1 -0
  43. package/dist/net/mesh.d.ts +135 -0
  44. package/dist/net/mesh.js +491 -0
  45. package/dist/net/mesh.js.map +1 -0
  46. package/dist/net/offline-net.d.ts +58 -0
  47. package/dist/net/offline-net.js +485 -0
  48. package/dist/net/offline-net.js.map +1 -0
  49. package/dist/net/ot-net.d.ts +42 -0
  50. package/dist/net/ot-net.js +219 -0
  51. package/dist/net/ot-net.js.map +1 -0
  52. package/dist/net/pa.d.ts +65 -0
  53. package/dist/net/pa.js +118 -0
  54. package/dist/net/pa.js.map +1 -0
  55. package/dist/net/party-main.d.ts +48 -0
  56. package/dist/net/party-main.js +146 -0
  57. package/dist/net/party-main.js.map +1 -0
  58. package/dist/net/prep.d.ts +40 -0
  59. package/dist/net/prep.js +12 -0
  60. package/dist/net/prep.js.map +1 -0
  61. package/dist/net/protocol.d.ts +126 -0
  62. package/dist/net/protocol.js +655 -0
  63. package/dist/net/protocol.js.map +1 -0
  64. package/dist/net/wire.d.ts +89 -0
  65. package/dist/net/wire.js +242 -0
  66. package/dist/net/wire.js.map +1 -0
  67. package/dist/ot.d.ts +176 -17
  68. package/dist/ot.js +479 -252
  69. package/dist/ot.js.map +1 -1
  70. package/dist/otx.d.ts +76 -0
  71. package/dist/otx.js +238 -0
  72. package/dist/otx.js.map +1 -0
  73. package/dist/runner.d.ts +1 -1
  74. package/dist/runner.js +6 -1
  75. package/dist/runner.js.map +1 -1
  76. package/dist/sharing.d.ts +2 -0
  77. package/dist/sharing.js +7 -4
  78. package/dist/sharing.js.map +1 -1
  79. package/dist/spdz-runner.d.ts +20 -3
  80. package/dist/spdz-runner.js +21 -3
  81. package/dist/spdz-runner.js.map +1 -1
  82. package/dist/spdz.d.ts +96 -22
  83. package/dist/spdz.js +196 -47
  84. package/dist/spdz.js.map +1 -1
  85. package/package.json +15 -6
@@ -0,0 +1,222 @@
1
+ "use strict";
2
+ /**
3
+ * TEST-ONLY fault injection for the networked MPC.
4
+ *
5
+ * Two layers, deliberately separate:
6
+ * - `tamperFor(spec)`: a MALICIOUS SENDER rewriting its own outgoing frames at the application layer
7
+ * (duplicate, reorder, skipped sequence, garbage, truncation, wrong round/session, oversize length,
8
+ * drop, silence). The bytes still travel inside valid TLS, so the receiver's framing checks decide.
9
+ * - `FaultProxy`: a NETWORK adversary on the wire (TCP middlebox): drop / delay / truncate / bit-flip /
10
+ * duplicate / reorder at the byte level. TLS 1.3 record authentication rejects tampering, so the
11
+ * expected outcome is an attributable-to-the-link `disconnect`, never a silently corrupted value.
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.FaultProxy = void 0;
48
+ exports.tamperFor = tamperFor;
49
+ const net = __importStar(require("node:net"));
50
+ const wire_1 = require("./wire");
51
+ function tamperFor(spec) {
52
+ const stash = new Map();
53
+ let silent = false;
54
+ return (ev) => {
55
+ if (silent)
56
+ return [];
57
+ const hit = ev.frame.rd === spec.round && (spec.to === undefined || spec.to === ev.to);
58
+ if (spec.kind === 'reorder') {
59
+ const held = stash.get(ev.to);
60
+ if (held) {
61
+ stash.delete(ev.to);
62
+ return [ev.raw, held]; // later frame first, then the held-back one
63
+ }
64
+ if (hit) {
65
+ stash.set(ev.to, ev.raw);
66
+ return [];
67
+ }
68
+ return [ev.raw];
69
+ }
70
+ if (!hit)
71
+ return [ev.raw];
72
+ switch (spec.kind) {
73
+ case 'duplicate':
74
+ return [ev.raw, ev.raw];
75
+ case 'skip-seq':
76
+ return [(0, wire_1.encodeFrame)({ ...ev.frame, seq: ev.frame.seq + 1 })];
77
+ case 'garbage': {
78
+ const g = Buffer.alloc(ev.raw.length, 0x5a);
79
+ g.writeUInt32BE(ev.raw.length - 4, 0);
80
+ return [g];
81
+ }
82
+ case 'truncate':
83
+ return [ev.raw.subarray(0, Math.max(5, Math.floor(ev.raw.length / 2)))];
84
+ case 'bitflip': {
85
+ const b = Buffer.from(ev.raw);
86
+ const i = Math.floor(b.length * 0.6);
87
+ b[i] = b[i] ^ 0x04;
88
+ return [b];
89
+ }
90
+ case 'wrong-round':
91
+ return [(0, wire_1.encodeFrame)({ ...ev.frame, rd: 'zzz-' + ev.frame.rd })];
92
+ case 'wrong-session':
93
+ return [(0, wire_1.encodeFrame)({ ...ev.frame, sid: 'not-this-session' })];
94
+ case 'oversize': {
95
+ const h = Buffer.alloc(4);
96
+ h.writeUInt32BE(0x7fffffff, 0);
97
+ return [h];
98
+ }
99
+ case 'drop':
100
+ return [];
101
+ case 'silent-from':
102
+ silent = true;
103
+ return [];
104
+ case 'false-accuse':
105
+ return [
106
+ (0, wire_1.encodeFrame)({ ...ev.frame, ty: 'abort', rd: 'abort', d: { kind: 'timeout', blamed: spec.accuse ?? 0, detail: 'forged accusation' } }),
107
+ ];
108
+ case 'extra-field':
109
+ return [(0, wire_1.encodeFrame)({ ...ev.frame, x: 1 })];
110
+ }
111
+ };
112
+ }
113
+ /** A transparent TCP proxy that misbehaves once, after `afterBytes` bytes, in one direction. */
114
+ class FaultProxy {
115
+ listenPort;
116
+ target;
117
+ fault;
118
+ server;
119
+ log = [];
120
+ constructor(listenPort, target, fault) {
121
+ this.listenPort = listenPort;
122
+ this.target = target;
123
+ this.fault = fault;
124
+ this.server = net.createServer((c) => this.onClient(c));
125
+ }
126
+ listen() {
127
+ return new Promise((res, rej) => {
128
+ this.server.once('error', rej);
129
+ this.server.listen(this.listenPort, '127.0.0.1', () => res());
130
+ });
131
+ }
132
+ close() {
133
+ this.server.close();
134
+ }
135
+ onClient(c) {
136
+ const up = net.connect(this.target.port, this.target.host);
137
+ c.on('error', () => up.destroy());
138
+ up.on('error', () => c.destroy());
139
+ c.on('close', () => up.destroy());
140
+ up.on('close', () => c.destroy());
141
+ this.pipe(c, up, 'c2s');
142
+ this.pipe(up, c, 's2c');
143
+ }
144
+ pipe(from, to, dir) {
145
+ const f = this.fault;
146
+ const active = f.kind !== 'none' && f.dir === dir;
147
+ let seen = 0;
148
+ let fired = false;
149
+ let done = false;
150
+ let held = null;
151
+ let pending = 0; // delayed writes in flight: a half-close must not overtake them
152
+ let ended = false;
153
+ from.on('data', (chunk) => {
154
+ const before = seen;
155
+ seen += chunk.length;
156
+ if (!active || done || before + chunk.length <= f.afterBytes) {
157
+ if (active && f.kind === 'drop' && fired)
158
+ return; // black hole stays black
159
+ to.write(chunk);
160
+ return;
161
+ }
162
+ if (!fired) {
163
+ fired = true;
164
+ this.log.push(`fault ${f.kind} ${dir} after ${f.afterBytes}B`);
165
+ }
166
+ switch (f.kind) {
167
+ case 'drop':
168
+ return;
169
+ case 'delay':
170
+ pending++;
171
+ setTimeout(() => {
172
+ if (!to.destroyed)
173
+ to.write(chunk);
174
+ pending--;
175
+ if (pending === 0 && ended)
176
+ to.end();
177
+ }, f.ms ?? 1000);
178
+ return;
179
+ case 'truncate':
180
+ done = true;
181
+ to.write(chunk.subarray(0, Math.floor(chunk.length / 2)));
182
+ to.end();
183
+ return;
184
+ case 'bitflip': {
185
+ done = true;
186
+ const b = Buffer.from(chunk);
187
+ const i = Math.floor(b.length / 2);
188
+ b[i] = b[i] ^ 0x01;
189
+ to.write(b);
190
+ return;
191
+ }
192
+ case 'duplicate':
193
+ done = true;
194
+ to.write(chunk);
195
+ to.write(chunk);
196
+ return;
197
+ case 'reorder':
198
+ if (!held) {
199
+ held = chunk;
200
+ }
201
+ else {
202
+ done = true;
203
+ to.write(chunk);
204
+ to.write(held);
205
+ held = null;
206
+ }
207
+ return;
208
+ default:
209
+ to.write(chunk);
210
+ }
211
+ });
212
+ from.on('end', () => {
213
+ if (held)
214
+ to.write(held);
215
+ ended = true;
216
+ if (pending === 0)
217
+ to.end();
218
+ });
219
+ }
220
+ }
221
+ exports.FaultProxy = FaultProxy;
222
+ //# sourceMappingURL=faults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"faults.js","sourceRoot":"","sources":["../../src/net/faults.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Post-abort disclosure of the discarded triple's OT transcript (dealer-free mode), so a wrong operand in the offline
3
+ * triple products is ATTRIBUTED instead of only detected.
4
+ *
5
+ * When the triple sacrifice fails at triple `t`, that triple (its shares `a`, `a-hat_r`, `b` and the OT masks of its
6
+ * product items) is thrown away and the session is over. Every party then discloses, for the failed triple only:
7
+ * for each product slot (the product c and each partner product c-hat_r) its choice bits, its sender operand `y`
8
+ * (its share of `b`), the product share it claimed, the values it RECEIVED from each peer and the masks `rho` it OFFERED to
9
+ * each peer. Nothing disclosed is a MAC-key share, an input, or anything used in a completed computation, so naming costs
10
+ * no privacy.
11
+ *
12
+ * Each ordered pair (receiver i, sender j) must satisfy `recv_i[j][k] = rho_j[i][k] + bit_k * g_k * y_j` (mod p), and every
13
+ * party's claimed product share must equal `value*y + sum_p recv[p] - sum_p rho[p]` from its own disclosure. A party whose own
14
+ * disclosure fails the second test is certainly lying. A pair failing the first test has exactly one liar among the two (the
15
+ * honest endpoint's data are consistent with its own OT view); the honest endpoint therefore blames its counterpart, a third
16
+ * party can only name the pair. As elsewhere in this package an accusation is evidence for the accuser, not proof for a
17
+ * third party, and with two corrupt parties a corrupt receiver can frame an honest sender.
18
+ *
19
+ * COMMIT FIRST (R3-17). Disclosures are not sent in the clear first: every party first broadcasts a hiding, binding
20
+ * commitment to its disclosure (`forensic-c`), and only after it holds ALL commitments does it open (`forensic-o`). A
21
+ * rushing corrupt OT sender therefore cannot read the honest receivers' choice bits and received values and then solve
22
+ * for a `rho` / `y` that passes every pair and self check: it has to commit before it can see anything. A party whose
23
+ * opening does not match its commitment is blamed (`commitment`); one that never commits or opens within the shared
24
+ * deadline is blamed by timeout, and the deadline (also carried in the commitment message) is recorded on the abort.
25
+ * Both are first-hand observations of the blaming party, not transferable proof. What attribution still cannot do:
26
+ * with two corrupt parties a corrupt receiver can make an honest sender's pair fail, and a pair failure between two
27
+ * parties neither of which is the verifier names no one (`blamed = null` with a reason).
28
+ */
29
+ export interface SlotDisclosure {
30
+ /** My OT choice bits for this product item (the encoding of my triple share). */
31
+ bits: number[];
32
+ /** My sender operand (my share of b). */
33
+ y: bigint;
34
+ /** The product share I claimed. */
35
+ z: bigint;
36
+ /** What I received as OT receiver, per peer. */
37
+ recv: Map<number, bigint[]>;
38
+ /** The masks rho I offered as OT sender, per peer. */
39
+ rho: Map<number, bigint[]>;
40
+ }
41
+ export type Disclosure = SlotDisclosure[];
42
+ export declare const slotsFor: (partners: number) => number;
43
+ export declare function wireDisclosure(d: Disclosure): unknown;
44
+ /** Strict parse of a peer's disclosure; throws `Error` on any deviation from the expected shape. */
45
+ export declare function parseDisclosure(raw: unknown, slots: number, rows: number, peers: readonly number[]): Disclosure;
46
+ export interface AuditResult {
47
+ /** Parties whose own disclosure is internally inconsistent (their claimed product share does not follow from it). */
48
+ selfBad: Set<number>;
49
+ /** Ordered pairs `[receiver, sender]` whose OT transcripts disagree. */
50
+ pairBad: Array<[number, number]>;
51
+ }
52
+ /** Cross-check every party's disclosure for one failed triple. `gadget` is the public choice-bit gadget. */
53
+ export declare function auditDisclosures(all: ReadonlyMap<number, Disclosure>, gadget: readonly bigint[]): AuditResult;
54
+ /**
55
+ * The party the verifier `me` blames, or null if the evidence cannot name one: a party with an inconsistent own disclosure;
56
+ * else the counterpart of a failing pair `me` belongs to (the honest endpoint's data are consistent, so its counterpart
57
+ * lied); else null.
58
+ */
59
+ export declare function blameFrom(me: number, r: AuditResult): number | null;
60
+ /** Default time (ms) every party has to produce its forensic commitment and opening. Shared by all parties and carried in the commit message. */
61
+ export declare const DEFAULT_FORENSIC_DEADLINE_MS = 30000;
62
+ /** Binding commitment to a disclosure: session, party, failed-triple index, deadline, a 256-bit nonce and the canonical wire form. */
63
+ export declare function disclosureCommit(sessionId: string, party: number, tripleIndex: number, deadlineMs: number, nonce: string, wire: unknown): string;
64
+ export interface ForensicExchangeArgs {
65
+ sessionId: string;
66
+ id: number;
67
+ n: number;
68
+ tripleIndex: number;
69
+ mine: Disclosure;
70
+ slots: number;
71
+ rows: number;
72
+ deadlineMs: number;
73
+ /** One un-echoed all-to-all round whose receive deadline is `deadlineMs`. */
74
+ exchange: <T>(rd: string, mine: (peer: number) => unknown, parse: (p: number, raw: unknown) => T, timeoutMs: number) => Promise<Map<number, T>>;
75
+ bad: (p: number, what: string) => never;
76
+ }
77
+ /**
78
+ * Commit-first disclosure exchange. Returns every OTHER party's verified disclosure. Nobody opens before every commitment is
79
+ * in hand (the `forensic-c` exchange completes first), so no party's disclosure can depend on another's.
80
+ */
81
+ export declare function exchangeDisclosures(a: ForensicExchangeArgs): Promise<Map<number, Disclosure>>;
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ /**
3
+ * Post-abort disclosure of the discarded triple's OT transcript (dealer-free mode), so a wrong operand in the offline
4
+ * triple products is ATTRIBUTED instead of only detected.
5
+ *
6
+ * When the triple sacrifice fails at triple `t`, that triple (its shares `a`, `a-hat_r`, `b` and the OT masks of its
7
+ * product items) is thrown away and the session is over. Every party then discloses, for the failed triple only:
8
+ * for each product slot (the product c and each partner product c-hat_r) its choice bits, its sender operand `y`
9
+ * (its share of `b`), the product share it claimed, the values it RECEIVED from each peer and the masks `rho` it OFFERED to
10
+ * each peer. Nothing disclosed is a MAC-key share, an input, or anything used in a completed computation, so naming costs
11
+ * no privacy.
12
+ *
13
+ * Each ordered pair (receiver i, sender j) must satisfy `recv_i[j][k] = rho_j[i][k] + bit_k * g_k * y_j` (mod p), and every
14
+ * party's claimed product share must equal `value*y + sum_p recv[p] - sum_p rho[p]` from its own disclosure. A party whose own
15
+ * disclosure fails the second test is certainly lying. A pair failing the first test has exactly one liar among the two (the
16
+ * honest endpoint's data are consistent with its own OT view); the honest endpoint therefore blames its counterpart, a third
17
+ * party can only name the pair. As elsewhere in this package an accusation is evidence for the accuser, not proof for a
18
+ * third party, and with two corrupt parties a corrupt receiver can frame an honest sender.
19
+ *
20
+ * COMMIT FIRST (R3-17). Disclosures are not sent in the clear first: every party first broadcasts a hiding, binding
21
+ * commitment to its disclosure (`forensic-c`), and only after it holds ALL commitments does it open (`forensic-o`). A
22
+ * rushing corrupt OT sender therefore cannot read the honest receivers' choice bits and received values and then solve
23
+ * for a `rho` / `y` that passes every pair and self check: it has to commit before it can see anything. A party whose
24
+ * opening does not match its commitment is blamed (`commitment`); one that never commits or opens within the shared
25
+ * deadline is blamed by timeout, and the deadline (also carried in the commitment message) is recorded on the abort.
26
+ * Both are first-hand observations of the blaming party, not transferable proof. What attribution still cannot do:
27
+ * with two corrupt parties a corrupt receiver can make an honest sender's pair fail, and a pair failure between two
28
+ * parties neither of which is the verifier names no one (`blamed = null` with a reason).
29
+ */
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ exports.DEFAULT_FORENSIC_DEADLINE_MS = exports.slotsFor = void 0;
32
+ exports.wireDisclosure = wireDisclosure;
33
+ exports.parseDisclosure = parseDisclosure;
34
+ exports.auditDisclosures = auditDisclosures;
35
+ exports.blameFrom = blameFrom;
36
+ exports.disclosureCommit = disclosureCommit;
37
+ exports.exchangeDisclosures = exchangeDisclosures;
38
+ const node_crypto_1 = require("node:crypto");
39
+ const field_1 = require("../field");
40
+ const wire_1 = require("./wire");
41
+ const wire_2 = require("./wire");
42
+ const slotsFor = (partners) => 1 + partners;
43
+ exports.slotsFor = slotsFor;
44
+ function wireDisclosure(d) {
45
+ return d.map((s) => ({
46
+ bits: s.bits.join(''),
47
+ y: (0, wire_2.hx)(s.y),
48
+ z: (0, wire_2.hx)(s.z),
49
+ recv: Array.from(s.recv.entries()).map(([p, v]) => [p, v.map(wire_2.hx)]),
50
+ rho: Array.from(s.rho.entries()).map(([p, v]) => [p, v.map(wire_2.hx)]),
51
+ }));
52
+ }
53
+ /** Strict parse of a peer's disclosure; throws `Error` on any deviation from the expected shape. */
54
+ function parseDisclosure(raw, slots, rows, peers) {
55
+ if (!Array.isArray(raw) || raw.length !== slots)
56
+ throw new Error('bad forensic disclosure');
57
+ const field = (s) => {
58
+ const v = (0, wire_2.unhx)(s);
59
+ if (v === null)
60
+ throw new Error('bad field element');
61
+ return v;
62
+ };
63
+ return raw.map((o) => {
64
+ const r = o;
65
+ if (typeof r?.bits !== 'string' || !new RegExp(`^[01]{${rows}}$`).test(r.bits))
66
+ throw new Error('bad choice bits');
67
+ const side = (x) => {
68
+ if (!Array.isArray(x) || x.length !== peers.length)
69
+ throw new Error('bad peer table');
70
+ const m = new Map();
71
+ for (const e of x) {
72
+ if (!Array.isArray(e) || e.length !== 2 || typeof e[0] !== 'number' || !peers.includes(e[0]) || m.has(e[0]))
73
+ throw new Error('bad peer entry');
74
+ if (!Array.isArray(e[1]) || e[1].length !== rows)
75
+ throw new Error('bad row table');
76
+ m.set(e[0], e[1].map(field));
77
+ }
78
+ return m;
79
+ };
80
+ return { bits: Array.from(r.bits, (c) => (c === '1' ? 1 : 0)), y: field(r.y), z: field(r.z), recv: side(r.recv), rho: side(r.rho) };
81
+ });
82
+ }
83
+ /** Cross-check every party's disclosure for one failed triple. `gadget` is the public choice-bit gadget. */
84
+ function auditDisclosures(all, gadget) {
85
+ const selfBad = new Set();
86
+ const pairBad = [];
87
+ const parties = Array.from(all.keys()).sort((a, b) => a - b);
88
+ for (const i of parties) {
89
+ const di = all.get(i);
90
+ for (let s = 0; s < di.length; s++) {
91
+ const sd = di[s];
92
+ let value = 0n;
93
+ for (let k = 0; k < gadget.length; k++)
94
+ if (sd.bits[k] === 1)
95
+ value += gadget[k];
96
+ let implied = (0, field_1.fmul)((0, field_1.mod)(value), sd.y);
97
+ for (const p of parties) {
98
+ if (p === i)
99
+ continue;
100
+ for (const v of sd.recv.get(p))
101
+ implied = (0, field_1.fadd)(implied, (0, field_1.mod)(v));
102
+ for (const v of sd.rho.get(p))
103
+ implied = (0, field_1.fsub)(implied, v);
104
+ }
105
+ if (implied !== sd.z)
106
+ selfBad.add(i);
107
+ for (const p of parties) {
108
+ if (p === i)
109
+ continue;
110
+ const sp = all.get(p)[s];
111
+ const rho = sp.rho.get(i);
112
+ const got = sd.recv.get(p);
113
+ const y = (0, field_1.mod)(sp.y);
114
+ let bad = false;
115
+ for (let k = 0; k < gadget.length && !bad; k++) {
116
+ const want = (0, field_1.fadd)(rho[k], sd.bits[k] === 1 ? (0, field_1.fmul)(gadget[k], y) : 0n);
117
+ if ((0, field_1.mod)(got[k]) !== want)
118
+ bad = true;
119
+ }
120
+ if (bad)
121
+ pairBad.push([i, p]);
122
+ }
123
+ }
124
+ }
125
+ void field_1.PRIME;
126
+ return { selfBad, pairBad };
127
+ }
128
+ /**
129
+ * The party the verifier `me` blames, or null if the evidence cannot name one: a party with an inconsistent own disclosure;
130
+ * else the counterpart of a failing pair `me` belongs to (the honest endpoint's data are consistent, so its counterpart
131
+ * lied); else null.
132
+ */
133
+ function blameFrom(me, r) {
134
+ const own = Array.from(r.selfBad).filter((p) => p !== me).sort((a, b) => a - b);
135
+ if (own.length > 0)
136
+ return own[0];
137
+ for (const [recv, send] of r.pairBad) {
138
+ if (recv === me)
139
+ return send;
140
+ if (send === me)
141
+ return recv;
142
+ }
143
+ return null;
144
+ }
145
+ // ---- commit-first exchange (R3-17) ----
146
+ /** Default time (ms) every party has to produce its forensic commitment and opening. Shared by all parties and carried in the commit message. */
147
+ exports.DEFAULT_FORENSIC_DEADLINE_MS = 30_000;
148
+ /** Binding commitment to a disclosure: session, party, failed-triple index, deadline, a 256-bit nonce and the canonical wire form. */
149
+ function disclosureCommit(sessionId, party, tripleIndex, deadlineMs, nonce, wire) {
150
+ return (0, node_crypto_1.createHash)('sha256')
151
+ .update('atlas-pca-mpc/forensic-commit/v1\0')
152
+ .update(JSON.stringify([sessionId, party, tripleIndex, deadlineMs, nonce, wire]))
153
+ .digest('hex');
154
+ }
155
+ /**
156
+ * Commit-first disclosure exchange. Returns every OTHER party's verified disclosure. Nobody opens before every commitment is
157
+ * in hand (the `forensic-c` exchange completes first), so no party's disclosure can depend on another's.
158
+ */
159
+ async function exchangeDisclosures(a) {
160
+ const wire = wireDisclosure(a.mine);
161
+ const nonce = (0, node_crypto_1.randomBytes)(32).toString('hex');
162
+ const myCommit = disclosureCommit(a.sessionId, a.id, a.tripleIndex, a.deadlineMs, nonce, wire);
163
+ const commits = await a.exchange('forensic-c', () => ({ c: myCommit, d: a.deadlineMs }), (p, raw) => {
164
+ const o = raw;
165
+ if (typeof o?.c !== 'string' || !/^[0-9a-f]{64}$/.test(o.c))
166
+ return a.bad(p, 'bad forensic commitment');
167
+ if (o.d !== a.deadlineMs)
168
+ return a.bad(p, `forensic deadline ${String(o.d)} differs from the agreed ${a.deadlineMs}`);
169
+ return o.c;
170
+ }, a.deadlineMs);
171
+ return a.exchange('forensic-o', () => ({ w: wire, nonce }), (p, raw) => {
172
+ const o = raw;
173
+ if (typeof o?.nonce !== 'string' || !/^[0-9a-f]{64}$/.test(o.nonce))
174
+ return a.bad(p, 'bad forensic opening');
175
+ if (disclosureCommit(a.sessionId, p, a.tripleIndex, a.deadlineMs, o.nonce, o.w) !== commits.get(p)) {
176
+ throw new wire_1.NetAbort('commitment', p, a.id, `party ${p} opened a forensic disclosure that does not match its commitment`);
177
+ }
178
+ return parseDisclosure(o.w, a.slots, a.rows, Array.from({ length: a.n }, (_, q) => q).filter((q) => q !== p));
179
+ }, a.deadlineMs);
180
+ }
181
+ //# sourceMappingURL=forensics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forensics.js","sourceRoot":"","sources":["../../src/net/forensics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Agreement on the joint choice-bit gadget seeds (R3-16): a signed commit-reveal with an echo round, so that ONE
3
+ * corrupt party cannot make the honest parties derive different gadgets and then blame each other.
4
+ *
5
+ * The plain commit-reveal (`gd-c` / `gd-o`) leaves each party's message to each peer unauthenticated beyond the TLS link,
6
+ * so a corrupt party can send a different commitment and seed to each honest peer. The honest parties then compute different
7
+ * gadgets, the triple sacrifice fails, and the forensic audit (which uses each verifier's OWN gadget) makes honest parties
8
+ * accuse each other while the corrupt one goes unnamed.
9
+ *
10
+ * Here every commitment and every opening is SIGNED by its sender with the sender's pinned TLS identity key. After the
11
+ * reveal each party echoes, to every peer, the signed values it received from each third party (`gd-e`). A receiver then
12
+ * checks each echoed statement against what it received directly:
13
+ *
14
+ * - an echoed signature that does not verify is a forgery by the echoer: blame the echoer (first-hand: I can verify
15
+ * the signature myself, and I need no one's word);
16
+ * - an echoed statement that verifies but differs from the one I received directly from the same signer means the signer
17
+ * signed two different values for the same round: blame the signer, with both signed statements as TRANSFERABLE evidence
18
+ * (any third party can verify both against the signer's pinned certificate). An honest party signs one value per
19
+ * round, so it can never be framed this way, and a corrupt echoer can only relay values the signer really signed.
20
+ *
21
+ * If every check passes, all honest parties hold identical seeds and so identical gadgets. A party that is silent, late
22
+ * or malformed is blamed by the existing receive deadline / schema checks (a local observation, see `NetAbort.deadlineMs`).
23
+ * With n = 2 there is no third party to equivocate towards, so the echo round is skipped.
24
+ */
25
+ /** What the gadget agreement needs from the transport. */
26
+ export interface GadgetNet {
27
+ selfId: number;
28
+ sessionId: string;
29
+ sign(data: Uint8Array): Uint8Array;
30
+ verify(peer: number, data: Uint8Array, sig: Uint8Array): boolean;
31
+ }
32
+ export interface GadgetIo {
33
+ /** One un-echoed all-to-all round; a throw inside `parse` aborts naming that peer. */
34
+ exchange: <T>(rd: string, mine: (peer: number) => unknown, parse: (p: number, raw: unknown) => T) => Promise<Map<number, T>>;
35
+ bad: (p: number, what: string) => never;
36
+ }
37
+ export declare const gadgetCommit: (sessionId: string, party: number, seed: Uint8Array) => string;
38
+ /** The exact bytes a party signs: domain, session, round, signer and value, length-unambiguous via JSON. */
39
+ export declare const gadgetStatement: (sessionId: string, round: "gd-c" | "gd-o", signer: number, value: string) => Uint8Array;
40
+ /**
41
+ * Run the signed commit / reveal / echo and return every party's seed in party order (mine included).
42
+ * `mySeed` is injectable for tests; production passes nothing.
43
+ */
44
+ export declare function agreeGadgetSeeds(net: GadgetNet, n: number, io: GadgetIo, mySeed?: Uint8Array): Promise<Uint8Array[]>;