owenrusk.dev

tally

shamir's secret sharing over gf(256).

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

commit f34ae17f113f029d4c1057b0d7786e3a3d25b797
parent 49397b48b5b9c69fe020cc885882e7dc5c40eb71
author Owen Rusk <owen@papermothgames.com>
date   2026-10-08 16:58:24 -0500
split: drop --secret, read from a file or stdin only

a secret passed as an argument ends up in shell history and in ps.
README.md+3-1
tally/cli.py+3-5
tests/test_cli.py+3-3
diff --git a/README.md b/README.md
index e5ebb5b..47ceda5 100644
--- a/README.md
+++ b/README.md
@@ -15,10 +15,12 @@ or run it in place with `python -m tally`.
 ## split
 
     tally split -k 3 -n 5 secret.txt
-    tally split -k 2 -n 3 --secret 'something'
+    tally split -k 2 -n 3 < secret.txt
 
 reads the secret from the file, or from stdin if there's no file, and prints n shares, one per line. 2 <= k <= n <= 255.
 
+the secret is never an argument. arguments end up in shell history and in `ps`.
+
 ## join
 
     tally join SHARE SHARE SHARE
diff --git a/tally/cli.py b/tally/cli.py
index 7792b7e..9b77cd6 100644
--- a/tally/cli.py
+++ b/tally/cli.py
@@ -1,13 +1,12 @@
 import argparse
 import sys
 
-from . import ShareError, join, split
+from . import join, split
 
 
 def cmd_split(args: argparse.Namespace) -> int:
-    if args.secret is not None:
-        secret = args.secret.encode()
-    elif args.file in (None, "-"):
+    # never from an argument: those end up in shell history and in ps
+    if args.file in (None, "-"):
         secret = sys.stdin.buffer.read()
     else:
         with open(args.file, "rb") as f:
@@ -35,7 +34,6 @@ def main(argv: list[str] | None = None) -> int:
     p = sub.add_parser("split", help="split a secret into n shares")
     p.add_argument("-k", type=int, required=True, help="shares needed to rebuild it")
     p.add_argument("-n", type=int, required=True, help="shares to make")
-    p.add_argument("-s", "--secret", help="the secret itself, instead of a file")
     p.add_argument("file", nargs="?", help="file to read the secret from (default: stdin)")
     p.set_defaults(func=cmd_split)
 
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 7dc1bd0..8f2e3f9 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -46,10 +46,10 @@ class CliTest(unittest.TestCase):
         self.assertEqual(join.returncode, 0, join.stderr)
         self.assertEqual(join.stdout, b"not a real secret")
 
-    def test_secret_option(self) -> None:
+    def test_no_secret_on_the_command_line(self) -> None:
         split = tally("split", "-k", "2", "-n", "2", "--secret", "not a real secret")
-        join = tally("join", stdin=split.stdout)
-        self.assertEqual(join.stdout, b"not a real secret")
+        self.assertEqual(split.returncode, 2)
+        self.assertEqual(split.stdout, b"")
 
     def test_fewer_than_k(self) -> None:
         split = tally("split", "-k", "3", "-n", "5", stdin=b"not a real secret")