@atlasauth/pca-mpc 0.0.0-stage → 0.1.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 +30 -2
- package/dist/beaver.d.ts +49 -0
- package/dist/beaver.js +72 -0
- package/dist/beaver.js.map +1 -0
- package/dist/compose.d.ts +21 -0
- package/dist/compose.js +33 -0
- package/dist/compose.js.map +1 -0
- package/dist/csprng.d.ts +46 -0
- package/dist/csprng.js +86 -0
- package/dist/csprng.js.map +1 -0
- package/dist/ec.d.ts +110 -0
- package/dist/ec.js +306 -0
- package/dist/ec.js.map +1 -0
- package/dist/field.d.ts +34 -0
- package/dist/field.js +65 -0
- package/dist/field.js.map +1 -0
- package/dist/gf128.d.ts +23 -0
- package/dist/gf128.js +59 -0
- package/dist/gf128.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/kem-ot.d.ts +137 -0
- package/dist/kem-ot.js +224 -0
- package/dist/kem-ot.js.map +1 -0
- package/dist/mascot.d.ts +189 -0
- package/dist/mascot.js +322 -0
- package/dist/mascot.js.map +1 -0
- package/dist/ot.d.ts +212 -0
- package/dist/ot.js +536 -0
- package/dist/ot.js.map +1 -0
- package/dist/party.d.ts +38 -0
- package/dist/party.js +40 -0
- package/dist/party.js.map +1 -0
- package/dist/runner.d.ts +56 -0
- package/dist/runner.js +97 -0
- package/dist/runner.js.map +1 -0
- package/dist/sharing.d.ts +40 -0
- package/dist/sharing.js +97 -0
- package/dist/sharing.js.map +1 -0
- package/dist/spdz-runner.d.ts +50 -0
- package/dist/spdz-runner.js +107 -0
- package/dist/spdz-runner.js.map +1 -0
- package/dist/spdz.d.ts +136 -0
- package/dist/spdz.js +243 -0
- package/dist/spdz.js.map +1 -0
- package/dist/thermometer.d.ts +22 -0
- package/dist/thermometer.js +41 -0
- package/dist/thermometer.js.map +1 -0
- package/package.json +31 -3
package/dist/mascot.js
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The NO-DEALER offline phase (MASCOT-style) — the last trust assumption removed.
|
|
4
|
+
*
|
|
5
|
+
* The SPDZ online layer (`spdz.ts`/`spdz-runner.ts`) is maliciously secure with abort, but until now
|
|
6
|
+
* its *preprocessing* — the global MAC key α, the authenticated Beaver triples, and the authenticated
|
|
7
|
+
* input sharings — came from a TRUSTED DEALER who knew α and generated everything. This module removes
|
|
8
|
+
* that dealer. All preprocessing is derived from real oblivious transfer (`ot.ts`), so:
|
|
9
|
+
*
|
|
10
|
+
* • **The MAC key α is distributed, never reconstructed.** Each party i samples its own share α_i
|
|
11
|
+
* locally; `α = Σ α_i` is a value no party ever holds and the protocol never forms. (The in-process
|
|
12
|
+
* simulator can sum the shares for test assertions — see `MacContext.alpha` — but no per-party view
|
|
13
|
+
* and no protocol step contains α.)
|
|
14
|
+
*
|
|
15
|
+
* • **Beaver triples are generated by the parties from OT, no dealer.** Each party samples its own
|
|
16
|
+
* shares a_i, b_i of two random values; the product share `c = a·b` is obtained by OT-multiplying
|
|
17
|
+
* the share vectors (Gilboa), and the SPDZ MACs on a, b, c are obtained by OT-multiplying α's shares
|
|
18
|
+
* against each value's shares. No party learns a, b or c; no party learns α.
|
|
19
|
+
*
|
|
20
|
+
* ## The one OT-based primitive: `otShareMultiply`
|
|
21
|
+
*
|
|
22
|
+
* Given additive sharings `⟨x⟩ = (x_0,…,x_{n−1})` and `⟨y⟩`, the parties want an additive sharing
|
|
23
|
+
* `⟨z⟩` with `Σ z = (Σ x)(Σ y)`, learning nothing else. Expand:
|
|
24
|
+
*
|
|
25
|
+
* (Σ_i x_i)(Σ_j y_j) = Σ_i x_i·y_i + Σ_{i≠j} x_i·y_j.
|
|
26
|
+
*
|
|
27
|
+
* The diagonal `x_i·y_i` each party computes locally. Each cross term `x_i·y_j` (i≠j) is turned into an
|
|
28
|
+
* additive sharing between party i and party j by **Gilboa's OT multiplication**: party i (holding x_i)
|
|
29
|
+
* is the OT RECEIVER using the bits of x_i as choices; party j (holding y_j) is the OT SENDER. For bit
|
|
30
|
+
* k of x_i, the sender offers `(ρ_k, ρ_k + 2^k·y_j)` for a fresh random ρ_k; the receiver's choice bit
|
|
31
|
+
* `(x_i)_k` selects `ρ_k + (x_i)_k·2^k·y_j`. Summed over k the receiver gets `x_i·y_j + Σρ_k` and the
|
|
32
|
+
* sender keeps `−Σρ_k`, an additive sharing of `x_i·y_j`. Because the OT hides both the choice and the
|
|
33
|
+
* unchosen message, neither party learns the other's share.
|
|
34
|
+
*
|
|
35
|
+
* ## Malicious security (docs §7.1)
|
|
36
|
+
*
|
|
37
|
+
* The OT is now **malicious-secure**: Chou–Orlandi base OT + IKNP extension **with the KOS correlation
|
|
38
|
+
* check** (`ot.ts`), so a cheating OT-extension receiver is caught and the extension aborts. On top of
|
|
39
|
+
* that, triple generation runs the **MASCOT sacrifice**: every delivered triple is generated as a PAIR
|
|
40
|
+
* `(a,b,c)` and `(â,b,ĉ)` sharing `b`, and one is *sacrificed* to check the other under the MACs — a
|
|
41
|
+
* party that fed wrong OT inputs (producing `c ≠ a·b`, even one that is internally MAC-consistent) is
|
|
42
|
+
* caught when the sacrifice residual `τ = e·c − ĉ − (e·a−â)·b` opens to a non-zero value, or when the
|
|
43
|
+
* commit-then-open MAC-check on the sacrifice openings fails. There is also an **input-consistency
|
|
44
|
+
* check** (`checkInputConsistency`): a random masked combination of authenticated inputs is opened and
|
|
45
|
+
* MAC-checked, catching any input whose MAC does not match its value. Both the sacrifice and the input
|
|
46
|
+
* check ABORT (throw `MacCheckAbort`) rather than emit a bad triple / bad input.
|
|
47
|
+
*
|
|
48
|
+
* So the whole stack is now **malicious-with-abort, dishonest-majority** end to end: malicious-secure
|
|
49
|
+
* no-dealer OFFLINE (KOS OT + MASCOT sacrifice + input check, `α` never reconstructed) feeding the
|
|
50
|
+
* malicious-with-abort SPDZ ONLINE phase (the MAC-check still catches any online deviation). The base
|
|
51
|
+
* OTs are themselves malicious-secure (committed Chou–Orlandi: Schnorr PoK + point validation, `ot.ts`
|
|
52
|
+
* / `ec.ts`), and all randomness here is the CSPRNG by DEFAULT — construct `NoDealerOffline` WITHOUT a
|
|
53
|
+
* seed for production (`SecureFieldRng` + `secureOtRandom`); passing a seed selects the deterministic
|
|
54
|
+
* SplitMix64 stream for reproducible tests only. Residual boundary (docs §7.1): just two honestly
|
|
55
|
+
* unavoidable items — constant-time field arithmetic (a native/WASM workstream) and a real async
|
|
56
|
+
* network/transport (including the interactive secure coin-flip for the public MAC-check challenge).
|
|
57
|
+
*/
|
|
58
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
59
|
+
exports.NoDealerOffline = void 0;
|
|
60
|
+
exports.makeNoDealerOffline = makeNoDealerOffline;
|
|
61
|
+
const field_1 = require("./field");
|
|
62
|
+
const csprng_1 = require("./csprng");
|
|
63
|
+
const sharing_1 = require("./sharing");
|
|
64
|
+
const spdz_1 = require("./spdz");
|
|
65
|
+
const ot_1 = require("./ot");
|
|
66
|
+
/** Number of bits needed to represent any element of F_p (p = 2^61 − 1 ⇒ values use bits 0..60). */
|
|
67
|
+
const FIELD_BITS = 61;
|
|
68
|
+
/**
|
|
69
|
+
* The no-dealer offline phase for a fixed party count `n`. Holds the distributed MAC key (α_i only),
|
|
70
|
+
* and a reusable set of per-ordered-pair OT-extension channels so the κ base OTs are amortized across
|
|
71
|
+
* every triple and input it produces. Deterministic given its seed (production: a CSPRNG per party).
|
|
72
|
+
*
|
|
73
|
+
* MALICIOUS-secure: the OT extension carries the KOS correlation check (`ot.ts`), and every delivered
|
|
74
|
+
* triple survives the MASCOT sacrifice. `checkInputConsistency` provides the input check.
|
|
75
|
+
*/
|
|
76
|
+
class NoDealerOffline {
|
|
77
|
+
n;
|
|
78
|
+
/** α_i: party i's locally-sampled share of the MAC key. Σ α_i = α (never formed by any party). */
|
|
79
|
+
alphaShares;
|
|
80
|
+
rng;
|
|
81
|
+
seed;
|
|
82
|
+
/** Whether randomness is a deterministic (test) seed; when false, all randomness is the CSPRNG. */
|
|
83
|
+
deterministic;
|
|
84
|
+
/** OT channels keyed "i->j": receiver = party i, sender = party j. Base OTs run on first use. */
|
|
85
|
+
channels = new Map();
|
|
86
|
+
/** Whether to run the MASCOT sacrifice per delivered triple (malicious-secure when true). */
|
|
87
|
+
sacrificeOn;
|
|
88
|
+
/** Test-only offline deviation (a malicious party corrupting a product share). */
|
|
89
|
+
deviation;
|
|
90
|
+
/** Count of triple-product OT multiplications performed (for targeting `deviation.productMul`). */
|
|
91
|
+
productMulCount = 0;
|
|
92
|
+
constructor(n, seed, opts = {}) {
|
|
93
|
+
if (!Number.isInteger(n) || n < 1)
|
|
94
|
+
throw new Error('NoDealerOffline: n must be a positive integer');
|
|
95
|
+
this.n = n;
|
|
96
|
+
// CSPRNG by DEFAULT (production); a deterministic SplitMix64 stream ONLY when a test seed is given
|
|
97
|
+
// (docs §7.1 item c). `this.seed` is kept for per-pair OT-stream derivation in the deterministic case.
|
|
98
|
+
this.deterministic = seed !== undefined;
|
|
99
|
+
this.seed = seed ?? 0xabcdef12345n;
|
|
100
|
+
this.rng = this.deterministic ? new field_1.FieldRng(this.seed) : new csprng_1.SecureFieldRng();
|
|
101
|
+
this.sacrificeOn = opts.sacrifice ?? true;
|
|
102
|
+
this.deviation = opts.deviation;
|
|
103
|
+
// DISTRIBUTED MAC-KEY GENERATION: each party samples its own α_i locally. α is never reconstructed.
|
|
104
|
+
this.alphaShares = Array.from({ length: n }, () => this.rng.next());
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The SPDZ MAC context the online runner consumes. It carries ONLY `alphaShares` for the protocol;
|
|
108
|
+
* `alpha` is the sum the in-process simulator computes for TEST ASSERTIONS and is never used by any
|
|
109
|
+
* protocol step or held by any party.
|
|
110
|
+
*/
|
|
111
|
+
get macContext() {
|
|
112
|
+
let alpha = 0n;
|
|
113
|
+
for (const ai of this.alphaShares)
|
|
114
|
+
alpha = (0, field_1.fadd)(alpha, ai);
|
|
115
|
+
return { n: this.n, alphaShares: this.alphaShares.slice(), alpha };
|
|
116
|
+
}
|
|
117
|
+
channel(i, j) {
|
|
118
|
+
const key = `${i}->${j}`;
|
|
119
|
+
let ch = this.channels.get(key);
|
|
120
|
+
if (!ch) {
|
|
121
|
+
// CSPRNG by default; a distinct DETERMINISTIC OT stream per ordered pair only under a test seed.
|
|
122
|
+
const otRng = this.deterministic
|
|
123
|
+
? (0, ot_1.otRandom)((0, ot_1.splitMix64)(this.seed ^ (BigInt(i + 1) * 0x100000001b3n) ^ (BigInt(j + 1) * 0x1000000000n)))
|
|
124
|
+
: (0, csprng_1.secureOtRandom)();
|
|
125
|
+
ch = new ot_1.OtChannel(otRng);
|
|
126
|
+
this.channels.set(key, ch);
|
|
127
|
+
}
|
|
128
|
+
return ch;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Gilboa OT multiplication of two scalars held by different parties. Party `i` holds `xi` (OT
|
|
132
|
+
* receiver, choice bits = bits of xi); party `j` holds `yj` (OT sender). Returns `[shareI, shareJ]`
|
|
133
|
+
* with `shareI + shareJ = xi·yj (mod p)`, neither party learning the other's input or share.
|
|
134
|
+
*/
|
|
135
|
+
gilboa(i, j, xi, yj) {
|
|
136
|
+
const x = (0, field_1.mod)(xi);
|
|
137
|
+
const y = (0, field_1.mod)(yj);
|
|
138
|
+
// Sender draws fresh masks ρ_k and offers (ρ_k, ρ_k + 2^k·y) for each bit k.
|
|
139
|
+
const choiceBits = new Array(FIELD_BITS);
|
|
140
|
+
const msg0 = new Array(FIELD_BITS);
|
|
141
|
+
const msg1 = new Array(FIELD_BITS);
|
|
142
|
+
let senderSum = 0n; // Σ ρ_k
|
|
143
|
+
let pow = 1n; // 2^k mod p (k ≤ 60 ⇒ no wrap)
|
|
144
|
+
for (let k = 0; k < FIELD_BITS; k++) {
|
|
145
|
+
const rho = this.rng.next();
|
|
146
|
+
senderSum = (0, field_1.fadd)(senderSum, rho);
|
|
147
|
+
msg0[k] = rho;
|
|
148
|
+
msg1[k] = (0, field_1.fadd)(rho, (0, field_1.fmul)(pow, y));
|
|
149
|
+
choiceBits[k] = Number((x >> BigInt(k)) & 1n);
|
|
150
|
+
pow = (pow * 2n) % field_1.PRIME;
|
|
151
|
+
}
|
|
152
|
+
const { received } = this.channel(i, j).extend(choiceBits, msg0, msg1);
|
|
153
|
+
let receiverSum = 0n; // Σ (received_k mod p)
|
|
154
|
+
for (let k = 0; k < FIELD_BITS; k++)
|
|
155
|
+
receiverSum = (0, field_1.fadd)(receiverSum, (0, field_1.mod)(received[k]));
|
|
156
|
+
// shareI + shareJ = Σ received − Σ ρ = (xi·yj + Σρ) − Σρ = xi·yj.
|
|
157
|
+
return [receiverSum, (0, field_1.fneg)(senderSum)];
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* OT-based share multiplication: given additive sharings `x`, `y` (length n), returns an additive
|
|
161
|
+
* sharing `z` with `Σ z = (Σ x)(Σ y) mod p`. Diagonal terms are local; each cross term is a Gilboa OT
|
|
162
|
+
* multiplication. No party learns Σx, Σy, or Σz.
|
|
163
|
+
*/
|
|
164
|
+
otShareMultiply(x, y) {
|
|
165
|
+
if (x.length !== this.n || y.length !== this.n)
|
|
166
|
+
throw new Error('otShareMultiply: wrong length');
|
|
167
|
+
const z = x.map((xi, i) => (0, field_1.fmul)(xi, y[i])); // diagonal x_i·y_i (local)
|
|
168
|
+
for (let i = 0; i < this.n; i++) {
|
|
169
|
+
for (let j = 0; j < this.n; j++) {
|
|
170
|
+
if (i === j)
|
|
171
|
+
continue;
|
|
172
|
+
const [si, sj] = this.gilboa(i, j, x[i], y[j]); // sharing of x_i·y_j
|
|
173
|
+
z[i] = (0, field_1.fadd)(z[i], si);
|
|
174
|
+
z[j] = (0, field_1.fadd)(z[j], sj);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return z;
|
|
178
|
+
}
|
|
179
|
+
/** Authenticate a value sharing: produce MAC shares γ with Σ γ = α·(Σ value), via OT (no dealer). */
|
|
180
|
+
authenticate(valueShares) {
|
|
181
|
+
return this.otShareMultiply(this.alphaShares, valueShares);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* The product sharing `c` (Σc = a·b) for a triple, via OT. Counts as a triple PRODUCT so a test
|
|
185
|
+
* `deviation` can corrupt one — modelling a malicious party that feeds a wrong OT input and gets a
|
|
186
|
+
* wrong-but-self-MAC-consistent product share (only the sacrifice catches this).
|
|
187
|
+
*/
|
|
188
|
+
tripleProduct(x, y) {
|
|
189
|
+
const z = this.otShareMultiply(x, y);
|
|
190
|
+
const idx = this.productMulCount++;
|
|
191
|
+
const dev = this.deviation;
|
|
192
|
+
if (dev && dev.productMul === idx)
|
|
193
|
+
z[0] = (0, field_1.fadd)(z[0], dev.delta);
|
|
194
|
+
return z;
|
|
195
|
+
}
|
|
196
|
+
/** A RAW authenticated triple (a, b, c=a·b) from OT, before the sacrifice. No dealer. */
|
|
197
|
+
rawTriple() {
|
|
198
|
+
const aShares = Array.from({ length: this.n }, () => this.rng.next());
|
|
199
|
+
const bShares = Array.from({ length: this.n }, () => this.rng.next());
|
|
200
|
+
const cShares = this.tripleProduct(aShares, bShares);
|
|
201
|
+
return {
|
|
202
|
+
a: { value: aShares, mac: this.authenticate(aShares) },
|
|
203
|
+
b: { value: bShares, mac: this.authenticate(bShares) },
|
|
204
|
+
c: { value: cShares, mac: this.authenticate(cShares) },
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/** A RAW authenticated triple (â, b, ĉ=â·b) SHARING the given authenticated `b` — the sacrifice pair. */
|
|
208
|
+
rawTripleWithB(b) {
|
|
209
|
+
const aShares = Array.from({ length: this.n }, () => this.rng.next());
|
|
210
|
+
const cShares = this.tripleProduct(aShares, b.value);
|
|
211
|
+
return {
|
|
212
|
+
a: { value: aShares, mac: this.authenticate(aShares) },
|
|
213
|
+
b,
|
|
214
|
+
c: { value: cShares, mac: this.authenticate(cShares) },
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* The MASCOT **sacrifice** check. Given two triples sharing `b`, `(a,b,c)` (the one to KEEP) and
|
|
219
|
+
* `(â,b,ĉ)` (the one to SACRIFICE), draw a public random challenge `e`, open `ρ = e·a − â`, form the
|
|
220
|
+
* authenticated residual `⟦τ⟧ = e·⟦c⟧ − ⟦ĉ⟧ − ρ·⟦b⟧`, open `τ`, run the commit-then-open MAC-check on
|
|
221
|
+
* both openings, and require `τ = 0`. If both triples are correct, `τ = e·(c−ab) − (ĉ−âb) = 0`; if the
|
|
222
|
+
* kept triple has `c = ab + δ`, then `τ = e·δ`, which is non-zero (e ≠ 0, δ ≠ 0) — ABORT. Lying in the
|
|
223
|
+
* `τ` opening to force a zero value is caught by the MAC-check (the forged MAC won't reconcile). The
|
|
224
|
+
* sacrificed triple is consumed by the check and discarded; the kept triple is certified `c = a·b`.
|
|
225
|
+
*/
|
|
226
|
+
sacrifice(keep, sac) {
|
|
227
|
+
const ctx = this.macContext;
|
|
228
|
+
const engine = new spdz_1.SpdzEngine(ctx, []);
|
|
229
|
+
let e = this.rng.next();
|
|
230
|
+
if (e === 0n)
|
|
231
|
+
e = 1n; // public random challenge, non-zero
|
|
232
|
+
const rho = engine.open((0, spdz_1.subAuth)((0, spdz_1.scaleAuth)(keep.a, e), sac.a), 'sacrifice:rho');
|
|
233
|
+
let tau = (0, spdz_1.subAuth)((0, spdz_1.scaleAuth)(keep.c, e), sac.c);
|
|
234
|
+
tau = (0, spdz_1.subAuth)(tau, (0, spdz_1.scaleAuth)(keep.b, rho));
|
|
235
|
+
const tauValue = engine.open(tau, 'sacrifice:tau');
|
|
236
|
+
engine.macCheck(this.rng); // commit-then-open MAC-check on ρ and τ; throws MacCheckAbort on a forged MAC
|
|
237
|
+
if (tauValue !== 0n) {
|
|
238
|
+
throw new spdz_1.MacCheckAbort(`MASCOT sacrifice FAILED: residual τ=${tauValue} != 0 — a malformed Beaver triple (c != a·b) was detected in the offline phase; aborting with no triple emitted`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Generate ONE authenticated Beaver triple with NO dealer, MALICIOUS-secure. Each party samples its
|
|
243
|
+
* own a_i, b_i; the product sharing c (Σc = a·b) comes from OT; every component is MAC'd via OT
|
|
244
|
+
* against the α shares. When the sacrifice is on (default), a SECOND triple sharing `b` is generated
|
|
245
|
+
* and sacrificed to certify `c = a·b` under the MACs, so a malformed triple ABORTS rather than being
|
|
246
|
+
* emitted. No party learns a, b, c, or α.
|
|
247
|
+
*/
|
|
248
|
+
genAuthTriple() {
|
|
249
|
+
if (!this.sacrificeOn)
|
|
250
|
+
return this.rawTriple();
|
|
251
|
+
const keep = this.rawTriple();
|
|
252
|
+
const sac = this.rawTripleWithB(keep.b);
|
|
253
|
+
this.sacrifice(keep, sac);
|
|
254
|
+
return keep;
|
|
255
|
+
}
|
|
256
|
+
/** Generate `count` authenticated triples (channels/base-OTs amortized across all of them). */
|
|
257
|
+
genAuthTriples(count) {
|
|
258
|
+
const out = [];
|
|
259
|
+
for (let k = 0; k < count; k++)
|
|
260
|
+
out.push(this.genAuthTriple());
|
|
261
|
+
return out;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Authenticated input sharing of `value`, owned by party `owner`, with NO dealer. The owner splits
|
|
265
|
+
* its own value into additive shares (local); the MAC `α·value` is computed via OT against the α
|
|
266
|
+
* shares. A malicious owner can of course choose any value (inputs are unconstrained in SPDZ), but it
|
|
267
|
+
* cannot make the sharing inconsistent with its MAC — the online MAC-check binds it.
|
|
268
|
+
*/
|
|
269
|
+
authInput(value, owner) {
|
|
270
|
+
if (owner < 0 || owner >= this.n)
|
|
271
|
+
throw new Error('authInput: owner out of range');
|
|
272
|
+
const valueShares = (0, sharing_1.share)((0, field_1.mod)(value), this.n, this.rng);
|
|
273
|
+
return { value: valueShares, mac: this.authenticate(valueShares) };
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* The MASCOT **input-consistency check**: verify that a batch of authenticated inputs each satisfy
|
|
277
|
+
* `Σγ = α·(Σvalue)` — i.e. their MACs match their values — WITHOUT revealing any value, and ABORT if
|
|
278
|
+
* not. A malicious party that produced an input whose MAC does not match its value (e.g. by feeding a
|
|
279
|
+
* bad OT input to the authentication) is caught here rather than only downstream.
|
|
280
|
+
*
|
|
281
|
+
* Method: draw public random coefficients `e_k`, generate ONE fresh OT-authenticated random mask
|
|
282
|
+
* `⟦r⟧`, form `⟦w⟧ = Σ_k e_k·⟦x_k⟧ + ⟦r⟧`, partial-open `w` (masked by the uniform `r`, so no input
|
|
283
|
+
* leaks), and run the commit-then-open MAC-check on that opening. If some input's MAC is off by `δ`,
|
|
284
|
+
* the opened `w` carries MAC residual `Σ e_k·δ_k ≠ 0` w.h.p. over the random `e_k`, and the MAC-check
|
|
285
|
+
* aborts. No-op for an empty batch.
|
|
286
|
+
*/
|
|
287
|
+
checkInputConsistency(inputs) {
|
|
288
|
+
if (inputs.length === 0)
|
|
289
|
+
return;
|
|
290
|
+
for (const inp of inputs) {
|
|
291
|
+
if (inp.value.length !== this.n || inp.mac.length !== this.n) {
|
|
292
|
+
throw new Error('checkInputConsistency: input party count mismatch');
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
const ctx = this.macContext;
|
|
296
|
+
const engine = new spdz_1.SpdzEngine(ctx, []);
|
|
297
|
+
// Fresh OT-authenticated random mask ⟦r⟧ (hides w so no input value is revealed).
|
|
298
|
+
const rShares = Array.from({ length: this.n }, () => this.rng.next());
|
|
299
|
+
let w = { value: rShares, mac: this.authenticate(rShares) };
|
|
300
|
+
for (const inp of inputs) {
|
|
301
|
+
let e = this.rng.next(); // public random coefficient
|
|
302
|
+
if (e === 0n)
|
|
303
|
+
e = 1n; // weight every input (0 would skip one); bias is negligible (prob 1/p)
|
|
304
|
+
w = addAuthLocal(w, (0, spdz_1.scaleAuth)(inp, e));
|
|
305
|
+
}
|
|
306
|
+
engine.open(w, 'input-check:w');
|
|
307
|
+
engine.macCheck(this.rng); // throws MacCheckAbort if any input's MAC is inconsistent with its value
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
exports.NoDealerOffline = NoDealerOffline;
|
|
311
|
+
/** Local authenticated addition (kept here to avoid widening mascot's spdz import surface). */
|
|
312
|
+
function addAuthLocal(x, y) {
|
|
313
|
+
return {
|
|
314
|
+
value: x.value.map((xi, i) => (0, field_1.fadd)(xi, y.value[i])),
|
|
315
|
+
mac: x.mac.map((mi, i) => (0, field_1.fadd)(mi, y.mac[i])),
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
/** Convenience: a fresh no-dealer offline phase for `n` parties (malicious-secure by default). */
|
|
319
|
+
function makeNoDealerOffline(n, seed, opts) {
|
|
320
|
+
return new NoDealerOffline(n, seed, opts);
|
|
321
|
+
}
|
|
322
|
+
//# sourceMappingURL=mascot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mascot.js","sourceRoot":"","sources":["../src/mascot.ts"],"names":[],"mappings":"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"}
|
package/dist/ot.d.ts
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Oblivious transfer — the real cryptographic root of the no-dealer offline phase.
|
|
3
|
+
*
|
|
4
|
+
* A 1-out-of-2 OT lets a RECEIVER with a choice bit `c` obtain exactly message `m_c` from a SENDER's
|
|
5
|
+
* pair `(m_0, m_1)`, such that the sender learns nothing about `c` and the receiver learns nothing
|
|
6
|
+
* about `m_{1−c}`. That single primitive is enough to multiply two parties' secret shares without a
|
|
7
|
+
* dealer (Gilboa's trick, see `mascot.ts`), which is enough to generate Beaver triples and SPDZ MACs
|
|
8
|
+
* with no trusted party. This module provides OT two ways:
|
|
9
|
+
*
|
|
10
|
+
* 1. **Base OT — MALICIOUSLY-secure Chou–Orlandi over the Ed25519 subgroup (`ec.ts`).** The core is
|
|
11
|
+
* "simplest OT": sender samples `y`, publishes `S = y·B`, holds `T = y·S`; receiver with choice `c`
|
|
12
|
+
* samples `x`, publishes `R = x·B + c·S`, derives pad `k = H(x·S)`; sender derives `k_b = H(y·R − b·T)`
|
|
13
|
+
* for `b∈{0,1}`; since `y·R = x·(y·B) + c·T`, `k_c = k` while `k_{1−c}` is `H` of a point the receiver
|
|
14
|
+
* can't compute (it would need the discrete log). **Receiver-choice privacy is information-theoretic
|
|
15
|
+
* in the transcript:** `R = x·B + c·S` with `x` uniform is a uniform subgroup element whatever `c` is
|
|
16
|
+
* — for every observed `R` there is one `x` consistent with `c=0` and one with `c=1` (`x' = x − y`),
|
|
17
|
+
* so the sender's view is identically distributed for both choices. Two additions upgrade this from
|
|
18
|
+
* semi-honest to **malicious-secure against both a cheating sender AND a cheating receiver** (docs
|
|
19
|
+
* §7.1 item a):
|
|
20
|
+
* • **the sender proves knowledge of `y` with a Schnorr NIZK on `S = y·B`** (`ec.ts`), so a sender
|
|
21
|
+
* cannot use an `S` it cannot open (e.g. one crafted to leak the receiver's choice) — the
|
|
22
|
+
* receiver verifies the proof and ABORTS before forming `R`;
|
|
23
|
+
* • **every received point is validated** (on-curve + prime-order-subgroup cofactor check +
|
|
24
|
+
* non-identity): the receiver validates `S`, the sender validates every `R_i`, so neither party
|
|
25
|
+
* can inject an off-curve / small-order / mixed-order point for a small-subgroup attack.
|
|
26
|
+
* The IKNP setup consumes this as a **random OT** (`malBaseRandomOT`): the two transferred seeds ARE
|
|
27
|
+
* the RO pads `(H(y·R), H(y·R − T))`, so there are **no sender-chosen ciphertexts** and hence no
|
|
28
|
+
* selective-failure surface — the only abort (bad `S`/proof/`R_i`) is independent of the receiver's
|
|
29
|
+
* selector, which is exactly what malicious security of the role-inverted base OTs requires. The
|
|
30
|
+
* chosen-message `baseOT` wrapper (random OT + one-time-pad + a commit-to-message check) is used by
|
|
31
|
+
* the direct OT tests; its commitment catches a sender that encrypts inconsistently with its commitment.
|
|
32
|
+
*
|
|
33
|
+
* 2. **OT extension — IKNP + the KOS consistency check (MALICIOUS-secure).** Base OT needs public-key
|
|
34
|
+
* ops per transfer; the offline phase needs hundreds of thousands of OTs. IKNP turns `κ = 128` base
|
|
35
|
+
* OTs (done once) into arbitrarily many OTs using only a hash/PRG. Roles invert for the base OTs:
|
|
36
|
+
* the extension SENDER plays base-receiver with a secret selector `s ∈ {0,1}^κ`; the extension
|
|
37
|
+
* RECEIVER plays base-sender with `κ` seed pairs. Thereafter each extension round of `m` OTs costs
|
|
38
|
+
* `κ` PRG expansions plus `~3·m` hashes. Correctness: the receiver recovers exactly `m_{c_j}` for
|
|
39
|
+
* every `j`; the sender's `s` (hidden by the base OTs) and the correlation-robust hash keep the
|
|
40
|
+
* unchosen messages hidden.
|
|
41
|
+
*
|
|
42
|
+
* Plain IKNP is only SEMI-HONEST: a cheating RECEIVER can send an extension matrix `u` that encodes
|
|
43
|
+
* *different* choice vectors in different columns, which breaks the row correlation `q_j = t_j ⊕
|
|
44
|
+
* (b_j·s)` and lets the receiver learn bits of the sender's selector `s` (and thus the unchosen
|
|
45
|
+
* messages). The **KOS correlation check** (Keller–Orsini–Scholl, "Actively Secure OT Extension
|
|
46
|
+
* with Optimal Overhead") closes exactly this: after `u` is on the wire, the parties draw public
|
|
47
|
+
* random weights `χ_j ∈ GF(2^κ)` (one per row, bound to `u` by a Fiat–Shamir hash here), the
|
|
48
|
+
* receiver reveals `x = Σ_j b_j·χ_j` and `t = Σ_j χ_j·t_j`, and the sender checks
|
|
49
|
+
* `Σ_j χ_j·q_j == t ⊕ x·s` in GF(2^κ). Honestly this always holds (`q_j = t_j ⊕ b_j·s`); a receiver
|
|
50
|
+
* who deviated in `u` satisfies it with probability ≤ `2^{-κ} = 2^{-128}`, so a deviation ABORTS.
|
|
51
|
+
* The check is run over `m + κ + SSEC` rows — the extra `κ + SSEC` random "sacrifice" OT rows mask
|
|
52
|
+
* the revealed combination (receiver privacy) and give statistical soundness. This makes the OT
|
|
53
|
+
* extension **malicious-secure**, not just semi-honest.
|
|
54
|
+
*
|
|
55
|
+
* In-process model: both parties run in one process and the functions take *both* parties' inputs and
|
|
56
|
+
* return the receiver's outputs plus an inspectable transcript (the receiver's wire message `R`, the
|
|
57
|
+
* sender's ciphertexts, the IKNP `u` matrix). That is exactly what the tests assert over: receiver
|
|
58
|
+
* correctness, sender-side choice-hiding from the transcript, and the KOS check aborting on a tampered
|
|
59
|
+
* `u`. See docs §7.1 for the remaining boundary (real async transport, constant-time, CSPRNG).
|
|
60
|
+
*/
|
|
61
|
+
import { type Point, type SchnorrProof } from './ec';
|
|
62
|
+
/** IKNP security parameter (number of base OTs / width of the selector s). */
|
|
63
|
+
export declare const KAPPA = 128;
|
|
64
|
+
/**
|
|
65
|
+
* KOS statistical-security parameter: the number of EXTRA random check-OT rows (beyond the `κ` that
|
|
66
|
+
* mask the revealed combination) appended to every extension round. Together `κ + SSEC` padding rows
|
|
67
|
+
* give the correlation check its receiver-privacy and statistical soundness margin.
|
|
68
|
+
*/
|
|
69
|
+
export declare const SSEC = 64;
|
|
70
|
+
/** Raised when the KOS correlation check fails: a cheating OT-extension receiver is detected → ABORT. */
|
|
71
|
+
export declare class MalOtAbort extends Error {
|
|
72
|
+
constructor(message: string);
|
|
73
|
+
}
|
|
74
|
+
/** A deterministic source of scalars/seeds; wraps the module FieldRng-style stream for OT needs. */
|
|
75
|
+
export interface OtRandom {
|
|
76
|
+
/** A uniform scalar in [1, L) (for EC blinding) — never 0. */
|
|
77
|
+
scalar(): bigint;
|
|
78
|
+
/** `n` random bytes (for seeds). */
|
|
79
|
+
bytes(n: number): Uint8Array;
|
|
80
|
+
}
|
|
81
|
+
/** A raw SplitMix64 64-bit stream (deterministic). Production uses a CSPRNG with a secret seed. */
|
|
82
|
+
export declare function splitMix64(seed: bigint): () => bigint;
|
|
83
|
+
/** Build an OtRandom from a SplitMix64-style 64-bit stream (deterministic; CSPRNG in production). */
|
|
84
|
+
export declare function otRandom(next64: () => bigint): OtRandom;
|
|
85
|
+
/** Raised when a base OT aborts: a cheating sender (bad proof / inconsistent ciphertext) is detected. */
|
|
86
|
+
export declare class BaseOtAbort extends Error {
|
|
87
|
+
constructor(message: string);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* TEST-ONLY injection points modelling a malicious SENDER or RECEIVER in the base OT. Each hook mutates
|
|
91
|
+
* or replaces a value exactly where it would cross the wire, so the honest party's validation runs
|
|
92
|
+
* against the adversarial value — which is what the malicious-security checks must catch.
|
|
93
|
+
*/
|
|
94
|
+
export interface BaseOtTamper {
|
|
95
|
+
/** Malicious SENDER: replace `S` on the wire (the receiver still validates it + the proof). */
|
|
96
|
+
tamperS?: (S: Point) => Point;
|
|
97
|
+
/** Malicious SENDER: forge the Schnorr proof on the wire. */
|
|
98
|
+
tamperProof?: (p: SchnorrProof) => SchnorrProof;
|
|
99
|
+
/** Malicious RECEIVER: mutate the `R_i` points on the wire (the sender still validates each). */
|
|
100
|
+
tamperR?: (R: Point[]) => void;
|
|
101
|
+
/** Malicious SENDER: corrupt the ciphertexts on the wire (inconsistent with the commitment). */
|
|
102
|
+
tamperCiphertext?: (ct: Array<[Uint8Array, Uint8Array]>) => void;
|
|
103
|
+
}
|
|
104
|
+
/** The base-OT transcript: the sender's `S` + proof-of-knowledge, the receiver's `R_i`, and the ciphertexts/commitments. */
|
|
105
|
+
export interface BaseOtTranscript {
|
|
106
|
+
/** Sender's public point S = y·B. */
|
|
107
|
+
S: Point;
|
|
108
|
+
/** Schnorr NIZK proving the sender knows `y` with `S = y·B` (malicious-sender hardening). */
|
|
109
|
+
proof: SchnorrProof;
|
|
110
|
+
/** Receiver's points R_i = x_i·B + c_i·S (uniform subgroup elements; independent of c_i). */
|
|
111
|
+
R: Point[];
|
|
112
|
+
/** Sender ciphertexts: for each i, [E_{i,0}, E_{i,1}] = [m_{i,0} ⊕ pad_{i,0}, m_{i,1} ⊕ pad_{i,1}]. */
|
|
113
|
+
ct: Array<[Uint8Array, Uint8Array]>;
|
|
114
|
+
/** Per-message RO commitments com_{i,b} = H(i ‖ b ‖ m_{i,b} ‖ pad_{i,b}); the receiver checks com_{i,c}. */
|
|
115
|
+
com: Array<[Uint8Array, Uint8Array]>;
|
|
116
|
+
}
|
|
117
|
+
export interface BaseOtResult {
|
|
118
|
+
/** Receiver's recovered messages m_{i, c_i}. */
|
|
119
|
+
received: Uint8Array[];
|
|
120
|
+
transcript: BaseOtTranscript;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* A pluggable chosen-message base OT: `count = choices.length` 1-of-2 OTs returning the receiver's
|
|
124
|
+
* recovered messages. The EC `baseOT` above satisfies it, and so does the post-quantum `kemBaseOT`
|
|
125
|
+
* (`kem-ot.ts`) — letting `OtChannel` run its κ setup OTs over either base without touching the
|
|
126
|
+
* IKNP/KOS layer. Only `received` is required (the EC-specific `transcript` is not part of the contract,
|
|
127
|
+
* since a non-EC base has a different transcript shape).
|
|
128
|
+
*/
|
|
129
|
+
export type BaseOtFn = (messages: Array<[Uint8Array, Uint8Array]>, choices: number[], rng: OtRandom) => {
|
|
130
|
+
received: Uint8Array[];
|
|
131
|
+
};
|
|
132
|
+
/** The output of the malicious-secure RANDOM base OT: validated points + the two RO pads per index. */
|
|
133
|
+
export interface MalRandomOtResult {
|
|
134
|
+
/** Sender's public point (as seen on the wire by the receiver). */
|
|
135
|
+
S: Point;
|
|
136
|
+
/** Sender's proof of knowledge of the discrete log of `S`. */
|
|
137
|
+
proof: SchnorrProof;
|
|
138
|
+
/** Receiver's points (as seen on the wire by the sender). */
|
|
139
|
+
R: Point[];
|
|
140
|
+
/** Sender's pad pairs: senderPads[i] = [H(y·R_i), H(y·R_i − T)]. */
|
|
141
|
+
senderPads: Array<[Uint8Array, Uint8Array]>;
|
|
142
|
+
/** Receiver's recovered pads: recvPads[i] = H(x_i·S) = senderPads[i][c_i] (honest run). */
|
|
143
|
+
recvPads: Uint8Array[];
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The MALICIOUS-secure RANDOM base OT: `count = choices.length` 1-of-2 random OTs. The sender publishes
|
|
147
|
+
* `S = y·B` with a Schnorr proof of knowledge of `y`; the receiver validates `S` + the proof and
|
|
148
|
+
* ABORTS on failure, then forms its `R_i`; the sender validates every `R_i` and derives the pad pairs.
|
|
149
|
+
* No messages are transferred — the pads ARE the random output. `tamper` injects malicious behaviour
|
|
150
|
+
* for tests. Both parties are simulated in-process.
|
|
151
|
+
*/
|
|
152
|
+
export declare function malBaseRandomOT(choices: number[], rng?: OtRandom, tamper?: BaseOtTamper): MalRandomOtResult;
|
|
153
|
+
/**
|
|
154
|
+
* Run `count` MALICIOUS-secure base OTs in one batch (chosen-message, over the random OT above).
|
|
155
|
+
* `messages[i] = [m0, m1]` (SEED_BYTES each), the sender's pair; `choices[i] ∈ {0,1}` the receiver's
|
|
156
|
+
* choice. The sender one-time-pads each message under the random-OT pads and commits to each message;
|
|
157
|
+
* the receiver recovers `m_{i,c_i}` and checks the commitment, aborting (`BaseOtAbort`) on any
|
|
158
|
+
* inconsistency. Returns the receiver's recovered messages and the full transcript.
|
|
159
|
+
*/
|
|
160
|
+
export declare function baseOT(messages: Array<[Uint8Array, Uint8Array]>, choices: number[], rng?: OtRandom, tamper?: BaseOtTamper): BaseOtResult;
|
|
161
|
+
/**
|
|
162
|
+
* An IKNP OT-extension channel between a fixed RECEIVER (choice bits) and SENDER (message pairs). The
|
|
163
|
+
* κ base OTs run lazily on the first `extend`; each later `extend(m)` is a cheap PRG+hash round. The
|
|
164
|
+
* channel is stateful (advances per-seed PRG counters) so many rounds compose into one amortized setup.
|
|
165
|
+
*/
|
|
166
|
+
export declare class OtChannel {
|
|
167
|
+
private readonly rng;
|
|
168
|
+
/** Optional post-quantum (or otherwise custom) base OT for the κ setup OTs; defaults to EC `baseOT`. */
|
|
169
|
+
private readonly baseOtFn?;
|
|
170
|
+
private ready;
|
|
171
|
+
private s;
|
|
172
|
+
private sBits;
|
|
173
|
+
private senderSeeds;
|
|
174
|
+
private senderBlk;
|
|
175
|
+
private recvSeed0;
|
|
176
|
+
private recvSeed1;
|
|
177
|
+
private recvBlk0;
|
|
178
|
+
private recvBlk1;
|
|
179
|
+
/** The base-OT transcript (available after setup) — exposed for inspection/tests. */
|
|
180
|
+
baseTranscript?: BaseOtTranscript;
|
|
181
|
+
/**
|
|
182
|
+
* TEST-ONLY injection modelling a MALICIOUS extension RECEIVER: if set, it is called with the honest
|
|
183
|
+
* `u` matrix (κ columns, each `mExt` bits) just before it goes "on the wire", and may mutate it (e.g.
|
|
184
|
+
* XOR a delta into one or more columns) to encode inconsistent choices. The KOS check is computed
|
|
185
|
+
* over the tampered `u` (what the sender sees) while the receiver's revealed `(x, t)` stay honest, so
|
|
186
|
+
* a non-trivial tamper is caught — the real malicious-receiver attack that KOS defeats.
|
|
187
|
+
*/
|
|
188
|
+
tamperU?: (u: bigint[], round: number) => void;
|
|
189
|
+
private round;
|
|
190
|
+
/**
|
|
191
|
+
* `rng` defaults to the CSPRNG (`secureOtRandom`, `node:crypto`) — production randomness. Pass a
|
|
192
|
+
* deterministic `otRandom(splitMix64(seed))` ONLY to make a test bit-reproducible (docs §7.1 item c).
|
|
193
|
+
*/
|
|
194
|
+
constructor(rng?: OtRandom, opts?: {
|
|
195
|
+
baseOtFn?: BaseOtFn;
|
|
196
|
+
});
|
|
197
|
+
private setup;
|
|
198
|
+
/** Selector s as a κ-bit bigint (sender-side secret; exposed only for tests). */
|
|
199
|
+
get selector(): bigint;
|
|
200
|
+
/**
|
|
201
|
+
* One MALICIOUS-secure extension round: `choiceBits[j] ∈ {0,1}` (receiver), `msg0[j]/msg1[j]`
|
|
202
|
+
* field-element messages (sender). Returns the receiver's chosen messages `msg_{choiceBits[j]}[j]`
|
|
203
|
+
* for the `m` real rows. The round transparently appends `κ + SSEC` random check-OT rows and runs the
|
|
204
|
+
* **KOS correlation check** over all `m + κ + SSEC` rows; a cheating receiver (tampered `u`) is caught
|
|
205
|
+
* there and the round throws `MalOtAbort`. `uMatrix` (the receiver→sender wire message, now
|
|
206
|
+
* `mExt`-bit) is returned for tests.
|
|
207
|
+
*/
|
|
208
|
+
extend(choiceBits: number[], msg0: bigint[], msg1: bigint[]): {
|
|
209
|
+
received: bigint[];
|
|
210
|
+
uMatrix: bigint[];
|
|
211
|
+
};
|
|
212
|
+
}
|