mirror of
https://github.com/mii443/RustySecrets.git
synced 2025-08-22 16:25:32 +00:00
Refactoring to keep same sanitisation of shares between lib & bin.
This commit is contained in:
@ -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()))
|
||||
)
|
||||
}
|
||||
|
@ -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);
|
||||
|
62
src/main.rs
62
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<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));
|
||||
match line {
|
||||
Ok(share) => shares.push(share),
|
||||
Err(_) => {}
|
||||
}
|
||||
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))
|
||||
}
|
||||
|
||||
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()))
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user