tally
shamir's secret sharing over gf(256).
git clone https://owenrusk.dev/tally.git
commit 07d5b0d9de5ea454e03e1defe9b668cb5e4ce68d parent eed86d5b4ffb6b8bded85b168a45f131cf16dc27 author Owen Rusk <owen@papermothgames.com> date 2025-11-17 21:25:48 -0600
shamir: lagrange weights once per join, not once per byte joining a few kilobytes at k=10 went from seconds to a blink.
| tally/shamir.py | +13 | -11 |
diff --git a/tally/shamir.py b/tally/shamir.py index 30d44b4..368be83 100644 --- a/tally/shamir.py +++ b/tally/shamir.py @@ -28,17 +28,19 @@ def interpolate(shares: list[tuple[int, bytes]], x: int = 0) -> bytes: xs = [xj for xj, _ in shares] if len(set(xs)) != len(xs): raise ValueError("two shares with the same x")- out = bytearray()- for i in range(len(shares[0][1])):- acc = 0- for j, (xj, ys) in enumerate(shares):- num = den = 1- for m, xm in enumerate(xs):- if m != j:- num = gf256.mul(num, xm ^ x)- den = gf256.mul(den, xm ^ xj)- acc ^= gf256.mul(ys[i], gf256.div(num, den))- out.append(acc)+ # the weights depend only on the xs, so work them out once, not once per byte + weights = [] + for j, xj in enumerate(xs): + num = den = 1 + for m, xm in enumerate(xs): + if m != j: + num = gf256.mul(num, xm ^ x) + den = gf256.mul(den, xm ^ xj) + weights.append(gf256.div(num, den)) + out = bytearray(len(shares[0][1])) + for w, (_, ys) in zip(weights, shares): + for i, y in enumerate(ys): + out[i] ^= gf256.mul(w, y) return bytes(out)