From 1ae976e5db71908637de281b53b94de1cd854bcf Mon Sep 17 00:00:00 2001 From: Matthew Grotheer <34672297+mgrotheer@users.noreply.github.com> Date: Sat, 20 Jul 2024 23:16:49 -0700 Subject: [PATCH] feat: write out results of tested seed phrase reconstruction to txt file (#8) * print out results of testing seed phrase reconstruction * cargo fmt * remove unused function * update fmt --- src/main.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/src/main.rs b/src/main.rs index e2a2b44..7551acc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,11 @@ mod gf256; mod shamir; mod utils; -use std::str::FromStr; +use std::{ + fs::File, + io::{self, Write}, + str::FromStr, +}; use clap::{command, Parser}; use color_eyre::owo_colors::OwoColorize; @@ -114,7 +118,7 @@ fn main() -> Result<()> { // Double-check that the secret can be reconstructed from the shares. #[cfg(feature = "double-check")] - double_check_shares(&secret, &shares, t as usize); + double_check_shares(&secret, &shares, t as usize, &dictionary)?; } Operation::Reconstruct { shares } => { // Generate a bip-39 share from each input mnemonic. @@ -178,23 +182,77 @@ fn pretty_print_mnemonic(heading: &str, mnemonic: &str) { /// Double-check that the secret can be reconstructed from any `t` shares. /// Panic if the secret cannot be reconstructed. #[cfg(feature = "double-check")] -fn double_check_shares(secret: &Bip39Secret, shares: &[Bip39Share], t: usize) { +fn double_check_shares( + secret: &Bip39Secret, + shares: &[Bip39Share], + t: usize, + dictionary: &Bip39Dictionary, +) -> io::Result<()> { use itertools::Itertools; - print!("Double-checking secret can be reconstructed from any {t} shares..."); + // Open a file for writing the output + let mut file = File::create("reconstructed_seed_phrases.txt")?; + + println!("\nDouble-checking secret can be reconstructed from any {t} shares...\n"); + + // Write the original seed phrase to the file + let original_seed_phrase = secret.to_mnemonic(dictionary); + writeln!( + file, + "Original seed phrase:\n\"{}\"\n", + original_seed_phrase + )?; + for share in shares { assert!(share.is_valid().is_ok(), "The share is invalid"); } - for combination in (0..shares.len()).combinations(t) { - let shares = combination + + for (index, combination) in (0..shares.len()).combinations(t).enumerate() { + // Adjust share indices to start from 1 instead of 0 + let adjusted_combination: Vec<_> = combination.iter().map(|&i| i + 1).collect(); + + // Print the combination index + println!( + "Testing combination {}: {:?}", + index + 1, + adjusted_combination + ); + + let shares_subset = combination .into_iter() .map(|i| &shares[i]) .collect::>(); - let reconstructed = Bip39Secret::reconstruct(&shares); + + let reconstructed = Bip39Secret::reconstruct(&shares_subset); assert!( secret == &reconstructed, "The secret could not be reconstructed from the shares" ); + + // Write the reconstructed seed phrase to the file + let reconstructed_seed_phrase = reconstructed.to_mnemonic(dictionary); + writeln!( + file, + "Reconstructed seed phrase from combination {}:", + index + 1 + )?; + for &i in &adjusted_combination { + writeln!( + file, + " Share {}: \"{}\"", + i, + shares[i - 1].to_mnemonic(dictionary) + )?; // Adjust index back for accessing shares + } + writeln!( + file, + " Reconstructed seed phrase:\n \"{}\"\n", + reconstructed_seed_phrase + )?; } - println!(" [{}]\n", "ok".green().bold()); + + println!("\nWriting results to file: reconstructed_seed_phrases.txt\n"); + println!("[{}]\n", "ok".green().bold()); + + Ok(()) }