tally
Split a secret into n shares. Any k of them rebuild it. Fewer than k tell you nothing.
shamir's secret sharing over gf(256), one byte at a time. standard library only, randomness from secrets.
install
python 3.12 or newer. from a checkout:
pip install .
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.txt
tally split -k 3 -n 5 -o shares/ 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.
with -o DIR each share goes to its own file instead, DIR/share-1.txt and on, mode 600. it won't overwrite a share that's already there.
the secret is never an argument. arguments end up in shell history and in ps.
join
tally join SHARE SHARE SHARE
tally join < shares.txt
takes the shares as arguments, or one per line on stdin, and prints the secret. it refuses fewer than k, the same share twice, and shares from different splits. shares past the first k are checked against them.
on stdin, blank lines and lines starting with # are skipped, so a file of shares can carry notes.
share format
t1-xxxx-xxxx-xxxx-...
t1 is the format version. the rest is crockford's base32 (digits and lowercase letters, no i, l, o or u) in groups of four, carrying:
id 4 bytes, random, the same on every share of one split
k 1 byte, how many shares it takes
x 1 byte, this share's number, 1 to n
data as long as the secret
check 4 bytes, crc32 of "t1" and everything above
case, spaces and dashes don't matter when reading a share back, and o reads as 0, i and l as 1. a typo fails the check instead of rebuilding the wrong secret.
a share gives away k and the secret's length. nothing else.
t1 won't change. a different format would get a different number.
example
$ printf 'hello' | tally split -k 2 -n 3
t1-37bm-w6r2-05ak-qdek-eg8b-0mzr
t1-37bm-w6r2-089d-kh89-b5n7-gd8c
t1-37bm-w6r2-0cqr-e75p-8aw2-f5sb
$ tally join t1-37bm-w6r2-0cqr-e75p-8aw2-f5sb t1-37bm-w6r2-05ak-qdek-eg8b-0mzr
hello
$ tally join t1-37bm-w6r2-0cqr-e75p-8aw2-f5sb
tally: need 2 shares, got 1
shares from one split start the same way: that's the id. the secret comes back byte for byte, so echo would have split a trailing newline along with it.