tally
shamir's secret sharing over gf(256).
git clone https://owenrusk.dev/tally.git
tally / README.md -rw-r--r-- · 2401 bytes
1 # tally 2 3 Split a secret into n shares. Any k of them rebuild it. Fewer than k tell you nothing. 4 5 shamir's secret sharing over gf(256), one byte at a time. standard library only, randomness from `secrets`. 6 7 ## install 8 9 python 3.12 or newer. from a checkout: 10 11 pip install . 12 13 or run it in place with `python -m tally`. 14 15 ## split 16 17 tally split -k 3 -n 5 secret.txt 18 tally split -k 2 -n 3 < secret.txt 19 tally split -k 3 -n 5 -o shares/ secret.txt 20 21 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. 22 23 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. 24 25 the secret is never an argument. arguments end up in shell history and in `ps`. 26 27 ## join 28 29 tally join SHARE SHARE SHARE 30 tally join < shares.txt 31 32 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. 33 34 on stdin, blank lines and lines starting with `#` are skipped, so a file of shares can carry notes. 35 36 ## share format 37 38 t1-xxxx-xxxx-xxxx-... 39 40 `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: 41 42 id 4 bytes, random, the same on every share of one split 43 k 1 byte, how many shares it takes 44 x 1 byte, this share's number, 1 to n 45 data as long as the secret 46 check 4 bytes, crc32 of "t1" and everything above 47 48 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. 49 50 a share gives away k and the secret's length. nothing else. 51 52 `t1` won't change. a different format would get a different number. 53 54 ## example 55 56 $ printf 'hello' | tally split -k 2 -n 3 57 t1-37bm-w6r2-05ak-qdek-eg8b-0mzr 58 t1-37bm-w6r2-089d-kh89-b5n7-gd8c 59 t1-37bm-w6r2-0cqr-e75p-8aw2-f5sb 60 61 $ tally join t1-37bm-w6r2-0cqr-e75p-8aw2-f5sb t1-37bm-w6r2-05ak-qdek-eg8b-0mzr 62 hello 63 64 $ tally join t1-37bm-w6r2-0cqr-e75p-8aw2-f5sb 65 tally: need 2 shares, got 1 66 67 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.