feat: shares and secrets written on paper, shown once and typed back - #219
Merged
Merged
Conversation
reveal shows a share or any byte artifact for a person to write down. A window over the log says the value is coming and that it is not written to the transcript, shows it on Enter with its rows numbered as on the sheet, and closes only on a yes to "every row written down and checked?". The prompt is recorded without the value and the fact says only that it was shown. The console asks the same way and says to clear the terminal; a headless run acknowledges in a dry run and stops otherwise. The encoding is paper32, in rite_model::paper32: rows of 28 base-32 characters and 4 of parity, the alphabet without I, L, O and U, each row a Reed-Solomon codeword over GF(32) evaluated at all 32 field elements. One wrong character in a row is corrected and the row named, two unreadable ones (typed as ? or U) are recovered, and a row that needs more is refused by name. A correct sheet decodes by dropping the last four characters of each row. A share is its wire bytes in these rows, 64 characters for a 32-byte secret. format: hex shows two characters per byte instead. rite script writes the sheets beside the script, in <name>.worksheets.html or where --worksheets says, one page per reveal step: the ceremony in the header, the step's message and note, rows of boxes in cells of four with the parity cells shaded, the encoding in small print. length: makes the rows exact, and the step refuses a value of another size before showing it. enter_share types a share back from its sheet. A new prompt, EnterRows, takes a value row by row; the TUI and the console check each row as it is typed, so a slip is corrected and its row named at once. Every row but the last is full, so a short row where more are due is refused and a short row ends an entry of no set length. Rows that are not a share, or a share of another size than length: says, are asked for again through the reporter's new prompt_checked. The share is held as a set of one, which combine_shares names without a property. The transcript records the share's index and the rows repaired, never the rows. enter_secret takes format: paper32 through the same prompt, which carries the step's rule so the runtime checks it and a rehearsal can build a stand-in; enter_value refuses paper32. split_secret no longer logs how its shares are named. The split_and_combine example splits a 32-byte secret and hands share 3 over on paper; recover_from_paper recovers a secret from two fixed sheets typed back and checks it against a digest. Examples with an enter_share step are left out of the dry-run test, since no made-up value is a share; instead a test types the published sheets back through enter_share and combine_shares and must get secret.txt, which pins the alphabet, bit order, parity, row size and share header to fixed text. ReporterHarness hands a reporter only the answers queued when it was built, so a prompt left without one fails instead of waiting forever. docs/secret-sharing.md and docs/typed-entry.md cover the actions, the paper format and the sheet, and the transcript schema covers the two new prompts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the human side of secret sharing: a share (or any byte value) leaves the machine once, on a paper sheet, and comes back by being typed from that sheet.
revealshows a value in a window of its own. The window says the value is coming and who it is for, shows it on Enter with its rows numbered as on the sheet, and closes only on a yes to "every row written down and checked?". The transcript records the message and the acknowledgement, never the value. The console asks the same way and says to clear the terminal; a headless run acknowledges in a dry run and stops otherwise.length:makes the sheet exact, and a value of another size is refused before it is shown.paper32 (
rite_model::paper32) is the encoding: rows of 28 base-32 characters plus 4 of parity, Crockford's alphabet (no I, L, O, U, either case, O read as 0 and I/L as 1), each row a Reed-Solomon codeword over GF(32). A wrong character in a row is corrected and the row named; two unreadable ones (typed as?orU) are recovered; a row that needs more is refused by name. Every row but the last is full, so a correct sheet decodes by hand by dropping the last four characters of each row.format: hexis available as a plain alternative.Worksheets.
rite scriptnow also writes<name>.worksheets.htmlbeside the script when a step shows a value: one page perrevealstep, rows of boxes in groups of four with the parity cells shaded, the encoding in small print. It is a separate document because a sheet is printed once and kept with the value, while the script is copied for everyone.--worksheets <path>moves it.enter_sharetypes a share back. A newEnterRowsprompt takes the value row by row; the TUI and the console check each row as it is typed, so a slip is corrected and named at once, and a short row where more are due is refused. Rows that are not a share, or a share of another size, are asked for again (Reporter::prompt_checked). The share arrives as a set of one thatcombine_sharesreads directly. The transcript records the share's index and which rows were repaired, never the rows.enter_secretalso takesformat: paper32;enter_valuerefuses it, since a value on a sheet is a secret.Examples and tests.
split_and_combinenow splits a 32-byte secret and hands share 3 over on paper. The newrecover_from_paperrecovers it from two fixed sheets and checks the result against a digest. It is left out of the dry-run test (no made-up value is a share); instead a test inrite-stdlibtypes the published sheets back and must recoversecret.txt, which pins the alphabet, bit order, parity, row size and share header to fixed text.ReporterHarnessnow fails a er instead of blocking forever.