Refactoring to keep same sanitisation of shares between lib & bin.

This commit is contained in:
Frederic Jacobs
2016-04-02 23:57:42 +02:00
parent da01e4e450
commit 3ca43e7977
3 changed files with 64 additions and 58 deletions

View File

@ -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<String>) -> 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()))
)
}

View File

@ -32,8 +32,54 @@ pub fn generate_shares(k: u8, n: u8, secret: Vec<u8>) -> io::Result<Vec<Vec<u8>>
Ok(result)
}
pub fn recover_secret(k: u8, shares: Vec<(u8,Vec<u8>)>) -> io::Result<Vec<u8>> {
assert!(!shares.is_empty());
pub fn process_shares(shares_strings: Vec<String>) -> io::Result<(u8, Vec<(u8,Vec<u8>)>)> {
let mut opt_k_l: Option<(u8, usize)> = None;
let mut counter = 0u8;
let mut shares: Vec<(u8,Vec<u8>)> = 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::<u8>().map_err(pie2io));
let n = try!(iter.next().unwrap().parse::<u8>().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<String>) -> io::Result<Vec<u8>> {
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);

View File

@ -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<u8>)> representing x-coordinates
/// and share data.
fn read_shares() -> io::Result<(u8, Vec<(u8,Vec<u8>)>)> {
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<u8>)> = Vec::new();
let mut shares: Vec<String> = 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::<u8>().map_err(pie2io));
let n = try!(iter.next().unwrap().parse::<u8>().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()))
)
}