owenrusk.dev

tally

shamir's secret sharing over gf(256).

git clone https://owenrusk.dev/tally.git

commit bdc899c85c20d8e61ea10ea5d4065e663de0b4af
parent 0c268631da02f3502d28d0712938bb4469b5c8a6
author Owen Rusk <owen@papermothgames.com>
date   2024-09-12 20:10:37 -0500
tests: every k-subset rebuilds, for more k, n and lengths
tests/test_shamir.py+37-8
diff --git a/tests/test_shamir.py b/tests/test_shamir.py
index c3b9a42..e8cfcec 100644
--- a/tests/test_shamir.py
+++ b/tests/test_shamir.py
@@ -1,9 +1,13 @@
 import itertools
 import os
+import random
 import unittest
 
 from tally import shamir
 
+LENGTHS = [1, 2, 3, 15, 16, 17, 64, 255, 256, 1000]
+SHAPES = [(2, 2), (2, 3), (3, 5), (5, 5), (4, 7), (6, 9)]
+
 
 class ShamirTest(unittest.TestCase):
     def test_round_trip(self) -> None:
@@ -12,16 +16,41 @@ class ShamirTest(unittest.TestCase):
         self.assertEqual(len(shares), 5)
         self.assertEqual(shamir.combine(shares[:3]), secret)
 
-    def test_any_three_of_five(self) -> None:
-        secret = os.urandom(32)
-        shares = shamir.split(secret, 3, 5)
-        for subset in itertools.combinations(shares, 3):
-            self.assertEqual(shamir.combine(list(subset)), secret)
+    def test_many_lengths(self) -> None:
+        for length in LENGTHS:
+            secret = os.urandom(length)
+            shares = shamir.split(secret, 3, 5)
+            self.assertTrue(all(len(data) == length for _, data in shares))
+            with self.subTest(length=length):
+                self.assertEqual(shamir.combine(random.sample(shares, 3)), secret)
+
+    def test_every_k_subset_rebuilds(self) -> None:
+        for k, n in SHAPES:
+            secret = os.urandom(random.choice([1, 17, 100]))
+            shares = shamir.split(secret, k, n)
+            for subset in itertools.combinations(shares, k):
+                with self.subTest(k=k, n=n, xs=[x for x, _ in subset]):
+                    self.assertEqual(shamir.combine(list(subset)), secret)
 
-    def test_two_of_five_is_not_enough(self) -> None:
+    def test_order_doesnt_matter(self) -> None:
         secret = os.urandom(32)
-        shares = shamir.split(secret, 3, 5)
-        self.assertNotEqual(shamir.combine(shares[:2]), secret)
+        shares = shamir.split(secret, 4, 6)
+        for _ in range(20):
+            self.assertEqual(shamir.combine(random.sample(shares, 4)), secret)
+
+    def test_widest(self) -> None:
+        secret = os.urandom(3)
+        shares = shamir.split(secret, 2, 255)
+        self.assertEqual(shamir.combine([shares[0], shares[254]]), secret)
+        shares = shamir.split(secret, 255, 255)
+        self.assertEqual(shamir.combine(shares), secret)
+
+    def test_fewer_than_k_is_not_enough(self) -> None:
+        for k, n in SHAPES:
+            secret = os.urandom(32)
+            shares = shamir.split(secret, k, n)
+            with self.subTest(k=k, n=n):
+                self.assertNotEqual(shamir.combine(shares[: k - 1]), secret)
 
     def test_bad_k_and_n(self) -> None:
         for k, n in [(1, 3), (4, 3), (2, 256), (0, 0)]: