mirror of
https://github.com/mii443/RustySecrets.git
synced 2025-09-04 00:09:24 +00:00
Remove CRC-24 dependency. Closes #3
This commit is contained in:
@ -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
10
Cargo.lock
generated
@ -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]]
|
||||||
|
@ -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"
|
||||||
|
23
README.md
23
README.md
@ -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
|
||||||
|
|
||||||
|
49
src/main.rs
49
src/main.rs
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user