mirror of
https://github.com/mii443/RustySecrets.git
synced 2025-09-01 14:59:18 +00:00
add checksums to shares (CRC-24)
This commit is contained in:
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -2,10 +2,16 @@
|
|||||||
name = "secretshare"
|
name = "secretshare"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"crc24 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"getopts 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"getopts 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc24"
|
||||||
|
version = "0.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getopts"
|
name = "getopts"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -2,7 +2,11 @@
|
|||||||
name = "secretshare"
|
name = "secretshare"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
authors = ["Sebastian Gesemann <s.gesemann@gmail.com>"]
|
authors = ["Sebastian Gesemann <s.gesemann@gmail.com>"]
|
||||||
|
description = "This is an implementation of Shamir's secret sharing scheme."
|
||||||
|
license = "GPLv3"
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
getopts = "0.2.0"
|
getopts = "0.2.0"
|
||||||
rustc-serialize = "0.2.10"
|
rustc-serialize = "0.2.10"
|
||||||
|
crc24 = "0.0.2"
|
||||||
|
92
src/main.rs
92
src/main.rs
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
extern crate "rustc-serialize" as serialize;
|
extern crate "rustc-serialize" as serialize;
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
|
extern crate crc24;
|
||||||
|
|
||||||
use std::os;
|
use std::os;
|
||||||
use std::rand::{ Rng, OsRng };
|
use std::rand::{ Rng, OsRng };
|
||||||
@ -121,7 +122,14 @@ fn read_no_more_than<R: Reader>(r: &mut R, max: usize) -> IoResult<Vec<u8>> {
|
|||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perform_encode(k: u8, n: u8) -> IoResult<()> {
|
fn crc24_as_bytes(octets: &[u8]) -> [u8; 3] {
|
||||||
|
let v = crc24::hash_raw(octets);
|
||||||
|
[((v >> 16) & 0xFF) as u8,
|
||||||
|
((v >> 8) & 0xFF) as u8,
|
||||||
|
( v & 0xFF) as u8]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn perform_encode(k: u8, n: u8, with_checksums: bool) -> IoResult<()> {
|
||||||
let secret = try!(read_no_more_than(&mut stdio::stdin(), 0x10000));
|
let secret = try!(read_no_more_than(&mut stdio::stdin(), 0x10000));
|
||||||
let shares = try!(secret_share(&*secret, k, n));
|
let shares = try!(secret_share(&*secret, k, n));
|
||||||
let config = base64::Config {
|
let config = base64::Config {
|
||||||
@ -129,11 +137,26 @@ fn perform_encode(k: u8, n: u8) -> IoResult<()> {
|
|||||||
..base64::STANDARD
|
..base64::STANDARD
|
||||||
};
|
};
|
||||||
for (index, share) in shares.iter().enumerate() {
|
for (index, share) in shares.iter().enumerate() {
|
||||||
println!("{}-{}-{}", k, index+1, share.to_base64(config));
|
let salad = share.to_base64(config);
|
||||||
|
if with_checksums {
|
||||||
|
let crc_bytes = crc24_as_bytes(&**share);
|
||||||
|
println!("{}-{}-{}-{}", k, index+1, salad, crc_bytes.to_base64(config));
|
||||||
|
} else {
|
||||||
|
println!("{}-{}-{}", k, index+1, salad);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! otry {
|
||||||
|
($o:expr, $e:expr) => (
|
||||||
|
match $o {
|
||||||
|
Some(thing_) => thing_,
|
||||||
|
None => return Err(other_io_err($e))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// reads shares from stdin and returns Ok(k, shares) on success
|
/// reads shares from stdin and returns Ok(k, shares) on success
|
||||||
/// where shares is a Vec<(u8, Vec<u8>)> representing x-coordinates
|
/// where shares is a Vec<(u8, Vec<u8>)> representing x-coordinates
|
||||||
/// and share data.
|
/// and share data.
|
||||||
@ -145,36 +168,49 @@ fn read_shares() -> IoResult<(u8, Vec<(u8,Vec<u8>)>)> {
|
|||||||
for line in stdin.lines() {
|
for line in stdin.lines() {
|
||||||
let line = try!(line);
|
let line = try!(line);
|
||||||
let parts: Vec<_> = line.trim().split('-').collect();
|
let parts: Vec<_> = line.trim().split('-').collect();
|
||||||
let (k, n, raw) = match
|
if parts.len() < 3 || parts.len() > 4 {
|
||||||
Some(parts).and_then(|p| {
|
return Err(other_io_err("Share parse error: Expected 3 or 4 \
|
||||||
if p.len() != 3 { None } else { Some(p) }
|
parts searated by a minus sign"));
|
||||||
}).and_then(|p| {
|
}
|
||||||
let mut iter = p.into_iter();
|
let (k, n, p3, opt_p4) = {
|
||||||
let p1 = iter.next().unwrap().parse::<u8>();
|
let mut iter = parts.into_iter();
|
||||||
let p2 = iter.next().unwrap().parse::<u8>();
|
let msg = "Share parse error: Could not parse K,N parameters";
|
||||||
let p3 = iter.next().unwrap();
|
let k = otry!(iter.next().unwrap().parse::<u8>(), msg);
|
||||||
match (p1, p2) {
|
let n = otry!(iter.next().unwrap().parse::<u8>(), msg);
|
||||||
(Some(k), Some(n)) => Some((k,n,p3)),
|
let p3 = iter.next().unwrap();
|
||||||
_ => None
|
let opt_p4 = iter.next();
|
||||||
}
|
(k, n, p3, opt_p4)
|
||||||
}).and_then(|(k,n,text)| {
|
};
|
||||||
match text.from_base64() {
|
if k < 1 || n < 1 {
|
||||||
Ok(v) => Some((k,n,v)),
|
return Err(other_io_err("Share parse error: Illegal K,N parameters"));
|
||||||
_ => None
|
}
|
||||||
}
|
let data = try!(
|
||||||
}) {
|
p3.from_base64().map_err(|_| other_io_err(
|
||||||
None => return Err(other_io_err("Share parse error")),
|
"Share parse error: Base64 decoding of data block failed"))
|
||||||
Some(s) => s
|
);
|
||||||
};
|
if let Some(check) = opt_p4 {
|
||||||
if let Some((ck,cl)) = opt_k_l {
|
if check.len() != 4 {
|
||||||
if ck != k || cl != raw.len() {
|
return Err(other_io_err("Share parse error: Checksum part is \
|
||||||
|
expected to be four characters"));
|
||||||
|
}
|
||||||
|
let crc_bytes = try!(
|
||||||
|
check.from_base64().map_err(|_| other_io_err(
|
||||||
|
"Share parse error: Base64 decoding of checksum failed"))
|
||||||
|
);
|
||||||
|
let mychksum = crc24_as_bytes(&*data);
|
||||||
|
if mychksum != crc_bytes {
|
||||||
|
return Err(other_io_err("Share parse error: Checksum mismatch"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some((ck, cl)) = opt_k_l {
|
||||||
|
if ck != k || cl != data.len() {
|
||||||
return Err(other_io_err("Incompatible shares"));
|
return Err(other_io_err("Incompatible shares"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
opt_k_l = Some((k,raw.len()));
|
opt_k_l = Some((k, data.len()));
|
||||||
}
|
}
|
||||||
if shares.iter().all(|s| s.0 != n) {
|
if shares.iter().all(|s| s.0 != n) {
|
||||||
shares.push((n, raw));
|
shares.push((n, data));
|
||||||
counter += 1;
|
counter += 1;
|
||||||
if counter == k {
|
if counter == k {
|
||||||
return Ok((k, shares));
|
return Ok((k, shares));
|
||||||
@ -254,7 +290,7 @@ fn main() {
|
|||||||
|
|
||||||
let result =
|
let result =
|
||||||
match action {
|
match action {
|
||||||
Ok(Action::Encode(k,n)) => perform_encode(k,n),
|
Ok(Action::Encode(k,n)) => perform_encode(k, n, true),
|
||||||
Ok(Action::Decode) => perform_decode(),
|
Ok(Action::Decode) => perform_decode(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
drop(writeln!(&mut stderr, "Error: {}", e));
|
drop(writeln!(&mut stderr, "Error: {}", e));
|
||||||
|
Reference in New Issue
Block a user