@atlasauth/pca-mpc 0.3.0 → 0.4.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 +81 -3
- package/dist/beaver.js +4 -0
- package/dist/beaver.js.map +1 -1
- package/dist/compose.d.ts +9 -2
- package/dist/compose.js +24 -1
- package/dist/compose.js.map +1 -1
- package/dist/ec.d.ts +6 -3
- package/dist/ec.js +27 -9
- package/dist/ec.js.map +1 -1
- package/dist/enc.d.ts +46 -0
- package/dist/enc.js +88 -0
- package/dist/enc.js.map +1 -0
- package/dist/endemic-ot.js +24 -1
- package/dist/endemic-ot.js.map +1 -1
- package/dist/hybrid-ot.js +3 -0
- package/dist/hybrid-ot.js.map +1 -1
- package/dist/kem-ot.js +2 -0
- package/dist/kem-ot.js.map +1 -1
- package/dist/mascot.d.ts +81 -30
- package/dist/mascot.js +232 -113
- package/dist/mascot.js.map +1 -1
- package/dist/net/certs.d.ts +14 -0
- package/dist/net/certs.js +30 -0
- package/dist/net/certs.js.map +1 -0
- package/dist/net/faults.d.ts +49 -0
- package/dist/net/faults.js +222 -0
- package/dist/net/faults.js.map +1 -0
- package/dist/net/forensics.d.ts +81 -0
- package/dist/net/forensics.js +181 -0
- package/dist/net/forensics.js.map +1 -0
- package/dist/net/gadget.d.ts +44 -0
- package/dist/net/gadget.js +102 -0
- package/dist/net/gadget.js.map +1 -0
- package/dist/net/index.d.ts +11 -0
- package/dist/net/index.js +28 -0
- package/dist/net/index.js.map +1 -0
- package/dist/net/launch-local.d.ts +53 -0
- package/dist/net/launch-local.js +190 -0
- package/dist/net/launch-local.js.map +1 -0
- package/dist/net/launch-support.d.ts +6 -0
- package/dist/net/launch-support.js +65 -0
- package/dist/net/launch-support.js.map +1 -0
- package/dist/net/mesh.d.ts +135 -0
- package/dist/net/mesh.js +491 -0
- package/dist/net/mesh.js.map +1 -0
- package/dist/net/offline-net.d.ts +58 -0
- package/dist/net/offline-net.js +485 -0
- package/dist/net/offline-net.js.map +1 -0
- package/dist/net/ot-net.d.ts +42 -0
- package/dist/net/ot-net.js +219 -0
- package/dist/net/ot-net.js.map +1 -0
- package/dist/net/pa.d.ts +65 -0
- package/dist/net/pa.js +118 -0
- package/dist/net/pa.js.map +1 -0
- package/dist/net/party-main.d.ts +48 -0
- package/dist/net/party-main.js +146 -0
- package/dist/net/party-main.js.map +1 -0
- package/dist/net/prep.d.ts +40 -0
- package/dist/net/prep.js +12 -0
- package/dist/net/prep.js.map +1 -0
- package/dist/net/protocol.d.ts +126 -0
- package/dist/net/protocol.js +655 -0
- package/dist/net/protocol.js.map +1 -0
- package/dist/net/wire.d.ts +89 -0
- package/dist/net/wire.js +242 -0
- package/dist/net/wire.js.map +1 -0
- package/dist/ot.d.ts +176 -17
- package/dist/ot.js +479 -252
- package/dist/ot.js.map +1 -1
- package/dist/otx.d.ts +76 -0
- package/dist/otx.js +238 -0
- package/dist/otx.js.map +1 -0
- package/dist/runner.d.ts +1 -1
- package/dist/runner.js +6 -1
- package/dist/runner.js.map +1 -1
- package/dist/sharing.d.ts +2 -0
- package/dist/sharing.js +7 -4
- package/dist/sharing.js.map +1 -1
- package/dist/spdz-runner.d.ts +20 -3
- package/dist/spdz-runner.js +21 -3
- package/dist/spdz-runner.js.map +1 -1
- package/dist/spdz.d.ts +96 -22
- package/dist/spdz.js +196 -47
- package/dist/spdz.js.map +1 -1
- package/package.json +15 -6
package/dist/net/mesh.js
ADDED
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Authenticated, confidential, fail-closed point-to-point mesh over TLS 1.3 (research prototype).
|
|
4
|
+
*
|
|
5
|
+
* - MUTUAL TLS with PINNED self-signed certificates (generated per run by `certs.ts`). A peer is
|
|
6
|
+
* identified by the SHA-256 fingerprint of its certificate, never by anything it claims; the claimed
|
|
7
|
+
* id in the hello frame must agree with the pinned fingerprint.
|
|
8
|
+
* - Strict framing + per-link sequence numbers. A malformed frame, a duplicate / replayed frame, a
|
|
9
|
+
* skipped (out-of-order) frame, a frame for the wrong round or session, or an oversize length
|
|
10
|
+
* prefix aborts the whole run with an ATTRIBUTABLE `NetAbort` naming the sender.
|
|
11
|
+
* - Timeouts on every receive (no hangs); a silent peer is blamed after `recvTimeoutMs`.
|
|
12
|
+
* - ABORT PROPAGATION: the first failure poisons the mesh, wakes every pending receive, best-effort
|
|
13
|
+
* sends an `abort` frame to every peer (so they stop immediately and learn who we blame), then
|
|
14
|
+
* closes the sockets. Once failed, nothing further is sent as protocol data (fail closed).
|
|
15
|
+
*
|
|
16
|
+
* Network faults (drop, truncate, bit-flip, reorder, duplicate at the TCP level) are all caught by TLS
|
|
17
|
+
* record authentication and surface as `disconnect` on that link. Application-level misbehaviour
|
|
18
|
+
* (replay, skipped sequence, garbage, wrong round) is caught by the framing checks here. See the tests.
|
|
19
|
+
*/
|
|
20
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
23
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
24
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
25
|
+
}
|
|
26
|
+
Object.defineProperty(o, k2, desc);
|
|
27
|
+
}) : (function(o, m, k, k2) {
|
|
28
|
+
if (k2 === undefined) k2 = k;
|
|
29
|
+
o[k2] = m[k];
|
|
30
|
+
}));
|
|
31
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
32
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
33
|
+
}) : function(o, v) {
|
|
34
|
+
o["default"] = v;
|
|
35
|
+
});
|
|
36
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
37
|
+
var ownKeys = function(o) {
|
|
38
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
39
|
+
var ar = [];
|
|
40
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
41
|
+
return ar;
|
|
42
|
+
};
|
|
43
|
+
return ownKeys(o);
|
|
44
|
+
};
|
|
45
|
+
return function (mod) {
|
|
46
|
+
if (mod && mod.__esModule) return mod;
|
|
47
|
+
var result = {};
|
|
48
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
49
|
+
__setModuleDefault(result, mod);
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
52
|
+
})();
|
|
53
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
+
exports.Mesh = exports.MAX_MESH_EVENTS = exports.wallClock = void 0;
|
|
55
|
+
const node_crypto_1 = require("node:crypto");
|
|
56
|
+
const node_events_1 = require("node:events");
|
|
57
|
+
const tls = __importStar(require("node:tls"));
|
|
58
|
+
const node_tls_1 = require("node:tls");
|
|
59
|
+
const wire_1 = require("./wire");
|
|
60
|
+
const certs_1 = require("./certs");
|
|
61
|
+
exports.wallClock = {
|
|
62
|
+
now: () => Date.now(),
|
|
63
|
+
setTimer: (fn, ms) => setTimeout(fn, ms),
|
|
64
|
+
clearTimer: (h) => clearTimeout(h),
|
|
65
|
+
};
|
|
66
|
+
/** Most non-fatal observations kept in `Mesh.events`; further ones are only counted. */
|
|
67
|
+
exports.MAX_MESH_EVENTS = 64;
|
|
68
|
+
class Mesh {
|
|
69
|
+
selfId;
|
|
70
|
+
cfg;
|
|
71
|
+
links = new Map();
|
|
72
|
+
pinned = new Map(); // fingerprint -> node id
|
|
73
|
+
ev = new node_events_1.EventEmitter();
|
|
74
|
+
server = null;
|
|
75
|
+
failure = null;
|
|
76
|
+
finished = false;
|
|
77
|
+
clock;
|
|
78
|
+
recvTimeoutMs;
|
|
79
|
+
connectTimeoutMs;
|
|
80
|
+
/** Non-fatal observations (e.g. a TLS client rejected at the door) for evidence logs. */
|
|
81
|
+
events = [];
|
|
82
|
+
/** Observations beyond `MAX_MESH_EVENTS` that were counted but not stored. */
|
|
83
|
+
eventsDropped = 0;
|
|
84
|
+
maxInboxFrames;
|
|
85
|
+
maxInboxBytes;
|
|
86
|
+
constructor(cfg) {
|
|
87
|
+
this.cfg = cfg;
|
|
88
|
+
this.selfId = cfg.selfId;
|
|
89
|
+
this.clock = cfg.clock ?? exports.wallClock;
|
|
90
|
+
this.recvTimeoutMs = cfg.recvTimeoutMs ?? 20_000;
|
|
91
|
+
this.connectTimeoutMs = cfg.connectTimeoutMs ?? 30_000;
|
|
92
|
+
if (cfg.tamper && cfg.unsafeTestHooks !== true) {
|
|
93
|
+
throw new Error('mesh: the tamper test hook requires unsafeTestHooks: true (test-only)');
|
|
94
|
+
}
|
|
95
|
+
this.maxInboxFrames = cfg.maxInboxFrames ?? 1024;
|
|
96
|
+
this.maxInboxBytes = cfg.maxInboxBytes ?? 32 * 1024 * 1024;
|
|
97
|
+
this.ev.setMaxListeners(0);
|
|
98
|
+
const want = cfg.linkTo ?? cfg.nodes.map((n) => n.id).filter((i) => i !== cfg.selfId);
|
|
99
|
+
for (const n of cfg.nodes) {
|
|
100
|
+
if (n.id !== cfg.selfId)
|
|
101
|
+
this.pinned.set((0, certs_1.fingerprintOf)(n.certPem), n.id);
|
|
102
|
+
}
|
|
103
|
+
for (const id of want) {
|
|
104
|
+
if (!cfg.nodes.some((n) => n.id === id))
|
|
105
|
+
throw new Error(`mesh: unknown link target ${id}`);
|
|
106
|
+
this.links.set(id, newLink(id));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
note(msg) {
|
|
110
|
+
if (this.events.length < exports.MAX_MESH_EVENTS)
|
|
111
|
+
this.events.push(msg);
|
|
112
|
+
else
|
|
113
|
+
this.eventsDropped++;
|
|
114
|
+
}
|
|
115
|
+
/** The session id every frame on this mesh carries (used to bind sub-protocols to this session). */
|
|
116
|
+
get sessionId() {
|
|
117
|
+
return this.cfg.sessionId;
|
|
118
|
+
}
|
|
119
|
+
get peers() {
|
|
120
|
+
return [...this.links.keys()].sort((a, b) => a - b);
|
|
121
|
+
}
|
|
122
|
+
get failed() {
|
|
123
|
+
return this.failure;
|
|
124
|
+
}
|
|
125
|
+
// ------------------------------------------------------------------ connect
|
|
126
|
+
/** Listen, dial every lower-numbered link target, and wait until all links are authenticated. */
|
|
127
|
+
async connect() {
|
|
128
|
+
const self = this.cfg.nodes.find((n) => n.id === this.selfId);
|
|
129
|
+
if (!self)
|
|
130
|
+
throw new Error('mesh: self not in nodes');
|
|
131
|
+
const others = this.cfg.nodes.filter((n) => n.id !== this.selfId);
|
|
132
|
+
this.server = (0, node_tls_1.createServer)({
|
|
133
|
+
key: this.cfg.keyPem,
|
|
134
|
+
cert: this.cfg.certPem,
|
|
135
|
+
ca: others.map((n) => n.certPem),
|
|
136
|
+
requestCert: true,
|
|
137
|
+
rejectUnauthorized: true,
|
|
138
|
+
minVersion: 'TLSv1.3',
|
|
139
|
+
}, (sock) => this.onIncoming(sock));
|
|
140
|
+
this.server.on('tlsClientError', (e) => this.note(`tlsClientError: ${e.message.slice(0, 120)}`));
|
|
141
|
+
this.server.on('error', (e) => this.note(`server error: ${e.message}`));
|
|
142
|
+
await new Promise((res, rej) => {
|
|
143
|
+
this.server.once('error', rej);
|
|
144
|
+
this.server.listen(self.port, this.cfg.listenHost ?? '0.0.0.0', () => res());
|
|
145
|
+
});
|
|
146
|
+
const deadline = this.clock.now() + this.connectTimeoutMs;
|
|
147
|
+
for (const id of this.peers) {
|
|
148
|
+
if (id < this.selfId)
|
|
149
|
+
void this.dial(id, deadline);
|
|
150
|
+
}
|
|
151
|
+
// wait for all links to complete the authenticated hello exchange (poll; bounded by the deadline)
|
|
152
|
+
for (;;) {
|
|
153
|
+
if (this.failure)
|
|
154
|
+
throw this.failure;
|
|
155
|
+
const missing = this.peers.filter((i) => !this.links.get(i).helloSeen);
|
|
156
|
+
if (missing.length === 0)
|
|
157
|
+
return;
|
|
158
|
+
if (this.clock.now() > deadline) {
|
|
159
|
+
const e = new wire_1.NetAbort('timeout', missing[0], this.selfId, `connect: no authenticated link from ${missing.join(',')}`);
|
|
160
|
+
this.fail(e);
|
|
161
|
+
throw e;
|
|
162
|
+
}
|
|
163
|
+
await new Promise((r) => setTimeout(r, 20)); // a poll interval, not a decision: real time
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
async dial(id, deadline) {
|
|
167
|
+
const node = this.cfg.nodes.find((n) => n.id === id);
|
|
168
|
+
while (!this.failure && this.clock.now() < deadline) {
|
|
169
|
+
const ok = await new Promise((resolve) => {
|
|
170
|
+
const sock = tls.connect({
|
|
171
|
+
host: node.host,
|
|
172
|
+
port: node.port,
|
|
173
|
+
key: this.cfg.keyPem,
|
|
174
|
+
cert: this.cfg.certPem,
|
|
175
|
+
ca: [node.certPem],
|
|
176
|
+
minVersion: 'TLSv1.3',
|
|
177
|
+
// We pin by certificate (ca = exactly that cert + fingerprint check below), not by hostname.
|
|
178
|
+
checkServerIdentity: () => undefined,
|
|
179
|
+
});
|
|
180
|
+
let settled = false;
|
|
181
|
+
sock.once('secureConnect', () => {
|
|
182
|
+
settled = true;
|
|
183
|
+
const fp = sock.getPeerCertificate().fingerprint256;
|
|
184
|
+
if (!sock.authorized || this.pinned.get(fp) !== id) {
|
|
185
|
+
sock.destroy();
|
|
186
|
+
this.fail(new wire_1.NetAbort('identity', id, this.selfId, `dial: peer certificate is not the pinned identity of node ${id}`));
|
|
187
|
+
return resolve(true);
|
|
188
|
+
}
|
|
189
|
+
this.attach(id, sock);
|
|
190
|
+
resolve(true);
|
|
191
|
+
});
|
|
192
|
+
sock.once('error', () => {
|
|
193
|
+
if (!settled) {
|
|
194
|
+
sock.destroy();
|
|
195
|
+
resolve(false);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
if (ok)
|
|
200
|
+
return;
|
|
201
|
+
await new Promise((r) => setTimeout(r, 150)); // retry pacing, not a decision: real time
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
onIncoming(sock) {
|
|
205
|
+
sock.on('error', () => undefined);
|
|
206
|
+
const fp = sock.getPeerCertificate().fingerprint256;
|
|
207
|
+
const id = fp ? this.pinned.get(fp) : undefined;
|
|
208
|
+
if (!sock.authorized || id === undefined || !this.links.has(id) || id < this.selfId) {
|
|
209
|
+
this.note(`rejected incoming connection (fp=${fp ?? 'none'})`);
|
|
210
|
+
sock.destroy();
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const l = this.links.get(id);
|
|
214
|
+
if (l.socket) {
|
|
215
|
+
// a second connection claiming an already-linked identity
|
|
216
|
+
this.note(`duplicate connection from node ${id}`);
|
|
217
|
+
sock.destroy();
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
this.attach(id, sock);
|
|
221
|
+
}
|
|
222
|
+
attach(id, sock) {
|
|
223
|
+
const l = this.links.get(id);
|
|
224
|
+
if (l.socket) {
|
|
225
|
+
sock.destroy();
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
l.socket = sock;
|
|
229
|
+
sock.setNoDelay(true);
|
|
230
|
+
sock.on('data', (chunk) => this.onData(l, chunk));
|
|
231
|
+
sock.on('error', (e) => this.onClosed(l, `socket error: ${e.message}`));
|
|
232
|
+
sock.on('close', () => this.onClosed(l, 'socket closed'));
|
|
233
|
+
sock.on('end', () => this.onClosed(l, 'peer ended'));
|
|
234
|
+
// hello: first frame on every link (seq 0); carries our id so the peer can cross-check the pin.
|
|
235
|
+
this.sendFrame(l, 'hello', 'hello', { id: this.selfId });
|
|
236
|
+
}
|
|
237
|
+
// ------------------------------------------------------------------ receive path
|
|
238
|
+
onData(l, chunk) {
|
|
239
|
+
if (this.failure)
|
|
240
|
+
return;
|
|
241
|
+
l.bytesIn += chunk.length;
|
|
242
|
+
let bodies;
|
|
243
|
+
try {
|
|
244
|
+
bodies = l.splitter.push(chunk);
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
return this.fail(new wire_1.NetAbort('oversize', l.id, this.selfId, 'length prefix above MAX_FRAME_BYTES'));
|
|
248
|
+
}
|
|
249
|
+
for (const b of bodies) {
|
|
250
|
+
const f = (0, wire_1.parseFrame)(b);
|
|
251
|
+
if (!f) {
|
|
252
|
+
const pv = (0, wire_1.versionMismatch)(b);
|
|
253
|
+
if (pv !== null) {
|
|
254
|
+
return this.fail(new wire_1.NetAbort('version', l.id, this.selfId, `peer ${l.id} speaks wire version ${pv}, this node speaks ${wire_1.WIRE_VERSION}; upgrade both peers`));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (!f)
|
|
258
|
+
return this.fail(new wire_1.NetAbort('malformed', l.id, this.selfId, 'undecodable or ill-shaped frame'));
|
|
259
|
+
if (f.sid !== this.cfg.sessionId) {
|
|
260
|
+
return this.fail(new wire_1.NetAbort('wrong-session', l.id, this.selfId, 'frame from another session'));
|
|
261
|
+
}
|
|
262
|
+
if (f.ty === 'abort') {
|
|
263
|
+
// An abort frame is only a CLAIM by the peer that sent it. We blame that peer (the authenticated
|
|
264
|
+
// sender), never the party it names: otherwise any peer could frame an honest one.
|
|
265
|
+
const d = f.d;
|
|
266
|
+
// a relayed abort is second-hand (an honest peer passing on what ITS peer said): it names no one
|
|
267
|
+
const relayed = d?.relayed === true;
|
|
268
|
+
const claimedKind = typeof d?.kind === 'string' && wire_1.ABORT_KINDS.has(d.kind) ? d.kind : undefined;
|
|
269
|
+
const maxId = Math.max(...this.cfg.nodes.map((x) => x.id));
|
|
270
|
+
const claimedBlame = typeof d?.blamed === 'number' && Number.isInteger(d.blamed) && d.blamed >= 0 && d.blamed <= maxId ? d.blamed : null;
|
|
271
|
+
const detail = typeof d?.detail === 'string' ? sanitize(d.detail, 120) : '';
|
|
272
|
+
return this.fail(new wire_1.NetAbort('peer-abort', relayed ? null : l.id, this.selfId, `peer ${l.id} ${relayed ? 'relayed' : 'reported'} an abort (${claimedKind ?? 'unspecified'}, accuses ${claimedBlame === null ? 'no one' : claimedBlame}, unverified) ${detail}`, claimedKind, claimedBlame, relayed ? { reason: 'relayed abort: a second-hand claim passed on by an honest peer; it names no one and is never evidence' } : {}), l.id);
|
|
273
|
+
}
|
|
274
|
+
if (f.seq !== l.recvSeq) {
|
|
275
|
+
const kind = f.seq < l.recvSeq ? 'duplicate' : 'out-of-order';
|
|
276
|
+
return this.fail(new wire_1.NetAbort(kind, l.id, this.selfId, `expected seq ${l.recvSeq}, got ${f.seq} (round ${f.rd})`));
|
|
277
|
+
}
|
|
278
|
+
l.recvSeq++;
|
|
279
|
+
l.framesIn++;
|
|
280
|
+
if (f.ty === 'hello') {
|
|
281
|
+
const d = f.d;
|
|
282
|
+
if (l.helloSeen || d?.id !== l.id) {
|
|
283
|
+
return this.fail(new wire_1.NetAbort('identity', l.id, this.selfId, `hello claims id ${String(d?.id)} on the link pinned to ${l.id}`));
|
|
284
|
+
}
|
|
285
|
+
l.helloSeen = true;
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
if (!l.helloSeen)
|
|
289
|
+
return this.fail(new wire_1.NetAbort('malformed', l.id, this.selfId, 'data before hello'));
|
|
290
|
+
l.inbox.push({ f, size: b.length });
|
|
291
|
+
l.inboxBytes += b.length;
|
|
292
|
+
if (l.inbox.length > this.maxInboxFrames || l.inboxBytes > this.maxInboxBytes) {
|
|
293
|
+
return this.fail(new wire_1.NetAbort('flood', l.id, this.selfId, `peer ${l.id} queued more than the inbox cap allows`));
|
|
294
|
+
}
|
|
295
|
+
if (!l.paused && (l.inbox.length > this.maxInboxFrames / 2 || l.inboxBytes > this.maxInboxBytes / 2)) {
|
|
296
|
+
l.paused = true;
|
|
297
|
+
l.socket?.pause();
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
this.ev.emit('wake');
|
|
302
|
+
}
|
|
303
|
+
onClosed(l, why) {
|
|
304
|
+
if (l.closed)
|
|
305
|
+
return;
|
|
306
|
+
l.closed = true;
|
|
307
|
+
if (!this.finished && !this.failure && !l.helloSeen) {
|
|
308
|
+
this.note(`link ${l.id} closed before hello: ${why}`);
|
|
309
|
+
}
|
|
310
|
+
this.ev.emit('wake');
|
|
311
|
+
}
|
|
312
|
+
// ------------------------------------------------------------------ send path
|
|
313
|
+
sendFrame(l, ty, rd, d) {
|
|
314
|
+
const frame = { v: wire_1.WIRE_VERSION, ty, sid: this.cfg.sessionId, seq: l.sendSeq++, rd, d };
|
|
315
|
+
const raw = (0, wire_1.encodeFrame)(frame);
|
|
316
|
+
const outs = this.cfg.tamper && ty !== 'hello' ? this.cfg.tamper({ to: l.id, frame, raw }) : [raw];
|
|
317
|
+
for (const b of outs) {
|
|
318
|
+
if (l.socket && !l.socket.destroyed) {
|
|
319
|
+
l.socket.write(b);
|
|
320
|
+
l.bytesOut += b.length;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
l.framesOut++;
|
|
324
|
+
}
|
|
325
|
+
/** Send a protocol message to one peer. Throws the mesh failure if already aborted (fail closed). */
|
|
326
|
+
send(to, round, payload) {
|
|
327
|
+
if (this.failure)
|
|
328
|
+
throw this.failure;
|
|
329
|
+
const l = this.links.get(to);
|
|
330
|
+
if (!l)
|
|
331
|
+
throw new Error(`mesh: no link to ${to}`);
|
|
332
|
+
this.sendFrame(l, 'msg', round, payload);
|
|
333
|
+
}
|
|
334
|
+
broadcast(round, payload, to = this.peers) {
|
|
335
|
+
for (const p of to)
|
|
336
|
+
this.send(p, round, payload);
|
|
337
|
+
}
|
|
338
|
+
/** ECDSA-P256/SHA-256 signature over `data` with this node's TLS identity key (transferable: verifiable against the pinned certificate). */
|
|
339
|
+
sign(data) {
|
|
340
|
+
return (0, node_crypto_1.sign)('sha256', Buffer.from(data), this.cfg.keyPem);
|
|
341
|
+
}
|
|
342
|
+
/** Verify `sig` over `data` against the PINNED certificate of node `peer`. False on any failure (never throws). */
|
|
343
|
+
verify(peer, data, sig) {
|
|
344
|
+
const n = this.cfg.nodes.find((x) => x.id === peer);
|
|
345
|
+
if (!n || peer === this.selfId)
|
|
346
|
+
return false;
|
|
347
|
+
try {
|
|
348
|
+
return (0, node_crypto_1.verify)('sha256', Buffer.from(data), new node_crypto_1.X509Certificate(n.certPem).publicKey, Buffer.from(sig));
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
/** Receive the next message from `from`, which must belong to `round`. Times out; never hangs. */
|
|
355
|
+
async recv(from, round, timeoutMs = this.recvTimeoutMs) {
|
|
356
|
+
const l = this.links.get(from);
|
|
357
|
+
if (!l)
|
|
358
|
+
throw new Error(`mesh: no link to ${from}`);
|
|
359
|
+
const deadline = this.clock.now() + timeoutMs;
|
|
360
|
+
for (;;) {
|
|
361
|
+
if (this.failure)
|
|
362
|
+
throw this.failure;
|
|
363
|
+
const it = l.inbox.shift();
|
|
364
|
+
if (it) {
|
|
365
|
+
const f = it.f;
|
|
366
|
+
l.inboxBytes -= it.size;
|
|
367
|
+
if (l.paused && l.inbox.length <= this.maxInboxFrames / 2 && l.inboxBytes <= this.maxInboxBytes / 2) {
|
|
368
|
+
l.paused = false;
|
|
369
|
+
l.socket?.resume();
|
|
370
|
+
}
|
|
371
|
+
if (f.rd !== round) {
|
|
372
|
+
const e = new wire_1.NetAbort('wrong-round', from, this.selfId, `expected round '${round}', got '${f.rd}'`);
|
|
373
|
+
this.fail(e);
|
|
374
|
+
throw e;
|
|
375
|
+
}
|
|
376
|
+
return f.d;
|
|
377
|
+
}
|
|
378
|
+
if (l.closed) {
|
|
379
|
+
const e = new wire_1.NetAbort('disconnect', from, this.selfId, `link to ${from} closed while awaiting '${round}'`);
|
|
380
|
+
this.fail(e);
|
|
381
|
+
throw e;
|
|
382
|
+
}
|
|
383
|
+
const left = deadline - this.clock.now();
|
|
384
|
+
if (left <= 0) {
|
|
385
|
+
const e = new wire_1.NetAbort('timeout', from, this.selfId, `no '${round}' message from ${from} within ${timeoutMs}ms (deadline ${timeoutMs}ms; a silent peer is blamed on this local observation only)`, undefined, undefined, { deadlineMs: timeoutMs });
|
|
386
|
+
this.fail(e);
|
|
387
|
+
throw e;
|
|
388
|
+
}
|
|
389
|
+
await new Promise((res) => {
|
|
390
|
+
const done = () => {
|
|
391
|
+
this.clock.clearTimer(t);
|
|
392
|
+
this.ev.off('wake', done);
|
|
393
|
+
res();
|
|
394
|
+
};
|
|
395
|
+
const t = this.clock.setTimer(done, left);
|
|
396
|
+
this.ev.on('wake', done);
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
/** Receive `round` from every peer in `from` concurrently. A failure on any link rejects the whole call. */
|
|
401
|
+
async collect(round, from = this.peers, timeoutMs) {
|
|
402
|
+
const got = await Promise.all(from.map(async (p) => [p, await this.recv(p, round, timeoutMs)]));
|
|
403
|
+
return new Map(got);
|
|
404
|
+
}
|
|
405
|
+
// ------------------------------------------------------------------ failure / shutdown
|
|
406
|
+
/**
|
|
407
|
+
* Poison the mesh: record the first failure, tell EVERY peer except `skipPeer` (the one that just told us;
|
|
408
|
+
* forwarding the original accusation so an innocent bystander is never blamed for merely closing), close all.
|
|
409
|
+
*/
|
|
410
|
+
fail(err, skipPeer) {
|
|
411
|
+
if (this.failure)
|
|
412
|
+
return;
|
|
413
|
+
this.failure = err;
|
|
414
|
+
{
|
|
415
|
+
for (const l of this.links.values()) {
|
|
416
|
+
if (l.id === skipPeer)
|
|
417
|
+
continue;
|
|
418
|
+
if (l.socket && !l.socket.destroyed && !l.closed) {
|
|
419
|
+
try {
|
|
420
|
+
// a forwarded peer-abort stays a claim: we pass on what was claimed, receivers re-attribute to us
|
|
421
|
+
const kind = err.kind === 'peer-abort' ? (err.claimedKind ?? 'peer-abort') : err.kind;
|
|
422
|
+
const blamed = err.kind === 'peer-abort' ? (err.claimedBlame ?? null) : err.blamed;
|
|
423
|
+
this.sendFrameRaw(l, { kind, blamed, detail: sanitize(err.message, 200), ...(err.kind === 'peer-abort' ? { relayed: true } : {}) });
|
|
424
|
+
}
|
|
425
|
+
catch {
|
|
426
|
+
/* best effort */
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
this.ev.emit('wake');
|
|
432
|
+
setTimeout(() => this.closeAll(), 50).unref();
|
|
433
|
+
}
|
|
434
|
+
sendFrameRaw(l, d) {
|
|
435
|
+
const frame = { v: wire_1.WIRE_VERSION, ty: 'abort', sid: this.cfg.sessionId, seq: l.sendSeq++, rd: 'abort', d };
|
|
436
|
+
l.socket.write((0, wire_1.encodeFrame)(frame));
|
|
437
|
+
}
|
|
438
|
+
/** Normal completion: flush and close. Peers that are still reading will see EOF only after our data. */
|
|
439
|
+
async finish() {
|
|
440
|
+
this.finished = true;
|
|
441
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
442
|
+
this.closeAll();
|
|
443
|
+
}
|
|
444
|
+
closeAll() {
|
|
445
|
+
for (const l of this.links.values())
|
|
446
|
+
l.socket?.end();
|
|
447
|
+
setTimeout(() => {
|
|
448
|
+
for (const l of this.links.values())
|
|
449
|
+
l.socket?.destroy();
|
|
450
|
+
this.server?.close();
|
|
451
|
+
}, 100).unref();
|
|
452
|
+
}
|
|
453
|
+
stats() {
|
|
454
|
+
return this.peers.map((p) => {
|
|
455
|
+
const l = this.links.get(p);
|
|
456
|
+
return {
|
|
457
|
+
peer: p,
|
|
458
|
+
appBytesOut: l.bytesOut,
|
|
459
|
+
appBytesIn: l.bytesIn,
|
|
460
|
+
framesOut: l.framesOut,
|
|
461
|
+
framesIn: l.framesIn,
|
|
462
|
+
tlsBytesWritten: l.socket?.bytesWritten ?? 0,
|
|
463
|
+
tlsBytesRead: l.socket?.bytesRead ?? 0,
|
|
464
|
+
};
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
exports.Mesh = Mesh;
|
|
469
|
+
function newLink(id) {
|
|
470
|
+
return {
|
|
471
|
+
id,
|
|
472
|
+
socket: null,
|
|
473
|
+
splitter: new wire_1.FrameSplitter(),
|
|
474
|
+
inbox: [],
|
|
475
|
+
inboxBytes: 0,
|
|
476
|
+
paused: false,
|
|
477
|
+
sendSeq: 0,
|
|
478
|
+
recvSeq: 0,
|
|
479
|
+
closed: false,
|
|
480
|
+
helloSeen: false,
|
|
481
|
+
bytesIn: 0,
|
|
482
|
+
bytesOut: 0,
|
|
483
|
+
framesIn: 0,
|
|
484
|
+
framesOut: 0,
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
/** Printable-ASCII, length-capped copy of untrusted text (no control characters, no log forging). */
|
|
488
|
+
function sanitize(x, max) {
|
|
489
|
+
return x.replace(/[^\x20-\x7e]/g, '?').slice(0, max);
|
|
490
|
+
}
|
|
491
|
+
//# sourceMappingURL=mesh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mesh.js","sourceRoot":"","sources":["../../src/net/mesh.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The NO-DEALER offline phase over the mutual-TLS mesh (research prototype).
|
|
3
|
+
*
|
|
4
|
+
* Each party is its own process holding only its own shares. Nobody is trusted to know the MAC keys, the
|
|
5
|
+
* triples or the inputs: every party samples its own key shares and its own triple shares, and the products
|
|
6
|
+
* needed for the triples and the MACs are computed by Gilboa OT multiplication between every ordered pair of
|
|
7
|
+
* parties (`mascot.ts` is the in-process model of exactly this computation):
|
|
8
|
+
*
|
|
9
|
+
* ob-S / ob-R / ob-C all-to-all the kappa = 128 base OTs of every ordered pair (malicious-secure, session-bound
|
|
10
|
+
* Chou-Orlandi: Schnorr proof of knowledge, point validation, transcript KDF)
|
|
11
|
+
* in-share all-to-all each owner splits every input bit into additive shares and sends one to each peer
|
|
12
|
+
* ox<layer>.<chunk>.u all-to-all OT-extension receiver messages (u matrix + KOS pair) -> KOS correlation check
|
|
13
|
+
* ox<layer>.<chunk>.y all-to-all OT-extension sender ciphertexts
|
|
14
|
+
*
|
|
15
|
+
* Two multiplication layers (plus the tag layer 3): layer 1 = the triple products c = a*b and c-hat = a-hat*b, and the MACs of every
|
|
16
|
+
* value that is known before them (a, b, a-hat, the inputs, the input-check mask); layer 2 = the MACs of the
|
|
17
|
+
* products. The triple SACRIFICE and the input-consistency opening run in the online phase (`protocol.ts`),
|
|
18
|
+
* on top of the same batched MAC-check, so a party that feeds wrong OT inputs yields a wrong triple that the
|
|
19
|
+
* sacrifice catches, and an input whose MAC does not match its value fails the check.
|
|
20
|
+
*
|
|
21
|
+
* Statistical/computational parameters: 2 independent MAC keys (>= 2^-120), 2 sacrifice partners per triple
|
|
22
|
+
* (>= 2^-122), KOS check with SSEC = 128 extra rows (best known attack about 2^-128, argued; see ot.ts), Ed25519 base OTs.
|
|
23
|
+
*
|
|
24
|
+
* PAIRWISE TAGS (identifiable abort): after the MACs are known, a third OT layer gives every share a pairwise tag
|
|
25
|
+
* T_ij = K_ij + Δ_j·x_i for every peer j (one OT product of my x with j's secret Δ_j per item), so the online
|
|
26
|
+
* phase can name a party that lies about a share, a MAC share or a residual (`pa.ts`).
|
|
27
|
+
*
|
|
28
|
+
* SELECTIVE FAILURE (RT-04): receivers do not choose with the bits of their share. Each share they multiply with is the gadget
|
|
29
|
+
* sum `<g, b>` of 61 + 3s = 253 uniform choice bits (s = 64, `enc.ts`), so whether a run aborts is statistically independent of
|
|
30
|
+
* the share (about 2^-63); the gadget is a commit-reveal value contributed by all parties. The tag layer splits its derived operands as `e + d` with an encoded `e`.
|
|
31
|
+
*
|
|
32
|
+
* What is NOT here: any security proof, and attribution of a wrong OT operand in the offline triple products
|
|
33
|
+
* (the sacrifice detects the bad triple, but the tags are computed on the already-wrong value): named only for n = 2.
|
|
34
|
+
*/
|
|
35
|
+
import type { DecisionVector } from '../party';
|
|
36
|
+
import type { Mesh } from './mesh';
|
|
37
|
+
import { type Prep } from './prep';
|
|
38
|
+
export interface OfflineNetArgs {
|
|
39
|
+
mesh: Mesh;
|
|
40
|
+
id: number;
|
|
41
|
+
n: number;
|
|
42
|
+
C: number;
|
|
43
|
+
keys: number;
|
|
44
|
+
partners: number;
|
|
45
|
+
sessionId: string;
|
|
46
|
+
input: DecisionVector;
|
|
47
|
+
Q: number;
|
|
48
|
+
/** TEST ONLY (gated by the caller): an offline misbehaviour of this party. */
|
|
49
|
+
behavior?: {
|
|
50
|
+
kind: string;
|
|
51
|
+
};
|
|
52
|
+
/** One un-echoed all-to-all round (errors while parsing a peer's message abort naming that peer). */
|
|
53
|
+
exchange: <T>(rd: string, mine: (peer: number) => unknown, parse: (p: number, raw: unknown) => T) => Promise<Map<number, T>>;
|
|
54
|
+
crashIf: (rd: string) => void;
|
|
55
|
+
bad: (p: number, what: string) => never;
|
|
56
|
+
arr: (p: number, raw: unknown, len: number) => bigint[];
|
|
57
|
+
}
|
|
58
|
+
export declare function runOfflineNet(a: OfflineNetArgs): Promise<Prep>;
|