From 3ca43e7977946849af8cba9e2be9ab64882d2745 Mon Sep 17 00:00:00 2001 From: Frederic Jacobs Date: Sat, 2 Apr 2016 23:57:42 +0200 Subject: [PATCH] Refactoring to keep same sanitisation of shares between lib & bin. --- src/lib/custom_error.rs | 8 ++++++ src/lib/mod.rs | 50 ++++++++++++++++++++++++++++++-- src/main.rs | 64 ++++++----------------------------------- 3 files changed, 64 insertions(+), 58 deletions(-) diff --git a/src/lib/custom_error.rs b/src/lib/custom_error.rs index 3edafc5..9d15c83 100644 --- a/src/lib/custom_error.rs +++ b/src/lib/custom_error.rs @@ -4,6 +4,7 @@ pub use std::io::prelude::*; use std::error; use std::fmt; use std::io; +use std::num; #[derive(Debug)] pub struct Error { @@ -42,3 +43,10 @@ pub fn other_io_err(descr: &'static str, detail: Option) -> io::Error { Error::new(descr, detail) ) } + +/// maps a ParseIntError to an io::Error +pub fn pie2io(p: num::ParseIntError) -> io::Error { + convert::From::from( + Error::new("Integer parsing error", Some(p.to_string())) + ) +} diff --git a/src/lib/mod.rs b/src/lib/mod.rs index 5be2e3e..d0626a0 100644 --- a/src/lib/mod.rs +++ b/src/lib/mod.rs @@ -32,8 +32,54 @@ pub fn generate_shares(k: u8, n: u8, secret: Vec) -> io::Result> Ok(result) } -pub fn recover_secret(k: u8, shares: Vec<(u8,Vec)>) -> io::Result> { - assert!(!shares.is_empty()); +pub fn process_shares(shares_strings: Vec) -> io::Result<(u8, Vec<(u8,Vec)>)> { + let mut opt_k_l: Option<(u8, usize)> = None; + let mut counter = 0u8; + let mut shares: Vec<(u8,Vec)> = Vec::new(); + + for line in shares_strings { + let parts: Vec<_> = line.trim().split('-').collect(); + if parts.len() < 3 || parts.len() > 4 { + return Err(other_io_err("Share parse error: Expected 3 or 4 \ + parts separated by a minus sign", None)); + } + let (k, n, p3) = { + let mut iter = parts.into_iter(); + let k = try!(iter.next().unwrap().parse::().map_err(pie2io)); + let n = try!(iter.next().unwrap().parse::().map_err(pie2io)); + let p3 = iter.next().unwrap(); + (k, n, p3) + }; + if k < 1 || n < 1 { + return Err(other_io_err("Share parse error: Illegal K,N parameters", None)); + } + let data = try!( + p3.from_base64().map_err(|_| other_io_err( + "Share parse error: Base64 decoding of data block failed", None )) + ); + if let Some((ck, cl)) = opt_k_l { + if ck != k || cl != data.len() { + return Err(other_io_err("Incompatible shares", None)); + } + } else { + opt_k_l = Some((k, data.len())); + } + if shares.iter().all(|s| s.0 != n) { + shares.push((n, data)); + counter += 1; + if counter == k { + return Ok((k, shares)); + } + } + } + Err(other_io_err("Not enough shares provided!", None)) +} + +pub fn recover_secret(shares_strings: Vec) -> io::Result> { + assert!(!shares_strings.is_empty()); + + let (k, shares) = try!(process_shares(shares_strings)); + let slen = shares[0].1.len(); let mut col_in = Vec::with_capacity(k as usize); let mut secret = Vec::with_capacity(slen); diff --git a/src/main.rs b/src/main.rs index 1bc1fc8..caf41f4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,12 +4,10 @@ use getopts::Options; use std::str; use lib::custom_error::*; -use lib::serialize::base64::{ FromBase64 }; mod lib; use std::io; use std::env; -use std::num; enum Action { Encode(u8, u8), // k and n parameter @@ -117,58 +115,19 @@ fn perform_encode_from_io(k: u8, n: u8) -> io::Result<()> { return Ok(()) as io::Result<()>; } -/// reads shares from stdin and returns Ok(k, shares) on success -/// where shares is a Vec<(u8, Vec)> representing x-coordinates -/// and share data. -fn read_shares() -> io::Result<(u8, Vec<(u8,Vec)>)> { - let stdin = io::stdin(); +fn perform_decode_from_io() -> io::Result<()> { + let stdin = io::stdin(); let stdin = io::BufReader::new(stdin.lock()); - let mut opt_k_l: Option<(u8, usize)> = None; - let mut counter = 0u8; - let mut shares: Vec<(u8,Vec)> = Vec::new(); + let mut shares: Vec = Vec::new(); + for line in stdin.lines() { - let line = try!(line); - let parts: Vec<_> = line.trim().split('-').collect(); - if parts.len() < 3 || parts.len() > 4 { - return Err(other_io_err("Share parse error: Expected 3 or 4 \ - parts separated by a minus sign", None)); - } - let (k, n, p3) = { - let mut iter = parts.into_iter(); - let k = try!(iter.next().unwrap().parse::().map_err(pie2io)); - let n = try!(iter.next().unwrap().parse::().map_err(pie2io)); - let p3 = iter.next().unwrap(); - (k, n, p3) - }; - if k < 1 || n < 1 { - return Err(other_io_err("Share parse error: Illegal K,N parameters", None)); - } - let data = try!( - p3.from_base64().map_err(|_| other_io_err( - "Share parse error: Base64 decoding of data block failed", None )) - ); - if let Some((ck, cl)) = opt_k_l { - if ck != k || cl != data.len() { - return Err(other_io_err("Incompatible shares", None)); - } - } else { - opt_k_l = Some((k, data.len())); - } - if shares.iter().all(|s| s.0 != n) { - shares.push((n, data)); - counter += 1; - if counter == k { - return Ok((k, shares)); - } + match line { + Ok(share) => shares.push(share), + Err(_) => {} } } - Err(other_io_err("Not enough shares provided!", None)) -} -fn perform_decode_from_io() -> io::Result<()> { - let (k, shares) = try!(read_shares()); - - return match lib::recover_secret(k, shares) { + return match lib::recover_secret(shares) { Ok(secret) => { let mut out = io::stdout(); try!(out.write_all(&*secret)); @@ -187,10 +146,3 @@ fn parse_k_n(s: &str) -> io::Result<(u8, u8)> { let n = try!(s2.parse().map_err(pie2io)); Ok((k, n)) } - -/// maps a ParseIntError to an io::Error -fn pie2io(p: num::ParseIntError) -> io::Error { - convert::From::from( - Error::new("Integer parsing error", Some(p.to_string())) - ) -}