@atlasauth/pca-mpc 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +65 -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 +130 -0
- package/dist/ec.js +475 -0
- package/dist/ec.js.map +1 -0
- package/dist/endemic-ot.d.ts +209 -0
- package/dist/endemic-ot.js +405 -0
- package/dist/endemic-ot.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/hybrid-ot.d.ts +153 -0
- package/dist/hybrid-ot.js +241 -0
- package/dist/hybrid-ot.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/kem-ot.d.ts +292 -0
- package/dist/kem-ot.js +559 -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 +58 -3
package/dist/field.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arithmetic in the prime field F_p used for additive secret sharing.
|
|
3
|
+
*
|
|
4
|
+
* p = 2^61 - 1 (the Mersenne prime M61). It is wider than any value the composition ever shares
|
|
5
|
+
* (bits, thermometer bits, small sums), so no secret ever wraps; sharing randomness lives in the
|
|
6
|
+
* full field so that any single share is (information-theoretically) uniform and independent of the
|
|
7
|
+
* secret. All arithmetic is BigInt and exact — never floating point — so the protocol is
|
|
8
|
+
* bit-deterministic and verifier-reproducible.
|
|
9
|
+
*
|
|
10
|
+
* RANDOMNESS (docs §7.1 item "CSPRNG — done"): the `FieldRng` below is a deterministic SplitMix64, kept
|
|
11
|
+
* ONLY for bit-reproducible tests behind an explicit seed. It is NOT the default: the protocol draws
|
|
12
|
+
* all sharing/triple/MAC randomness from the CSPRNG `SecureFieldRng` / `secureOtRandom` in `csprng.ts`
|
|
13
|
+
* (`node:crypto.randomBytes`) unless a test explicitly asks for the seeded stream. `SecureFieldRng`
|
|
14
|
+
* extends this class and overrides `next()`, so it is a drop-in wherever a `FieldRng` is accepted.
|
|
15
|
+
*/
|
|
16
|
+
export declare const PRIME: bigint;
|
|
17
|
+
/** Canonical representative in [0, p). */
|
|
18
|
+
export declare function mod(x: bigint): bigint;
|
|
19
|
+
export declare const fadd: (a: bigint, b: bigint) => bigint;
|
|
20
|
+
export declare const fsub: (a: bigint, b: bigint) => bigint;
|
|
21
|
+
export declare const fmul: (a: bigint, b: bigint) => bigint;
|
|
22
|
+
export declare const fneg: (a: bigint) => bigint;
|
|
23
|
+
/**
|
|
24
|
+
* Deterministic SplitMix64, drawing UNBIASED field elements by rejection sampling (reject the top
|
|
25
|
+
* 2^64 mod p = 8 residues so the modulo is exactly uniform). Deterministic for reproducible tests;
|
|
26
|
+
* see the security note above for production.
|
|
27
|
+
*/
|
|
28
|
+
export declare class FieldRng {
|
|
29
|
+
private s;
|
|
30
|
+
constructor(seed?: bigint);
|
|
31
|
+
private nextU64;
|
|
32
|
+
/** Uniform element of F_p (unbiased). */
|
|
33
|
+
next(): bigint;
|
|
34
|
+
}
|
package/dist/field.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Arithmetic in the prime field F_p used for additive secret sharing.
|
|
4
|
+
*
|
|
5
|
+
* p = 2^61 - 1 (the Mersenne prime M61). It is wider than any value the composition ever shares
|
|
6
|
+
* (bits, thermometer bits, small sums), so no secret ever wraps; sharing randomness lives in the
|
|
7
|
+
* full field so that any single share is (information-theoretically) uniform and independent of the
|
|
8
|
+
* secret. All arithmetic is BigInt and exact — never floating point — so the protocol is
|
|
9
|
+
* bit-deterministic and verifier-reproducible.
|
|
10
|
+
*
|
|
11
|
+
* RANDOMNESS (docs §7.1 item "CSPRNG — done"): the `FieldRng` below is a deterministic SplitMix64, kept
|
|
12
|
+
* ONLY for bit-reproducible tests behind an explicit seed. It is NOT the default: the protocol draws
|
|
13
|
+
* all sharing/triple/MAC randomness from the CSPRNG `SecureFieldRng` / `secureOtRandom` in `csprng.ts`
|
|
14
|
+
* (`node:crypto.randomBytes`) unless a test explicitly asks for the seeded stream. `SecureFieldRng`
|
|
15
|
+
* extends this class and overrides `next()`, so it is a drop-in wherever a `FieldRng` is accepted.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.FieldRng = exports.fneg = exports.fmul = exports.fsub = exports.fadd = exports.PRIME = void 0;
|
|
19
|
+
exports.mod = mod;
|
|
20
|
+
exports.PRIME = 2n ** 61n - 1n;
|
|
21
|
+
const MASK64 = (1n << 64n) - 1n;
|
|
22
|
+
/** Canonical representative in [0, p). */
|
|
23
|
+
function mod(x) {
|
|
24
|
+
const r = x % exports.PRIME;
|
|
25
|
+
return r >= 0n ? r : r + exports.PRIME;
|
|
26
|
+
}
|
|
27
|
+
const fadd = (a, b) => mod(a + b);
|
|
28
|
+
exports.fadd = fadd;
|
|
29
|
+
const fsub = (a, b) => mod(a - b);
|
|
30
|
+
exports.fsub = fsub;
|
|
31
|
+
const fmul = (a, b) => mod(a * b);
|
|
32
|
+
exports.fmul = fmul;
|
|
33
|
+
const fneg = (a) => mod(-a);
|
|
34
|
+
exports.fneg = fneg;
|
|
35
|
+
/**
|
|
36
|
+
* Deterministic SplitMix64, drawing UNBIASED field elements by rejection sampling (reject the top
|
|
37
|
+
* 2^64 mod p = 8 residues so the modulo is exactly uniform). Deterministic for reproducible tests;
|
|
38
|
+
* see the security note above for production.
|
|
39
|
+
*/
|
|
40
|
+
class FieldRng {
|
|
41
|
+
s;
|
|
42
|
+
constructor(seed = 0x243f6a8885a308d3n) {
|
|
43
|
+
this.s = seed & MASK64;
|
|
44
|
+
}
|
|
45
|
+
nextU64() {
|
|
46
|
+
this.s = (this.s + 0x9e3779b97f4a7c15n) & MASK64;
|
|
47
|
+
let z = this.s;
|
|
48
|
+
z = ((z ^ (z >> 30n)) * 0xbf58476d1ce4e5b9n) & MASK64;
|
|
49
|
+
z = ((z ^ (z >> 27n)) * 0x94d049bb133111ebn) & MASK64;
|
|
50
|
+
z = (z ^ (z >> 31n)) & MASK64;
|
|
51
|
+
return z;
|
|
52
|
+
}
|
|
53
|
+
/** Uniform element of F_p (unbiased). */
|
|
54
|
+
next() {
|
|
55
|
+
// Largest multiple of p that fits in 64 bits; drop anything at or above it so `% PRIME` is uniform.
|
|
56
|
+
const limit = ((MASK64 + 1n) / exports.PRIME) * exports.PRIME;
|
|
57
|
+
for (;;) {
|
|
58
|
+
const u = this.nextU64();
|
|
59
|
+
if (u < limit)
|
|
60
|
+
return u % exports.PRIME;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.FieldRng = FieldRng;
|
|
65
|
+
//# sourceMappingURL=field.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field.js","sourceRoot":"","sources":["../src/field.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAOH,kBAGC;AARY,QAAA,KAAK,GAAG,EAAE,IAAI,GAAG,GAAG,EAAE,CAAC;AAEpC,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;AAEhC,0CAA0C;AAC1C,SAAgB,GAAG,CAAC,CAAS;IAC3B,MAAM,CAAC,GAAG,CAAC,GAAG,aAAK,CAAC;IACpB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,aAAK,CAAC;AACjC,CAAC;AAEM,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAApD,QAAA,IAAI,QAAgD;AAC1D,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAApD,QAAA,IAAI,QAAgD;AAC1D,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAApD,QAAA,IAAI,QAAgD;AAC1D,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAAtC,QAAA,IAAI,QAAkC;AAEnD;;;;GAIG;AACH,MAAa,QAAQ;IACX,CAAC,CAAS;IAElB,YAAY,OAAe,mBAAmB;QAC5C,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,MAAM,CAAC;IACzB,CAAC;IAEO,OAAO;QACb,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,mBAAmB,CAAC,GAAG,MAAM,CAAC;QACjD,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QACf,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,mBAAmB,CAAC,GAAG,MAAM,CAAC;QACtD,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,mBAAmB,CAAC,GAAG,MAAM,CAAC;QACtD,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;QAC9B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,yCAAyC;IACzC,IAAI;QACF,oGAAoG;QACpG,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,GAAG,aAAK,CAAC,GAAG,aAAK,CAAC;QAC9C,SAAS,CAAC;YACR,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YACzB,IAAI,CAAC,GAAG,KAAK;gBAAE,OAAO,CAAC,GAAG,aAAK,CAAC;QAClC,CAAC;IACH,CAAC;CACF;AAzBD,4BAyBC"}
|
package/dist/gf128.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GF(2^128) arithmetic — the field the KOS correlation check lives in (`ot.ts`).
|
|
3
|
+
*
|
|
4
|
+
* The malicious-secure OT-extension consistency check (KOS) folds every row of the extension matrix
|
|
5
|
+
* into a single random linear combination over GF(2^κ) with κ = 128, and verifies one field equation.
|
|
6
|
+
* A cheating receiver who deviates in the extension matrix passes that equation with probability at
|
|
7
|
+
* most `2^{-128}` (the field size), which is what upgrades IKNP from semi-honest to malicious-secure.
|
|
8
|
+
*
|
|
9
|
+
* We use the standard GF(2^128) with reduction polynomial `x^128 + x^7 + x^2 + x + 1` (the GCM /
|
|
10
|
+
* "0x87" polynomial). Elements are 128-bit `bigint`s, bit `i` = coefficient of `x^i`. Addition is XOR.
|
|
11
|
+
* Multiplication is schoolbook carryless multiply with reduction; `mulByXi` (multiply by `x^i`) is the
|
|
12
|
+
* repeated-shift form used by the column-domain check so the hot path pays no full 128×128 multiply
|
|
13
|
+
* per row. This is a textbook field (BigInt, not constant-time) — sound for the in-process prototype;
|
|
14
|
+
* see docs §7.1 for the constant-time boundary.
|
|
15
|
+
*/
|
|
16
|
+
/** Field addition in GF(2^128): XOR (masked to 128 bits). */
|
|
17
|
+
export declare function gf128Add(a: bigint, b: bigint): bigint;
|
|
18
|
+
/** Multiply by `x` (one step of the LFSR): shift left 1, reduce if it overflowed bit 127. */
|
|
19
|
+
export declare function gf128MulX(v: bigint): bigint;
|
|
20
|
+
/** Multiply by `x^i` (i ≥ 0): i LFSR steps. Used by the column-domain KOS fold. */
|
|
21
|
+
export declare function gf128MulByXi(v: bigint, i: number): bigint;
|
|
22
|
+
/** Full GF(2^128) multiplication (carryless multiply + reduction), right-to-left over the bits of `b`. */
|
|
23
|
+
export declare function gf128Mul(a: bigint, b: bigint): bigint;
|
package/dist/gf128.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* GF(2^128) arithmetic — the field the KOS correlation check lives in (`ot.ts`).
|
|
4
|
+
*
|
|
5
|
+
* The malicious-secure OT-extension consistency check (KOS) folds every row of the extension matrix
|
|
6
|
+
* into a single random linear combination over GF(2^κ) with κ = 128, and verifies one field equation.
|
|
7
|
+
* A cheating receiver who deviates in the extension matrix passes that equation with probability at
|
|
8
|
+
* most `2^{-128}` (the field size), which is what upgrades IKNP from semi-honest to malicious-secure.
|
|
9
|
+
*
|
|
10
|
+
* We use the standard GF(2^128) with reduction polynomial `x^128 + x^7 + x^2 + x + 1` (the GCM /
|
|
11
|
+
* "0x87" polynomial). Elements are 128-bit `bigint`s, bit `i` = coefficient of `x^i`. Addition is XOR.
|
|
12
|
+
* Multiplication is schoolbook carryless multiply with reduction; `mulByXi` (multiply by `x^i`) is the
|
|
13
|
+
* repeated-shift form used by the column-domain check so the hot path pays no full 128×128 multiply
|
|
14
|
+
* per row. This is a textbook field (BigInt, not constant-time) — sound for the in-process prototype;
|
|
15
|
+
* see docs §7.1 for the constant-time boundary.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.gf128Add = gf128Add;
|
|
19
|
+
exports.gf128MulX = gf128MulX;
|
|
20
|
+
exports.gf128MulByXi = gf128MulByXi;
|
|
21
|
+
exports.gf128Mul = gf128Mul;
|
|
22
|
+
/** 128-bit mask. */
|
|
23
|
+
const MASK128 = (1n << 128n) - 1n;
|
|
24
|
+
/**
|
|
25
|
+
* The reduction tail for `x^128 + x^7 + x^2 + x + 1`: when a shift pushes a 1 past bit 127, we have
|
|
26
|
+
* `x^128 ≡ x^7 + x^2 + x + 1 = 0x87`, so we XOR `0x87` back in.
|
|
27
|
+
*/
|
|
28
|
+
const GF128_RED = (1n << 7n) | (1n << 2n) | (1n << 1n) | 1n; // 0x87
|
|
29
|
+
/** Field addition in GF(2^128): XOR (masked to 128 bits). */
|
|
30
|
+
function gf128Add(a, b) {
|
|
31
|
+
return (a ^ b) & MASK128;
|
|
32
|
+
}
|
|
33
|
+
/** Multiply by `x` (one step of the LFSR): shift left 1, reduce if it overflowed bit 127. */
|
|
34
|
+
function gf128MulX(v) {
|
|
35
|
+
const carry = (v >> 127n) & 1n;
|
|
36
|
+
let r = (v << 1n) & MASK128;
|
|
37
|
+
if (carry)
|
|
38
|
+
r ^= GF128_RED;
|
|
39
|
+
return r;
|
|
40
|
+
}
|
|
41
|
+
/** Multiply by `x^i` (i ≥ 0): i LFSR steps. Used by the column-domain KOS fold. */
|
|
42
|
+
function gf128MulByXi(v, i) {
|
|
43
|
+
let r = v & MASK128;
|
|
44
|
+
for (let k = 0; k < i; k++)
|
|
45
|
+
r = gf128MulX(r);
|
|
46
|
+
return r;
|
|
47
|
+
}
|
|
48
|
+
/** Full GF(2^128) multiplication (carryless multiply + reduction), right-to-left over the bits of `b`. */
|
|
49
|
+
function gf128Mul(a, b) {
|
|
50
|
+
let res = 0n;
|
|
51
|
+
let v = a & MASK128;
|
|
52
|
+
for (let i = 0; i < 128; i++) {
|
|
53
|
+
if ((b >> BigInt(i)) & 1n)
|
|
54
|
+
res ^= v;
|
|
55
|
+
v = gf128MulX(v);
|
|
56
|
+
}
|
|
57
|
+
return res & MASK128;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=gf128.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gf128.js","sourceRoot":"","sources":["../src/gf128.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;AAYH,4BAEC;AAGD,8BAKC;AAGD,oCAIC;AAGD,4BAQC;AAtCD,oBAAoB;AACpB,MAAM,OAAO,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;AAElC;;;GAGG;AACH,MAAM,SAAS,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO;AAEpE,6DAA6D;AAC7D,SAAgB,QAAQ,CAAC,CAAS,EAAE,CAAS;IAC3C,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC;AAC3B,CAAC;AAED,6FAA6F;AAC7F,SAAgB,SAAS,CAAC,CAAS;IACjC,MAAM,KAAK,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/B,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC;IAC5B,IAAI,KAAK;QAAE,CAAC,IAAI,SAAS,CAAC;IAC1B,OAAO,CAAC,CAAC;AACX,CAAC;AAED,mFAAmF;AACnF,SAAgB,YAAY,CAAC,CAAS,EAAE,CAAS;IAC/C,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;QAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,CAAC;AACX,CAAC;AAED,0GAA0G;AAC1G,SAAgB,QAAQ,CAAC,CAAS,EAAE,CAAS;IAC3C,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE;YAAE,GAAG,IAAI,CAAC,CAAC;QACpC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,GAAG,GAAG,OAAO,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hybrid base OT — a SOUND combiner of the malicious-secure EC base OT (`ot.ts`/`ec.ts`) and the
|
|
3
|
+
* post-quantum committed ML-KEM base OT (`kem-ot.ts`), run together so the stack inherits the BEST
|
|
4
|
+
* guarantee of each half instead of the weakest.
|
|
5
|
+
*
|
|
6
|
+
* ─── WHY A COMBINER ────────────────────────────────────────────────────────────────────────────────
|
|
7
|
+
* The two base OTs this package ships have complementary weaknesses:
|
|
8
|
+
* • The EC base OT (`malBaseRandomOT`) is MALICIOUS-secure against both roles — a Schnorr NIZK proof
|
|
9
|
+
* of knowledge of `y` on `S = y·B`, full prime-order-subgroup validation of every transmitted
|
|
10
|
+
* point, and a random-OT core with no sender-chosen ciphertexts — but its hardness is the curve25519
|
|
11
|
+
* discrete log, which a QUANTUM adversary breaks with Shor.
|
|
12
|
+
* • The ML-KEM base OT (`kemBaseOtMalRandom`) is POST-QUANTUM (Module-LWE) and has unconditional,
|
|
13
|
+
* even-against-a-quantum-sender choice privacy, but against an actively-malicious receiver it has an
|
|
14
|
+
* IRREDUCIBLE residue from the opaque primitive: a receiver that runs keygen twice and keeps BOTH
|
|
15
|
+
* secret keys learns both messages, and the decisional-MLWE indistinguishability that gives choice
|
|
16
|
+
* privacy makes that cheat undetectable to the sender (see `kem-ot.ts` header).
|
|
17
|
+
*
|
|
18
|
+
* The combiner runs BOTH base OTs on the SAME choice bit and the SAME session, then derives each
|
|
19
|
+
* transfer key from BOTH halves' shared secrets:
|
|
20
|
+
*
|
|
21
|
+
* k_b = H( DOMAIN_SEP ‖ sid ‖ i ‖ b ‖ ss_ec_b ‖ ss_kem_b ) for b ∈ {0, 1}
|
|
22
|
+
*
|
|
23
|
+
* where `ss_ec_b` is the EC random-OT pad (`malBaseRandomOT`) and `ss_kem_b` the committed ML-KEM
|
|
24
|
+
* random-OT secret (`kemBaseOtMalRandom`, the hardened variant — never the semi-honest one). The sender
|
|
25
|
+
* one-time-pads `m_b` under `k_b` and commits to it (`com_b`); the honest receiver reconstructs only
|
|
26
|
+
* `k_c` (it holds only `ss_ec_c` and `ss_kem_c`) and checks `com_c`.
|
|
27
|
+
*
|
|
28
|
+
* ─── WHAT THIS ACHIEVES (precise) ───────────────────────────────────────────────────────────────────
|
|
29
|
+
* To recover `m_{1−c}` an adversary needs `k_{1−c}`, hence BOTH `ss_ec_{1−c}` AND `ss_kem_{1−c}` (the
|
|
30
|
+
* hash is a random oracle; missing either input leaves the pad pseudorandom). Therefore:
|
|
31
|
+
* • vs a CLASSICAL malicious receiver — MALICIOUS-secure. Even a receiver that defeats the KEM half
|
|
32
|
+
* entirely by keeping both ML-KEM secrets (so it holds `ss_kem_{1−c}`) still cannot obtain
|
|
33
|
+
* `ss_ec_{1−c}`: the EC base OT is malicious-secure and `ss_ec_{1−c} = H(y·R − T)` is a point the
|
|
34
|
+
* receiver cannot compute without the discrete log of `S`. No `ss_ec_{1−c}` ⇒ no `k_{1−c}` ⇒ `m_{1−c}`
|
|
35
|
+
* stays hidden. This is the KILLER property the tests prove.
|
|
36
|
+
* • SENDER PRIVACY vs a SEMI-HONEST QUANTUM receiver — holds via the KEM half (Module-LWE): a quantum
|
|
37
|
+
* receiver that follows the protocol (discards the non-chosen material) cannot get `ss_kem_{1−c}`,
|
|
38
|
+
* so again `k_{1−c}` is unobtainable even though it could break the EC half with Shor.
|
|
39
|
+
* • CHOICE PRIVACY — POST-QUANTUM. The KEM half's choice privacy is unconditional (two i.i.d. real
|
|
40
|
+
* ML-KEM public keys on the wire); the EC half's is information-theoretic in its transcript (`R` is a
|
|
41
|
+
* uniform subgroup element whatever `c` is). Neither leaks `c`, against any adversary.
|
|
42
|
+
* • SESSION BINDING — both halves are bound to a COMMON `sid` derived from BOTH sub-protocols'
|
|
43
|
+
* session material (the KEM `(rn, sn)` nonces and the EC point `S`), and `sid` is hashed into every
|
|
44
|
+
* transfer key and commitment, so secrets from one session/opened-key-set cannot be replayed into
|
|
45
|
+
* another. The KEM half additionally aborts (`KemBaseOtAbort`) if the receiver opens keys other than
|
|
46
|
+
* the ones it committed to; the EC half aborts (`BaseOtAbort`/`PointValidationError`) on a bad proof
|
|
47
|
+
* or an off-/small-order point; and the combiner aborts (`HybridOtAbort`) if a tampered ciphertext
|
|
48
|
+
* fails its commitment.
|
|
49
|
+
*
|
|
50
|
+
* ─── THE HONEST BOUNDARY (NOT faked) ────────────────────────────────────────────────────────────────
|
|
51
|
+
* The one residue this combiner does NOT close is a receiver that is SIMULTANEOUSLY actively-malicious
|
|
52
|
+
* AND quantum: such a receiver could break the classical EC half with Shor (recovering `ss_ec_{1−c}`
|
|
53
|
+
* from the transcript) WHILE keeping both ML-KEM secrets (recovering `ss_kem_{1−c}`), and so assemble
|
|
54
|
+
* `k_{1−c}`. Closing THAT requires a base OT that is BOTH post-quantum AND malicious-secure in one
|
|
55
|
+
* primitive — i.e. an endemic/UC OT from Module-LWE with a CRS, which needs direct lattice module
|
|
56
|
+
* arithmetic (sampling / adding in ML-KEM's structured public-key space to plant a secretless slot).
|
|
57
|
+
* The opaque `ml_kem768` keygen/encaps/decaps interface this package is restricted to does NOT expose
|
|
58
|
+
* that arithmetic, and hand-rolling it is exactly the lattice crypto the module forbids. So this is the
|
|
59
|
+
* honest limit of what a KEM-opaque + EC combiner can reach; it is stated, not papered over.
|
|
60
|
+
*
|
|
61
|
+
* No hand-rolled crypto: the EC half goes through `malBaseRandomOT` (unchanged), the KEM half through
|
|
62
|
+
* `kemBaseOtMalRandom` (unchanged), and this module only hashes (SHA-256 RO) and XORs their outputs.
|
|
63
|
+
*/
|
|
64
|
+
import { type Point } from './ec';
|
|
65
|
+
import { type BaseOtTamper, type OtChannel, type OtRandom } from './ot';
|
|
66
|
+
import { type KemMalTamper } from './kem-ot';
|
|
67
|
+
/** Raised when the hybrid combiner aborts: a sender ciphertext inconsistent with its commitment is caught. */
|
|
68
|
+
export declare class HybridOtAbort extends Error {
|
|
69
|
+
constructor(message: string);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The COMMON session id binding both halves: `H(TAG ‖ kemSid ‖ encode(ecS))`. It folds the KEM
|
|
73
|
+
* sub-protocol's two-nonce session id (`rn, sn`) and the EC sub-protocol's point `S`, so neither party
|
|
74
|
+
* alone fixes it and secrets cannot be mixed across sessions. Both parties derive the same value from
|
|
75
|
+
* the public transcript.
|
|
76
|
+
*/
|
|
77
|
+
export declare function hybridSessionId(kemSid: Uint8Array, ecS: Point): Uint8Array;
|
|
78
|
+
/**
|
|
79
|
+
* The hybrid transfer key for one slot: `H(TAG ‖ sid ‖ i ‖ slot ‖ ss_ec ‖ ss_kem)` expanded (SHA-256
|
|
80
|
+
* counter mode) to `len` bytes. Modelled as a random oracle: the key is pseudorandom unless BOTH
|
|
81
|
+
* `ss_ec` and `ss_kem` (for that exact slot/index/session) are supplied — the soundness crux of the
|
|
82
|
+
* combiner.
|
|
83
|
+
*/
|
|
84
|
+
export declare function hybridTransferKey(sid: Uint8Array, index: number, slot: number, ssEc: Uint8Array, ssKem: Uint8Array, len: number): Uint8Array;
|
|
85
|
+
/** The sender's wire message of the hybrid combiner: one-time-padded messages + per-message commitments. */
|
|
86
|
+
export interface HybridSenderMessage {
|
|
87
|
+
/** For each transfer i, `[E_0, E_1]` with `E_b = m_b ⊕ k_b`. */
|
|
88
|
+
encrypted: Array<[Uint8Array, Uint8Array]>;
|
|
89
|
+
/** For each transfer i, `[com_0, com_1]` with `com_b = H(sid ‖ i ‖ b ‖ m_b ‖ k_b)`. */
|
|
90
|
+
commitments: Array<[Uint8Array, Uint8Array]>;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* SENDER side of the combiner: given BOTH halves' per-slot shared secrets, derive both transfer keys,
|
|
94
|
+
* one-time-pad each message, and commit to each. `ecSecrets[i] = [ss_ec_0, ss_ec_1]` (the EC random-OT
|
|
95
|
+
* `senderPads`), `kemSecrets[i] = [ss_kem_0, ss_kem_1]` (the committed-KEM `senderSecrets`).
|
|
96
|
+
*/
|
|
97
|
+
export declare function hybridSenderEncrypt(sid: Uint8Array, messages: Array<[Uint8Array, Uint8Array]>, ecSecrets: Array<[Uint8Array, Uint8Array]>, kemSecrets: Array<[Uint8Array, Uint8Array]>): HybridSenderMessage;
|
|
98
|
+
/**
|
|
99
|
+
* RECEIVER side of the combiner: reconstruct ONLY the chosen transfer key (from the chosen EC and KEM
|
|
100
|
+
* secrets the receiver legitimately holds), unmask the chosen message, and CHECK the commitment.
|
|
101
|
+
* `ecRecv[i] = ss_ec_{choices[i]}` (the EC `recvPads`), `kemRecv[i] = ss_kem_{choices[i]}` (the
|
|
102
|
+
* committed-KEM `recvSecrets`). Aborts (`HybridOtAbort`) if the recovered message fails its commitment.
|
|
103
|
+
*/
|
|
104
|
+
export declare function hybridReceiverRecover(sid: Uint8Array, choices: number[], sender: HybridSenderMessage, ecRecv: Uint8Array[], kemRecv: Uint8Array[]): Uint8Array[];
|
|
105
|
+
/**
|
|
106
|
+
* TEST-ONLY injection points modelling malicious behaviour in the hybrid combiner. The `ec` / `kem`
|
|
107
|
+
* bags are forwarded to the respective sub-OTs (so each half's real malicious checks run against the
|
|
108
|
+
* adversarial value); `tamperEncrypted` corrupts the hybrid sender's ciphertexts on the wire (caught by
|
|
109
|
+
* the commitment check).
|
|
110
|
+
*/
|
|
111
|
+
export interface HybridBaseOtTamper {
|
|
112
|
+
/** Forwarded to the EC half (`malBaseRandomOT`): malicious sender/receiver on the EC sub-OT. */
|
|
113
|
+
ec?: BaseOtTamper;
|
|
114
|
+
/** Forwarded to the KEM half (`kemBaseOtMalRandom`): malicious receiver on the committed KEM sub-OT. */
|
|
115
|
+
kem?: KemMalTamper;
|
|
116
|
+
/** Malicious hybrid SENDER: corrupt the padded messages on the wire (inconsistent with the commitment). */
|
|
117
|
+
tamperEncrypted?: (encrypted: Array<[Uint8Array, Uint8Array]>) => void;
|
|
118
|
+
}
|
|
119
|
+
/** A full hybrid base-OT transcript, exposed for inspection/tests. */
|
|
120
|
+
export interface HybridBaseOtTranscript {
|
|
121
|
+
/** The common session id both halves are bound to. */
|
|
122
|
+
sid: Uint8Array;
|
|
123
|
+
/** The EC sub-OT's public point `S` (with its Schnorr proof available via the EC half). */
|
|
124
|
+
ecS: Point;
|
|
125
|
+
/** The committed-KEM sub-OT session id `H(rn ‖ sn)`. */
|
|
126
|
+
kemSid: Uint8Array;
|
|
127
|
+
encrypted: Array<[Uint8Array, Uint8Array]>;
|
|
128
|
+
commitments: Array<[Uint8Array, Uint8Array]>;
|
|
129
|
+
}
|
|
130
|
+
export interface HybridBaseOtResult {
|
|
131
|
+
/** Receiver's recovered messages `m_{i, choices[i]}`. */
|
|
132
|
+
received: Uint8Array[];
|
|
133
|
+
transcript: HybridBaseOtTranscript;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* In-process combined simulator (both parties in one call), matching the shape of `baseOT`/`kemBaseOT`
|
|
137
|
+
* so it is a drop-in for `OtChannel`'s `baseOtFn` (`withHybridBaseOt`). Runs the malicious-secure EC
|
|
138
|
+
* base OT and the committed ML-KEM base OT on the SAME choices, binds both to a common `sid`, and
|
|
139
|
+
* combines their per-slot secrets into the transfer keys. A cheating party is caught by whichever
|
|
140
|
+
* half's check applies (EC proof/point validation, KEM commitment, or the hybrid ciphertext
|
|
141
|
+
* commitment). `tamper` injects malicious behaviour for tests.
|
|
142
|
+
*/
|
|
143
|
+
export declare function hybridBaseOT(messages: Array<[Uint8Array, Uint8Array]>, choices: number[], rng?: OtRandom, tamper?: HybridBaseOtTamper): HybridBaseOtResult;
|
|
144
|
+
/**
|
|
145
|
+
* Wire the HYBRID base OT into the KOS OT-extension: a drop-in for `withKemBaseOt`/`withKemBaseOtMal`
|
|
146
|
+
* that makes `OtChannel` run its κ setup base OTs over the combiner. The extension inherits the
|
|
147
|
+
* combiner's guarantee — malicious security vs a classical receiver, PQ sender-privacy vs a semi-honest
|
|
148
|
+
* quantum one, and PQ choice privacy — with everything above the base OT (IKNP matrix, KOS correlation
|
|
149
|
+
* check, correlation-robust hash) unchanged.
|
|
150
|
+
*
|
|
151
|
+
* const ch = new OtChannel(secureOtRandom(), withHybridBaseOt());
|
|
152
|
+
*/
|
|
153
|
+
export declare function withHybridBaseOt(): ConstructorParameters<typeof OtChannel>[1];
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Hybrid base OT — a SOUND combiner of the malicious-secure EC base OT (`ot.ts`/`ec.ts`) and the
|
|
4
|
+
* post-quantum committed ML-KEM base OT (`kem-ot.ts`), run together so the stack inherits the BEST
|
|
5
|
+
* guarantee of each half instead of the weakest.
|
|
6
|
+
*
|
|
7
|
+
* ─── WHY A COMBINER ────────────────────────────────────────────────────────────────────────────────
|
|
8
|
+
* The two base OTs this package ships have complementary weaknesses:
|
|
9
|
+
* • The EC base OT (`malBaseRandomOT`) is MALICIOUS-secure against both roles — a Schnorr NIZK proof
|
|
10
|
+
* of knowledge of `y` on `S = y·B`, full prime-order-subgroup validation of every transmitted
|
|
11
|
+
* point, and a random-OT core with no sender-chosen ciphertexts — but its hardness is the curve25519
|
|
12
|
+
* discrete log, which a QUANTUM adversary breaks with Shor.
|
|
13
|
+
* • The ML-KEM base OT (`kemBaseOtMalRandom`) is POST-QUANTUM (Module-LWE) and has unconditional,
|
|
14
|
+
* even-against-a-quantum-sender choice privacy, but against an actively-malicious receiver it has an
|
|
15
|
+
* IRREDUCIBLE residue from the opaque primitive: a receiver that runs keygen twice and keeps BOTH
|
|
16
|
+
* secret keys learns both messages, and the decisional-MLWE indistinguishability that gives choice
|
|
17
|
+
* privacy makes that cheat undetectable to the sender (see `kem-ot.ts` header).
|
|
18
|
+
*
|
|
19
|
+
* The combiner runs BOTH base OTs on the SAME choice bit and the SAME session, then derives each
|
|
20
|
+
* transfer key from BOTH halves' shared secrets:
|
|
21
|
+
*
|
|
22
|
+
* k_b = H( DOMAIN_SEP ‖ sid ‖ i ‖ b ‖ ss_ec_b ‖ ss_kem_b ) for b ∈ {0, 1}
|
|
23
|
+
*
|
|
24
|
+
* where `ss_ec_b` is the EC random-OT pad (`malBaseRandomOT`) and `ss_kem_b` the committed ML-KEM
|
|
25
|
+
* random-OT secret (`kemBaseOtMalRandom`, the hardened variant — never the semi-honest one). The sender
|
|
26
|
+
* one-time-pads `m_b` under `k_b` and commits to it (`com_b`); the honest receiver reconstructs only
|
|
27
|
+
* `k_c` (it holds only `ss_ec_c` and `ss_kem_c`) and checks `com_c`.
|
|
28
|
+
*
|
|
29
|
+
* ─── WHAT THIS ACHIEVES (precise) ───────────────────────────────────────────────────────────────────
|
|
30
|
+
* To recover `m_{1−c}` an adversary needs `k_{1−c}`, hence BOTH `ss_ec_{1−c}` AND `ss_kem_{1−c}` (the
|
|
31
|
+
* hash is a random oracle; missing either input leaves the pad pseudorandom). Therefore:
|
|
32
|
+
* • vs a CLASSICAL malicious receiver — MALICIOUS-secure. Even a receiver that defeats the KEM half
|
|
33
|
+
* entirely by keeping both ML-KEM secrets (so it holds `ss_kem_{1−c}`) still cannot obtain
|
|
34
|
+
* `ss_ec_{1−c}`: the EC base OT is malicious-secure and `ss_ec_{1−c} = H(y·R − T)` is a point the
|
|
35
|
+
* receiver cannot compute without the discrete log of `S`. No `ss_ec_{1−c}` ⇒ no `k_{1−c}` ⇒ `m_{1−c}`
|
|
36
|
+
* stays hidden. This is the KILLER property the tests prove.
|
|
37
|
+
* • SENDER PRIVACY vs a SEMI-HONEST QUANTUM receiver — holds via the KEM half (Module-LWE): a quantum
|
|
38
|
+
* receiver that follows the protocol (discards the non-chosen material) cannot get `ss_kem_{1−c}`,
|
|
39
|
+
* so again `k_{1−c}` is unobtainable even though it could break the EC half with Shor.
|
|
40
|
+
* • CHOICE PRIVACY — POST-QUANTUM. The KEM half's choice privacy is unconditional (two i.i.d. real
|
|
41
|
+
* ML-KEM public keys on the wire); the EC half's is information-theoretic in its transcript (`R` is a
|
|
42
|
+
* uniform subgroup element whatever `c` is). Neither leaks `c`, against any adversary.
|
|
43
|
+
* • SESSION BINDING — both halves are bound to a COMMON `sid` derived from BOTH sub-protocols'
|
|
44
|
+
* session material (the KEM `(rn, sn)` nonces and the EC point `S`), and `sid` is hashed into every
|
|
45
|
+
* transfer key and commitment, so secrets from one session/opened-key-set cannot be replayed into
|
|
46
|
+
* another. The KEM half additionally aborts (`KemBaseOtAbort`) if the receiver opens keys other than
|
|
47
|
+
* the ones it committed to; the EC half aborts (`BaseOtAbort`/`PointValidationError`) on a bad proof
|
|
48
|
+
* or an off-/small-order point; and the combiner aborts (`HybridOtAbort`) if a tampered ciphertext
|
|
49
|
+
* fails its commitment.
|
|
50
|
+
*
|
|
51
|
+
* ─── THE HONEST BOUNDARY (NOT faked) ────────────────────────────────────────────────────────────────
|
|
52
|
+
* The one residue this combiner does NOT close is a receiver that is SIMULTANEOUSLY actively-malicious
|
|
53
|
+
* AND quantum: such a receiver could break the classical EC half with Shor (recovering `ss_ec_{1−c}`
|
|
54
|
+
* from the transcript) WHILE keeping both ML-KEM secrets (recovering `ss_kem_{1−c}`), and so assemble
|
|
55
|
+
* `k_{1−c}`. Closing THAT requires a base OT that is BOTH post-quantum AND malicious-secure in one
|
|
56
|
+
* primitive — i.e. an endemic/UC OT from Module-LWE with a CRS, which needs direct lattice module
|
|
57
|
+
* arithmetic (sampling / adding in ML-KEM's structured public-key space to plant a secretless slot).
|
|
58
|
+
* The opaque `ml_kem768` keygen/encaps/decaps interface this package is restricted to does NOT expose
|
|
59
|
+
* that arithmetic, and hand-rolling it is exactly the lattice crypto the module forbids. So this is the
|
|
60
|
+
* honest limit of what a KEM-opaque + EC combiner can reach; it is stated, not papered over.
|
|
61
|
+
*
|
|
62
|
+
* No hand-rolled crypto: the EC half goes through `malBaseRandomOT` (unchanged), the KEM half through
|
|
63
|
+
* `kemBaseOtMalRandom` (unchanged), and this module only hashes (SHA-256 RO) and XORs their outputs.
|
|
64
|
+
*/
|
|
65
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
66
|
+
exports.HybridOtAbort = void 0;
|
|
67
|
+
exports.hybridSessionId = hybridSessionId;
|
|
68
|
+
exports.hybridTransferKey = hybridTransferKey;
|
|
69
|
+
exports.hybridSenderEncrypt = hybridSenderEncrypt;
|
|
70
|
+
exports.hybridReceiverRecover = hybridReceiverRecover;
|
|
71
|
+
exports.hybridBaseOT = hybridBaseOT;
|
|
72
|
+
exports.withHybridBaseOt = withHybridBaseOt;
|
|
73
|
+
const node_crypto_1 = require("node:crypto");
|
|
74
|
+
const ec_1 = require("./ec");
|
|
75
|
+
const ot_1 = require("./ot");
|
|
76
|
+
const kem_ot_1 = require("./kem-ot");
|
|
77
|
+
const csprng_1 = require("./csprng");
|
|
78
|
+
const TAG_HYBRID_SID = new TextEncoder().encode('atlas-pca-mpc/hybrid-ot-sid');
|
|
79
|
+
const TAG_HYBRID_KEY = new TextEncoder().encode('atlas-pca-mpc/hybrid-ot-transfer-key');
|
|
80
|
+
const TAG_HYBRID_COMMIT = new TextEncoder().encode('atlas-pca-mpc/hybrid-ot-msg-commit');
|
|
81
|
+
function sha256(...chunks) {
|
|
82
|
+
const h = (0, node_crypto_1.createHash)('sha256');
|
|
83
|
+
for (const c of chunks)
|
|
84
|
+
h.update(c);
|
|
85
|
+
return new Uint8Array(h.digest());
|
|
86
|
+
}
|
|
87
|
+
function u32(x) {
|
|
88
|
+
const b = new Uint8Array(4);
|
|
89
|
+
b[0] = (x >>> 24) & 0xff;
|
|
90
|
+
b[1] = (x >>> 16) & 0xff;
|
|
91
|
+
b[2] = (x >>> 8) & 0xff;
|
|
92
|
+
b[3] = x & 0xff;
|
|
93
|
+
return b;
|
|
94
|
+
}
|
|
95
|
+
function xorBytes(a, b) {
|
|
96
|
+
if (a.length !== b.length)
|
|
97
|
+
throw new Error('hybrid-ot: XOR length mismatch');
|
|
98
|
+
const out = new Uint8Array(a.length);
|
|
99
|
+
for (let i = 0; i < a.length; i++)
|
|
100
|
+
out[i] = a[i] ^ b[i];
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
function ctEqual(a, b) {
|
|
104
|
+
return a.length === b.length && (0, node_crypto_1.timingSafeEqual)(Buffer.from(a), Buffer.from(b));
|
|
105
|
+
}
|
|
106
|
+
/** Raised when the hybrid combiner aborts: a sender ciphertext inconsistent with its commitment is caught. */
|
|
107
|
+
class HybridOtAbort extends Error {
|
|
108
|
+
constructor(message) {
|
|
109
|
+
super(message);
|
|
110
|
+
this.name = 'HybridOtAbort';
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.HybridOtAbort = HybridOtAbort;
|
|
114
|
+
/**
|
|
115
|
+
* The COMMON session id binding both halves: `H(TAG ‖ kemSid ‖ encode(ecS))`. It folds the KEM
|
|
116
|
+
* sub-protocol's two-nonce session id (`rn, sn`) and the EC sub-protocol's point `S`, so neither party
|
|
117
|
+
* alone fixes it and secrets cannot be mixed across sessions. Both parties derive the same value from
|
|
118
|
+
* the public transcript.
|
|
119
|
+
*/
|
|
120
|
+
function hybridSessionId(kemSid, ecS) {
|
|
121
|
+
return sha256(TAG_HYBRID_SID, kemSid, (0, ec_1.encodePoint)(ecS));
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The hybrid transfer key for one slot: `H(TAG ‖ sid ‖ i ‖ slot ‖ ss_ec ‖ ss_kem)` expanded (SHA-256
|
|
125
|
+
* counter mode) to `len` bytes. Modelled as a random oracle: the key is pseudorandom unless BOTH
|
|
126
|
+
* `ss_ec` and `ss_kem` (for that exact slot/index/session) are supplied — the soundness crux of the
|
|
127
|
+
* combiner.
|
|
128
|
+
*/
|
|
129
|
+
function hybridTransferKey(sid, index, slot, ssEc, ssKem, len) {
|
|
130
|
+
const out = new Uint8Array(len);
|
|
131
|
+
let produced = 0;
|
|
132
|
+
let ctr = 0;
|
|
133
|
+
while (produced < len) {
|
|
134
|
+
const block = sha256(TAG_HYBRID_KEY, sid, u32(index), Uint8Array.of(slot & 1), u32(ctr), ssEc, ssKem);
|
|
135
|
+
for (let k = 0; k < block.length && produced < len; k++)
|
|
136
|
+
out[produced++] = block[k];
|
|
137
|
+
ctr++;
|
|
138
|
+
}
|
|
139
|
+
return out;
|
|
140
|
+
}
|
|
141
|
+
/** Per-message RO commitment `com = H(TAG ‖ sid ‖ i ‖ slot ‖ msg ‖ key)`, bound to the session. */
|
|
142
|
+
function hybridCommit(sid, index, slot, msg, key) {
|
|
143
|
+
return sha256(TAG_HYBRID_COMMIT, sid, u32(index), Uint8Array.of(slot & 1), msg, key);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* SENDER side of the combiner: given BOTH halves' per-slot shared secrets, derive both transfer keys,
|
|
147
|
+
* one-time-pad each message, and commit to each. `ecSecrets[i] = [ss_ec_0, ss_ec_1]` (the EC random-OT
|
|
148
|
+
* `senderPads`), `kemSecrets[i] = [ss_kem_0, ss_kem_1]` (the committed-KEM `senderSecrets`).
|
|
149
|
+
*/
|
|
150
|
+
function hybridSenderEncrypt(sid, messages, ecSecrets, kemSecrets) {
|
|
151
|
+
if (messages.length !== ecSecrets.length || messages.length !== kemSecrets.length) {
|
|
152
|
+
throw new Error('hybridSenderEncrypt: messages/ecSecrets/kemSecrets length mismatch');
|
|
153
|
+
}
|
|
154
|
+
const encrypted = [];
|
|
155
|
+
const commitments = [];
|
|
156
|
+
for (let i = 0; i < messages.length; i++) {
|
|
157
|
+
const [m0, m1] = messages[i];
|
|
158
|
+
if (m0.length !== m1.length) {
|
|
159
|
+
throw new Error(`hybridSenderEncrypt (index ${i}): the two messages must be equal length`);
|
|
160
|
+
}
|
|
161
|
+
const k0 = hybridTransferKey(sid, i, 0, ecSecrets[i][0], kemSecrets[i][0], m0.length);
|
|
162
|
+
const k1 = hybridTransferKey(sid, i, 1, ecSecrets[i][1], kemSecrets[i][1], m1.length);
|
|
163
|
+
encrypted.push([xorBytes(m0, k0), xorBytes(m1, k1)]);
|
|
164
|
+
commitments.push([hybridCommit(sid, i, 0, m0, k0), hybridCommit(sid, i, 1, m1, k1)]);
|
|
165
|
+
}
|
|
166
|
+
return { encrypted, commitments };
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* RECEIVER side of the combiner: reconstruct ONLY the chosen transfer key (from the chosen EC and KEM
|
|
170
|
+
* secrets the receiver legitimately holds), unmask the chosen message, and CHECK the commitment.
|
|
171
|
+
* `ecRecv[i] = ss_ec_{choices[i]}` (the EC `recvPads`), `kemRecv[i] = ss_kem_{choices[i]}` (the
|
|
172
|
+
* committed-KEM `recvSecrets`). Aborts (`HybridOtAbort`) if the recovered message fails its commitment.
|
|
173
|
+
*/
|
|
174
|
+
function hybridReceiverRecover(sid, choices, sender, ecRecv, kemRecv) {
|
|
175
|
+
const { encrypted, commitments } = sender;
|
|
176
|
+
if (encrypted.length !== choices.length ||
|
|
177
|
+
commitments.length !== choices.length ||
|
|
178
|
+
ecRecv.length !== choices.length ||
|
|
179
|
+
kemRecv.length !== choices.length) {
|
|
180
|
+
throw new Error('hybridReceiverRecover: length mismatch');
|
|
181
|
+
}
|
|
182
|
+
const received = [];
|
|
183
|
+
for (let i = 0; i < choices.length; i++) {
|
|
184
|
+
const c = choices[i] & 1;
|
|
185
|
+
const e = encrypted[i][c];
|
|
186
|
+
const key = hybridTransferKey(sid, i, c, ecRecv[i], kemRecv[i], e.length);
|
|
187
|
+
const m = xorBytes(e, key);
|
|
188
|
+
const check = hybridCommit(sid, i, c, m, key);
|
|
189
|
+
if (!ctEqual(check, commitments[i][c])) {
|
|
190
|
+
throw new HybridOtAbort(`hybrid base OT (index ${i}): sender ciphertext inconsistent with its commitment; aborting`);
|
|
191
|
+
}
|
|
192
|
+
received.push(m);
|
|
193
|
+
}
|
|
194
|
+
return received;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* In-process combined simulator (both parties in one call), matching the shape of `baseOT`/`kemBaseOT`
|
|
198
|
+
* so it is a drop-in for `OtChannel`'s `baseOtFn` (`withHybridBaseOt`). Runs the malicious-secure EC
|
|
199
|
+
* base OT and the committed ML-KEM base OT on the SAME choices, binds both to a common `sid`, and
|
|
200
|
+
* combines their per-slot secrets into the transfer keys. A cheating party is caught by whichever
|
|
201
|
+
* half's check applies (EC proof/point validation, KEM commitment, or the hybrid ciphertext
|
|
202
|
+
* commitment). `tamper` injects malicious behaviour for tests.
|
|
203
|
+
*/
|
|
204
|
+
function hybridBaseOT(messages, choices, rng = (0, csprng_1.secureOtRandom)(), tamper) {
|
|
205
|
+
if (messages.length !== choices.length) {
|
|
206
|
+
throw new Error('hybridBaseOT: messages/choices length mismatch');
|
|
207
|
+
}
|
|
208
|
+
// EC half: malicious-secure random OT with ALL checks ON (Schnorr proof + subgroup validation).
|
|
209
|
+
const ec = (0, ot_1.malBaseRandomOT)(choices, rng, tamper?.ec);
|
|
210
|
+
// KEM half: the committed/session-bound random OT (aborts on an opened-key/commitment mismatch).
|
|
211
|
+
const kem = (0, kem_ot_1.kemBaseOtMalRandom)(choices, rng, tamper?.kem);
|
|
212
|
+
const sid = hybridSessionId(kem.sid, ec.S);
|
|
213
|
+
const sender = hybridSenderEncrypt(sid, messages, ec.senderPads, kem.senderSecrets);
|
|
214
|
+
// A malicious hybrid SENDER may corrupt the ciphertexts on the wire (test-injected).
|
|
215
|
+
if (tamper?.tamperEncrypted)
|
|
216
|
+
tamper.tamperEncrypted(sender.encrypted);
|
|
217
|
+
const received = hybridReceiverRecover(sid, choices, sender, ec.recvPads, kem.recvSecrets);
|
|
218
|
+
return {
|
|
219
|
+
received,
|
|
220
|
+
transcript: {
|
|
221
|
+
sid,
|
|
222
|
+
ecS: ec.S,
|
|
223
|
+
kemSid: kem.sid,
|
|
224
|
+
encrypted: sender.encrypted,
|
|
225
|
+
commitments: sender.commitments,
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Wire the HYBRID base OT into the KOS OT-extension: a drop-in for `withKemBaseOt`/`withKemBaseOtMal`
|
|
231
|
+
* that makes `OtChannel` run its κ setup base OTs over the combiner. The extension inherits the
|
|
232
|
+
* combiner's guarantee — malicious security vs a classical receiver, PQ sender-privacy vs a semi-honest
|
|
233
|
+
* quantum one, and PQ choice privacy — with everything above the base OT (IKNP matrix, KOS correlation
|
|
234
|
+
* check, correlation-robust hash) unchanged.
|
|
235
|
+
*
|
|
236
|
+
* const ch = new OtChannel(secureOtRandom(), withHybridBaseOt());
|
|
237
|
+
*/
|
|
238
|
+
function withHybridBaseOt() {
|
|
239
|
+
return { baseOtFn: (m, c, r) => ({ received: hybridBaseOT(m, c, r).received }) };
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=hybrid-ot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hybrid-ot.js","sourceRoot":"","sources":["../src/hybrid-ot.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @atlasauth/pca-mpc — PCA evolution B5 reference prototype.
|
|
3
|
+
*
|
|
4
|
+
* A multi-stakeholder Policy VM composed under secure multi-party computation, so user + org +
|
|
5
|
+
* regulator decide allow / threshold jointly WITHOUT any party revealing its own policy. Two layers:
|
|
6
|
+
* - SEMI-HONEST: additive secret sharing over a prime field + Beaver-triple multiplication
|
|
7
|
+
* (`sharing.ts`, `beaver.ts`, `runner.ts`).
|
|
8
|
+
* - MALICIOUS-WITH-ABORT (dishonest-majority): SPDZ-style authenticated sharing with
|
|
9
|
+
* information-theoretic MACs + a commit-then-open MAC-check that ABORTS on any deviation
|
|
10
|
+
* (`spdz.ts`, `spdz-runner.ts`). Result is correct, or an abort — never a silent wrong answer.
|
|
11
|
+
* See docs/specs/pca-mpc-policy-vm.md for the security model and the trusted-dealer / no-dealer boundary.
|
|
12
|
+
*/
|
|
13
|
+
export * from './field';
|
|
14
|
+
export * from './sharing';
|
|
15
|
+
export * from './beaver';
|
|
16
|
+
export * from './thermometer';
|
|
17
|
+
export * from './party';
|
|
18
|
+
export * from './compose';
|
|
19
|
+
export * from './runner';
|
|
20
|
+
export * from './spdz';
|
|
21
|
+
export * from './spdz-runner';
|
|
22
|
+
export * from './ec';
|
|
23
|
+
export * from './gf128';
|
|
24
|
+
export * from './csprng';
|
|
25
|
+
export * from './ot';
|
|
26
|
+
export * from './kem-ot';
|
|
27
|
+
export * from './hybrid-ot';
|
|
28
|
+
export * from './mascot';
|
|
29
|
+
export * from './endemic-ot';
|