Remove CRC-24 dependency. Closes #3

This commit is contained in:
Frederic Jacobs
2016-04-02 11:00:52 +02:00
parent f1ad2b74f1
commit 16be20fcff
5 changed files with 18 additions and 73 deletions

View File

@ -1,8 +0,0 @@
2015-02-03:
* I changed the CRC-24 checksum computation to include the coding parameter
K and the share number N so that these numbers are also protected.
If you have older shares generated with a previous version, you can still
decode the secret by simply removing the checksum part of the shares.
* The README now includes more information about the inner workings of
secretshare and also a note on "perfect secrecy".

10
Cargo.lock generated
View File

@ -2,17 +2,11 @@
name = "secretshare" name = "secretshare"
version = "0.1.6" version = "0.1.6"
dependencies = [ dependencies = [
"crc24 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "crc24"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "getopts" name = "getopts"
version = "0.2.14" version = "0.2.14"
@ -20,7 +14,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.8" version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -28,7 +22,7 @@ name = "rand"
version = "0.3.14" version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]

View File

@ -9,5 +9,4 @@ readme = "README.md"
[dependencies] [dependencies]
getopts = "^0.2.14" getopts = "^0.2.14"
rustc-serialize = "^0.3.18" rustc-serialize = "^0.3.18"
crc24 = "^0.1.6"
rand = "^0.3.14" rand = "^0.3.14"

View File

@ -17,11 +17,11 @@ Passing a secret to secretshare for encoding:
``` ```
$ echo My secret | ./secretshare -e2,5 $ echo My secret | ./secretshare -e2,5
2-1-1YAYwmOHqZ69jA-v+mz 2-1-1YAYwmOHqZ69jA
2-2-YJZQDGm22Y77Gw-IhSh 2-2-YJZQDGm22Y77Gw
2-3-+G9ovW9SAnUynQ-Elwi 2-3-+G9ovW9SAnUynQ
2-4-F7rAjX3UOa53KA-b2vm 2-4-F7rAjX3UOa53KA
2-5-j0P4PHsw4lW+rg-XyNl 2-5-j0P4PHsw4lW+rg
``` ```
The parameters following the `-e` option tell `secretshare` to create 5 shares of which 2 will be necessary for decoding. The parameters following the `-e` option tell `secretshare` to create 5 shares of which 2 will be necessary for decoding.
@ -29,7 +29,7 @@ The parameters following the `-e` option tell `secretshare` to create 5 shares o
Decoding a subset of shares (one share per line) can be done like this: Decoding a subset of shares (one share per line) can be done like this:
``` ```
$ echo -e "2-2-YJZQDGm22Y77Gw-IhSh \n 2-4-F7rAjX3UOa53KA-b2vm" | ./secretshare -d $ echo -e "2-2-YJZQDGm22Y77Gw \n 2-4-F7rAjX3UOa53KA" | ./secretshare -d
My secret My secret
``` ```
@ -62,9 +62,9 @@ The generated shares are lines of ASCII text.
# Structure of the shares # Structure of the shares
``` ```
2-1-LiTyeXwEP71IUA-Qj6n 2-1-LiTyeXwEP71IUA
^ ^ ^^^^^^^^^^^^^^ ^^^^ ^ ^ ^^^^^^^^^^^^^^
K N D C K N D
``` ```
A share is built out of three or four parts separated with a minus: K-N-D-C. A share is built out of three or four parts separated with a minus: K-N-D-C.
@ -73,10 +73,7 @@ how many distinct
shares of a specific secret are necessary to be able to recover the shares of a specific secret are necessary to be able to recover the
secret. The number N identifies the share (ranging from 1 to the number secret. The number N identifies the share (ranging from 1 to the number
of shares that have been created). The D part is a Base64 encoding of of shares that have been created). The D part is a Base64 encoding of
a specific share's raw data. The optional part C is a Base64 encoding a specific share's raw data.
of a CRC-24 checksum of the concatenation of K and N as bytes followed
by the share's raw data (before Base64 encoding). The same checksum
algorithm is used in the OpenPGP format for “ASCII amoring”.
# A word on the secrecy # A word on the secrecy

View File

@ -1,6 +1,5 @@
extern crate rustc_serialize as serialize; extern crate rustc_serialize as serialize;
extern crate getopts; extern crate getopts;
extern crate crc24;
extern crate rand; extern crate rand;
use std::convert; use std::convert;
@ -154,22 +153,7 @@ fn parse_k_n(s: &str) -> io::Result<(u8, u8)> {
Ok((k, n)) Ok((k, n))
} }
/// computes a CRC-24 hash over the concatenated coding parameters k, n fn perform_encode(k: u8, n: u8) -> io::Result<()> {
/// and the raw share data
fn crc24_as_bytes(k: u8, n: u8, octets: &[u8]) -> [u8; 3] {
use std::hash::Hasher;
let mut h = crc24::Crc24Hasher::new();
h.write(&[k, n]);
h.write(octets);
let v = h.finish();
[((v >> 16) & 0xFF) as u8,
((v >> 8) & 0xFF) as u8,
( v & 0xFF) as u8]
}
fn perform_encode(k: u8, n: u8, with_checksums: bool) -> io::Result<()> {
let secret = { let secret = {
let limit: usize = 0x10000; let limit: usize = 0x10000;
let stdin = io::stdin(); let stdin = io::stdin();
@ -192,12 +176,7 @@ fn perform_encode(k: u8, n: u8, with_checksums: bool) -> io::Result<()> {
}; };
for (index, share) in shares.iter().enumerate() { for (index, share) in shares.iter().enumerate() {
let salad = share.to_base64(config); let salad = share.to_base64(config);
if with_checksums { println!("{}-{}-{}", k, index+1, salad);
let crc_bytes = crc24_as_bytes(k, (index+1) as u8, &**share);
println!("{}-{}-{}-{}", k, index+1, salad, crc_bytes.to_base64(config));
} else {
println!("{}-{}-{}", k, index+1, salad);
}
} }
Ok(()) Ok(())
} }
@ -218,13 +197,12 @@ fn read_shares() -> io::Result<(u8, Vec<(u8,Vec<u8>)>)> {
return Err(other_io_err("Share parse error: Expected 3 or 4 \ return Err(other_io_err("Share parse error: Expected 3 or 4 \
parts searated by a minus sign", None)); parts searated by a minus sign", None));
} }
let (k, n, p3, opt_p4) = { let (k, n, p3) = {
let mut iter = parts.into_iter(); let mut iter = parts.into_iter();
let k = try!(iter.next().unwrap().parse::<u8>().map_err(pie2io)); let k = try!(iter.next().unwrap().parse::<u8>().map_err(pie2io));
let n = 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(); let p3 = iter.next().unwrap();
let opt_p4 = iter.next(); (k, n, p3)
(k, n, p3, opt_p4)
}; };
if k < 1 || n < 1 { if k < 1 || n < 1 {
return Err(other_io_err("Share parse error: Illegal K,N parameters", None)); return Err(other_io_err("Share parse error: Illegal K,N parameters", None));
@ -233,20 +211,6 @@ fn read_shares() -> io::Result<(u8, Vec<(u8,Vec<u8>)>)> {
p3.from_base64().map_err(|_| other_io_err( p3.from_base64().map_err(|_| other_io_err(
"Share parse error: Base64 decoding of data block failed", None )) "Share parse error: Base64 decoding of data block failed", None ))
); );
if let Some(check) = opt_p4 {
if check.len() != 4 {
return Err(other_io_err("Share parse error: Checksum part is \
expected to be four characters", None));
}
let crc_bytes = try!(
check.from_base64().map_err(|_| other_io_err(
"Share parse error: Base64 decoding of checksum failed", None))
);
let mychksum = crc24_as_bytes(k, n, &*data);
if crc_bytes != mychksum {
return Err(other_io_err("Share parse error: Checksum mismatch", None));
}
}
if let Some((ck, cl)) = opt_k_l { if let Some((ck, cl)) = opt_k_l {
if ck != k || cl != data.len() { if ck != k || cl != data.len() {
return Err(other_io_err("Incompatible shares", None)); return Err(other_io_err("Incompatible shares", None));
@ -311,7 +275,7 @@ fn main() {
return; return;
} }
let action: Result<_,_> = let action: Result<_,_> =
match (opt_matches.opt_present("e"), opt_matches.opt_present("d")) { match (opt_matches.opt_present("e"), opt_matches.opt_present("d")) {
(false, false) => Err("Nothing to do! Use -e or -d"), (false, false) => Err("Nothing to do! Use -e or -d"),
(true, true) => Err("Use either -e or -d and not both"), (true, true) => Err("Use either -e or -d and not both"),
@ -335,7 +299,7 @@ fn main() {
let result = let result =
match action { match action {
Ok(Action::Encode(k,n)) => perform_encode(k, n, true), Ok(Action::Encode(k,n)) => perform_encode(k, n),
Ok(Action::Decode) => perform_decode(), Ok(Action::Decode) => perform_decode(),
Err(e) => Err(other_io_err(e, None)) Err(e) => Err(other_io_err(e, None))
}; };
@ -345,4 +309,3 @@ fn main() {
// env::set_exit_status(1); // FIXME: unstable feature // env::set_exit_status(1); // FIXME: unstable feature
} }
} }