Secure Multi-Party Aggregation (SMPC)¶
Score and aggregate across confidential parties — hospital A and hospital B, or two tenants — without any party revealing its input to another. The privacy comes from secret sharing: a value is split into shares that individually reveal nothing, and only the aggregate is reconstructed.
Scope. This is the information-theoretic secret-sharing layer: additive (
n-of-n) and Shamir (t-of-n) sharing plus secure summation — the SMPC primitive for linear federated aggregation (sum, mean, count). Multiplicative MPC (SPDZ/MASCOT with Beaver triples and an interactive online phase) is a separate networked protocol and is out of scope here.
Additive secure aggregation¶
Each party splits its value into shares; the aggregator sums the shares component-wise and reconstructs only the total. No single party's value is ever materialised.
from director_ai import ProductionGuard
from director_ai.core.config import DirectorConfig
from director_ai.core.federated_privacy.secret_sharing import split
agg = ProductionGuard(DirectorConfig()).secure_aggregator(party_count=3)
for value in (10, 20, 12):
agg.submit(split(value, party_count=3))
print(agg.reconstruct()) # 42 — the sum, never any single value
Additive sharing is n-of-n: every party must contribute, and one dropout loses
the result.
Shamir threshold sharing¶
Shamir t-of-n sharing tolerates dropouts and collusion: any t of the n
parties reconstruct the secret, while fewer than t learn nothing — so up to
n - t parties can drop out and up to t - 1 can collude without breaking
privacy.
from director_ai.core.federated_privacy import (
shamir_split, shamir_reconstruct, shamir_sum_shares,
)
shares = shamir_split(secret, party_count=5, threshold=3) # 3-of-5
secret_back = shamir_reconstruct(shares[:3]) # any 3 suffice
# Secure summation across parties (additively homomorphic), dropout-tolerant:
groups = [shamir_split(v, party_count=5, threshold=3) for v in private_values]
total_shares = shamir_sum_shares(groups)
total = shamir_reconstruct(total_shares[:3]) # = sum(private_values)
The field modulus is the Mersenne prime 2**127 - 1, so the Lagrange
interpolation that reconstructs the secret always has the modular inverses it
needs. Shares carry no plaintext, so the protocol metadata is safe to route over
any transport. Production code must leave seed unset so the system CSPRNG is
used; a seed is for reproducible tests only and requires allow_insecure_seed=True.