Initial commit
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/target
|
||||||
|
**/*.rs.bk
|
||||||
|
Cargo.lock
|
||||||
|
local
|
||||||
|
.idea
|
||||||
|
*.iml
|
||||||
18
Cargo.toml
Normal file
18
Cargo.toml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[package]
|
||||||
|
name = "rssss"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["TQ Hirsch <thequux@thequux.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
num-bigint = {version = "0.2.2", features = ["rand", "serde"]}
|
||||||
|
lazy_static = "1.2.0"
|
||||||
|
structopt = "0.2.14"
|
||||||
|
failure = "0.1.5"
|
||||||
|
crc = "1.8.1"
|
||||||
|
byteorder = "1.3.1"
|
||||||
|
num-traits = "0.2.6"
|
||||||
|
rand = "0.6.5"
|
||||||
|
serde = "1.0.87"
|
||||||
|
serde_derive = "1.0.87"
|
||||||
|
serde_cbor = "0.9.0"
|
||||||
8
src/lib.rs
Normal file
8
src/lib.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use num_bigint::BigUint;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
pub mod primes;
|
||||||
|
pub mod poly;
|
||||||
|
pub mod s4;
|
||||||
|
|
||||||
|
|
||||||
187
src/main.rs
Normal file
187
src/main.rs
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
use structopt::StructOpt;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use failure::Error;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Rust implementation of Shamir Secret Sharing
|
||||||
|
///
|
||||||
|
/// Securely divides a small amount of data into shares, some subset of which are required
|
||||||
|
/// to reproduce the original data
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
///
|
||||||
|
/// Generating shares:
|
||||||
|
///
|
||||||
|
/// # Precompute data for secret sharing requiring 2 shares to reconsitute the data
|
||||||
|
///
|
||||||
|
/// rssss gen-poly 2 <secret >poly
|
||||||
|
///
|
||||||
|
/// # Generate a few shares
|
||||||
|
///
|
||||||
|
/// rssss gen-share <poly >share-1
|
||||||
|
///
|
||||||
|
/// rssss gen-share <poly >share-2
|
||||||
|
///
|
||||||
|
/// rssss gen-share <poly >share-3
|
||||||
|
///
|
||||||
|
/// rssss gen-share <poly >share-4
|
||||||
|
///
|
||||||
|
/// # Recover the poly from two of those shares
|
||||||
|
///
|
||||||
|
/// rssss solve share-2 share-4 >recovered-poly
|
||||||
|
///
|
||||||
|
/// # Generate some more shares from that poly
|
||||||
|
///
|
||||||
|
/// rssss gen-share <recovered-poly >share-5
|
||||||
|
///
|
||||||
|
/// # Get the secret back
|
||||||
|
///
|
||||||
|
/// rssss extract <recovered-poly >recovered-secret
|
||||||
|
#[derive(StructOpt)]
|
||||||
|
enum Cmdline {
|
||||||
|
/// Generate a poly from a secret
|
||||||
|
#[structopt(name = "gen-poly")]
|
||||||
|
GenPoly(GenPoly),
|
||||||
|
|
||||||
|
/// Generate a share from a poly
|
||||||
|
#[structopt(name = "gen-share")]
|
||||||
|
GenShare(GenShare),
|
||||||
|
|
||||||
|
/// Solve a set of shares to get the poly back
|
||||||
|
#[structopt(name = "solve")]
|
||||||
|
Solve(Solve),
|
||||||
|
|
||||||
|
/// Combine a set of shares to get the secret back
|
||||||
|
#[structopt(name = "combine")]
|
||||||
|
Combine(Combine),
|
||||||
|
|
||||||
|
/// Extract a secret from a poly
|
||||||
|
#[structopt(name="extract")]
|
||||||
|
ExtractSecret(ExtractSecret),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(StructOpt)]
|
||||||
|
struct GenPoly {
|
||||||
|
#[structopt(short="p", long="prime", default_value="p384", parse(try_from_str))]
|
||||||
|
prime: rssss::primes::Prime,
|
||||||
|
|
||||||
|
min_shares: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(StructOpt)]
|
||||||
|
struct GenShare {
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(StructOpt)]
|
||||||
|
struct Solve {
|
||||||
|
#[structopt(short="p", long="prime", default_value="p384", parse(try_from_str))]
|
||||||
|
prime: rssss::primes::Prime,
|
||||||
|
#[structopt(parse(from_os_str))]
|
||||||
|
data: Vec<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extract a secret
|
||||||
|
#[derive(StructOpt)]
|
||||||
|
struct ExtractSecret {
|
||||||
|
#[structopt(short="p", long="prime", default_value="p384", parse(try_from_str))]
|
||||||
|
prime: rssss::primes::Prime,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Combine a set of shares to find the secret
|
||||||
|
/// This is equivalent to solve followed by extract, but without the intermediate step
|
||||||
|
#[derive(StructOpt)]
|
||||||
|
struct Combine {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let cmdline = Cmdline::from_args();
|
||||||
|
let cmd: &Command = match cmdline {
|
||||||
|
Cmdline::GenPoly(ref cmd) => cmd,
|
||||||
|
Cmdline::GenShare(ref cmd) => cmd,
|
||||||
|
Cmdline::Solve(ref cmd) => cmd,
|
||||||
|
Cmdline::ExtractSecret(ref cmd) => cmd,
|
||||||
|
Cmdline::Combine(ref cmd) => cmd,
|
||||||
|
};
|
||||||
|
|
||||||
|
cmd.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Command {
|
||||||
|
fn run(&self) -> Result<(), Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for GenPoly {
|
||||||
|
fn run(&self) -> Result<(), Error> {
|
||||||
|
use std::io::Read;
|
||||||
|
use num_bigint::{RandBigInt, BigUint};
|
||||||
|
|
||||||
|
let mut rng = rand::rngs::JitterRng::new()?;
|
||||||
|
|
||||||
|
let mut payload = vec![];
|
||||||
|
io::stdin().read_to_end(&mut payload)?;
|
||||||
|
|
||||||
|
let secret = rssss::s4::Secret::new(payload);
|
||||||
|
let mut poly = rssss::poly::Poly::zero(self.prime);
|
||||||
|
for i in 1..self.min_shares {
|
||||||
|
poly += rng.gen_biguint_below(self.prime.modulus());
|
||||||
|
poly.mul_x();
|
||||||
|
}
|
||||||
|
poly += &BigUint::from(secret);
|
||||||
|
|
||||||
|
// export the poly
|
||||||
|
serde_cbor::to_writer(&mut io::stdout(), &poly)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for GenShare {
|
||||||
|
fn run(&self) -> Result<(), Error> {
|
||||||
|
let mut poly: rssss::poly::Poly = serde_cbor::from_reader(io::stdin())?;
|
||||||
|
let mut rng = rand::rngs::JitterRng::new()?;
|
||||||
|
|
||||||
|
let share = rssss::s4::Share::new(&mut rng, &poly);
|
||||||
|
share.write_to(io::stdout())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for Solve {
|
||||||
|
fn run(&self) -> Result<(), Error> {
|
||||||
|
use std::fs::File;
|
||||||
|
let shares = self.data.iter().map(|filename| {
|
||||||
|
Ok(File::open(&filename)
|
||||||
|
.and_then(|f| rssss::s4::Share::read_from(f, self.prime))
|
||||||
|
.map_err(|err| Error::from(err)
|
||||||
|
.context(format!("Failed to read {:?}", filename)))?)
|
||||||
|
}).collect::<Result<Vec<rssss::s4::Share>, Error>>();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for ExtractSecret {
|
||||||
|
fn run(&self) -> Result<(), Error> {
|
||||||
|
use num_bigint::BigUint;
|
||||||
|
use num_traits::Zero;
|
||||||
|
use std::io::Write;
|
||||||
|
let mut poly: rssss::poly::Poly = serde_cbor::from_reader(io::stdin())?;
|
||||||
|
let secret = rssss::s4::Secret::from(poly.eval_at(&BigUint::zero()));
|
||||||
|
io::stdout().write_all(&secret[..])?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command for Combine {
|
||||||
|
fn run(&self) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Impl
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
182
src/poly.rs
Normal file
182
src/poly.rs
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
use std::io::{self, prelude::*};
|
||||||
|
use std::ops::{Mul, Div, Add, AddAssign, DivAssign, Neg};
|
||||||
|
|
||||||
|
use num_bigint::BigUint;
|
||||||
|
use num_traits::{Zero, One};
|
||||||
|
use serde_derive::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
use crate::primes::Prime;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Poly {
|
||||||
|
// coeff[0] + coeff[1]*x + coeff[2] * x^2
|
||||||
|
// i.e., $$\sum_i coeff_i x^i$$
|
||||||
|
pub prime: Prime,
|
||||||
|
coeff: Vec<BigUint>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Poly {
|
||||||
|
pub fn zero(modulus: Prime) -> Self {
|
||||||
|
Poly {
|
||||||
|
prime: modulus,
|
||||||
|
coeff: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn x(modulus: Prime) -> Self {
|
||||||
|
Poly {
|
||||||
|
prime: modulus,
|
||||||
|
coeff: vec![BigUint::zero(), BigUint::one()],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mul_x(&mut self) {
|
||||||
|
self.coeff.insert(0, BigUint::zero());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eval_at(&self, point: &BigUint) -> BigUint {
|
||||||
|
let mut result: BigUint = BigUint::zero();
|
||||||
|
for item in self.coeff.iter().rev() {
|
||||||
|
result *= point;
|
||||||
|
result += item;
|
||||||
|
result %= self.prime.modulus();
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add<&Poly> for Poly {
|
||||||
|
type Output = Poly;
|
||||||
|
|
||||||
|
fn add(self, rhs: &Poly) -> Self::Output {
|
||||||
|
let mut res = self.clone();
|
||||||
|
res += rhs;
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign<&Poly> for Poly {
|
||||||
|
fn add_assign(&mut self, rhs: &Poly) {
|
||||||
|
assert_eq!(self.prime, rhs.prime);
|
||||||
|
if self.coeff.len() < rhs.coeff.len() {
|
||||||
|
self.coeff.extend(::std::iter::repeat(BigUint::zero()).take(rhs.coeff.len() - self.coeff.len()));
|
||||||
|
}
|
||||||
|
for (a, b) in self.coeff.iter_mut().zip(rhs.coeff.iter()) {
|
||||||
|
*a += b;
|
||||||
|
*a %= self.prime.modulus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add<&BigUint> for Poly {
|
||||||
|
type Output = Poly;
|
||||||
|
|
||||||
|
fn add(mut self, rhs: &BigUint) -> Self::Output {
|
||||||
|
self += rhs;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign<&BigUint> for Poly {
|
||||||
|
fn add_assign(&mut self, rhs: &BigUint) {
|
||||||
|
if self.coeff.len() == 0 {
|
||||||
|
self.coeff.push(rhs % self.prime.modulus())
|
||||||
|
} else {
|
||||||
|
self.coeff[0] += rhs;
|
||||||
|
self.coeff[0] %= self.prime.modulus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add<BigUint> for Poly {
|
||||||
|
type Output = Poly;
|
||||||
|
|
||||||
|
fn add(mut self, rhs: BigUint) -> Self::Output {
|
||||||
|
self += rhs;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign<BigUint> for Poly {
|
||||||
|
fn add_assign(&mut self, rhs: BigUint) {
|
||||||
|
if self.coeff.len() == 0 {
|
||||||
|
self.coeff.push(rhs % self.prime.modulus())
|
||||||
|
} else {
|
||||||
|
self.coeff[0] += rhs;
|
||||||
|
self.coeff[0] %= self.prime.modulus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<&BigUint> for Poly {
|
||||||
|
type Output = Poly;
|
||||||
|
fn mul(mut self, rhs: &BigUint) -> Poly {
|
||||||
|
for a in self.coeff.iter_mut() {
|
||||||
|
*a *= rhs;
|
||||||
|
*a %= self.prime.modulus();
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<&BigUint> for &Poly {
|
||||||
|
type Output = Poly;
|
||||||
|
fn mul(mut self, rhs: &BigUint) -> Poly {
|
||||||
|
Poly {
|
||||||
|
prime: self.prime,
|
||||||
|
coeff: self.coeff.iter().map(|a| (a * rhs) % self.prime.modulus()).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<&Poly> for Poly {
|
||||||
|
type Output = Poly;
|
||||||
|
|
||||||
|
fn mul(mut self, rhs: &Poly) -> Self::Output {
|
||||||
|
let mut result = Poly::zero(self.prime);
|
||||||
|
for factor in rhs.coeff.iter() {
|
||||||
|
result += &(&self * factor);
|
||||||
|
self.mul_x();
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<&Poly> for &Poly {
|
||||||
|
type Output = Poly;
|
||||||
|
|
||||||
|
fn mul(self, rhs: &Poly) -> Self::Output {
|
||||||
|
self.clone() * rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Div<BigUint> for Poly {
|
||||||
|
type Output = Poly;
|
||||||
|
|
||||||
|
fn div(mut self, rhs: BigUint) -> Poly {
|
||||||
|
self /= rhs;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DivAssign<BigUint> for Poly {
|
||||||
|
fn div_assign(&mut self, rhs: BigUint) {
|
||||||
|
let inv = self.prime.inverse(rhs);
|
||||||
|
for a in self.coeff.iter_mut() {
|
||||||
|
*a *= &inv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Neg for Poly {
|
||||||
|
type Output = Poly;
|
||||||
|
|
||||||
|
fn neg(mut self) -> Self::Output {
|
||||||
|
for a in self.coeff.iter_mut() {
|
||||||
|
*a = self.prime.negate(&*a);
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
116
src/primes.rs
Normal file
116
src/primes.rs
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use num_bigint::BigUint;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use num_traits::identities::{Zero, One};
|
||||||
|
|
||||||
|
use serde_derive::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
lazy_static!{
|
||||||
|
// 2^384 - 2^128 - 2^96 + 2^32 - 1
|
||||||
|
// Chosen to be large enough to hold any AES key
|
||||||
|
static ref PRIME_P384: BigUint = BigUint::new(vec![
|
||||||
|
0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFE,
|
||||||
|
0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||||
|
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||||
|
]);
|
||||||
|
|
||||||
|
static ref PRIME_P448: BigUint = BigUint::new(vec![
|
||||||
|
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||||
|
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE,
|
||||||
|
0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
|
||||||
|
0xFFFFFFFE, 0xFFFFFFFF,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||||
|
pub enum Prime {
|
||||||
|
// 2^384 - 2^128 - 2^96 + 2^32 - 1
|
||||||
|
P384,
|
||||||
|
// 2^448 - 2^224 - 1
|
||||||
|
P448,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Prime {
|
||||||
|
pub fn to_id(self) -> u8 {
|
||||||
|
match self {
|
||||||
|
Prime::P384 => 1,
|
||||||
|
Prime::P448 => 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn byte_size(self) -> usize {
|
||||||
|
match self {
|
||||||
|
Prime::P448 => 56,
|
||||||
|
Prime::P384 => 48,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn modulus(self) -> &'static BigUint {
|
||||||
|
match self {
|
||||||
|
Prime::P384 => &PRIME_P384,
|
||||||
|
Prime::P448 => &PRIME_P448,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inverse(self, value: BigUint) -> BigUint {
|
||||||
|
ext_gcd(value, self.modulus().clone()).0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn negate(self, value: &BigUint) -> BigUint {
|
||||||
|
self.modulus() - value
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Prime {
|
||||||
|
type Err = failure::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s.to_lowercase().as_str() {
|
||||||
|
"p384" => Ok(Prime::P384),
|
||||||
|
"p448" => Ok(Prime::P448),
|
||||||
|
_ => Err(failure::err_msg("Invalid prime spec; expected P384 or P448")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ext_gcd(mut a: BigUint, mut b: BigUint) -> (BigUint, BigUint) {
|
||||||
|
use std::mem::swap;
|
||||||
|
let mut x = BigUint::zero();
|
||||||
|
let mut last_x = BigUint::one();
|
||||||
|
let mut y = BigUint::one();
|
||||||
|
let mut last_y = BigUint::zero();
|
||||||
|
|
||||||
|
while !b.is_zero() {
|
||||||
|
let quot = &a / &b;
|
||||||
|
swap(&mut a, &mut b);
|
||||||
|
b %= &a;
|
||||||
|
swap(&mut x, &mut last_x);
|
||||||
|
swap(&mut y, &mut last_y);
|
||||||
|
|
||||||
|
|
||||||
|
last_x *= "
|
||||||
|
x -= &last_x;
|
||||||
|
|
||||||
|
last_y *= quot;
|
||||||
|
y -= &last_y;
|
||||||
|
}
|
||||||
|
(last_x, last_y)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use num_bigint::BigUint;
|
||||||
|
use super::Prime;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_value_of_p384() {
|
||||||
|
let one = &BigUint::new(vec![1]);
|
||||||
|
assert_eq!(Prime::P384::modulus, one << 384 - one - one << 128 - one << 96 - one << 32);
|
||||||
|
}
|
||||||
|
fn check_value_of_p448() {
|
||||||
|
let one = &BigUint::new(vec![1]);
|
||||||
|
assert_eq!(Prime::P448::modulus, one << 448 - one - one << 224);
|
||||||
|
}
|
||||||
|
}
|
||||||
138
src/s4.rs
Normal file
138
src/s4.rs
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
use std::io::{self, prelude::*};
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
|
||||||
|
use num_bigint::BigUint;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
/// Structure
|
||||||
|
/// | off | len | meaning |
|
||||||
|
/// | 0 | 1 | Length of payload (L)
|
||||||
|
/// | 1 | L | Payload
|
||||||
|
/// | L+1 | 4 | CRC32c
|
||||||
|
/// Note that these bytes are interpreted in big-endian form to get a field element;
|
||||||
|
/// this way, the high bit is always unset
|
||||||
|
#[derive(Default,Clone, Debug)]
|
||||||
|
pub struct Secret {
|
||||||
|
length: u8,
|
||||||
|
data: Vec<u8>,
|
||||||
|
crc32: u32,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Secret {
|
||||||
|
pub fn new(data: Vec<u8>) -> Self {
|
||||||
|
if data.len() == 0 {
|
||||||
|
panic!("Must have at least one byte of payload");
|
||||||
|
} else if data.len() > 127 {
|
||||||
|
panic!("Too much data");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut res = Secret {
|
||||||
|
length: data.len() as u8,
|
||||||
|
data,
|
||||||
|
crc32: 0,
|
||||||
|
};
|
||||||
|
res.crc32 = res.compute_crc();
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_crc(&self) -> u32 {
|
||||||
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
|
use crc::crc32::{CASTAGNOLI, Digest, Hasher32};
|
||||||
|
let mut hasher = Digest::new(CASTAGNOLI);
|
||||||
|
hasher.reset();
|
||||||
|
hasher.write(&[self.length]);
|
||||||
|
hasher.write(&self.data[..]);
|
||||||
|
hasher.write(&[0, 0, 0, 0]);
|
||||||
|
hasher.sum32()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_crc(&self) -> bool {
|
||||||
|
let crc = self.compute_crc();
|
||||||
|
crc == self.crc32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Secret {
|
||||||
|
type Target = Vec<u8>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BigUint> for Secret {
|
||||||
|
fn from(ui: BigUint) -> Self {
|
||||||
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
|
let decoded = ui.to_bytes_be();
|
||||||
|
let mut res = Secret::default();
|
||||||
|
res.length = decoded[0];
|
||||||
|
let len = res.length as usize;
|
||||||
|
res.data = decoded[1..len+1].to_owned();
|
||||||
|
res.crc32 = BigEndian::read_u32(&decoded[len+1..len+5]);
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Secret> for BigUint {
|
||||||
|
fn from(obj: Secret) -> BigUint {
|
||||||
|
use std::io::Write;
|
||||||
|
use byteorder::{WriteBytesExt, BigEndian};
|
||||||
|
let mut buf = vec![];
|
||||||
|
buf.write(&[obj.length]);
|
||||||
|
buf.write(&obj.data[..]);
|
||||||
|
buf.write_u32::<BigEndian>(obj.crc32);
|
||||||
|
BigUint::from_bytes_be(&buf[..])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
pub struct Share {
|
||||||
|
pub prime: crate::primes::Prime,
|
||||||
|
pub x: BigUint,
|
||||||
|
pub y: BigUint,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Share {
|
||||||
|
pub fn new<Rng: num_bigint::RandBigInt + ?Sized>(rnd: &mut Rng, poly: &crate::poly::Poly) -> Self {
|
||||||
|
use num_bigint::RandBigInt;
|
||||||
|
let x = rnd.gen_biguint_below(poly.prime.modulus());
|
||||||
|
let y = poly.eval_at(&x);
|
||||||
|
Share {
|
||||||
|
prime: poly.prime,
|
||||||
|
x, y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_to<W: Write>(&self, mut w: W) -> io::Result<()> {
|
||||||
|
let mut x = self.x.to_bytes_le();
|
||||||
|
x.resize(self.prime.byte_size(), 0);
|
||||||
|
let mut y = self.y.to_bytes_le();
|
||||||
|
y.resize(self.prime.byte_size(), 0);
|
||||||
|
|
||||||
|
(&mut w).write_all(&x[..])?;
|
||||||
|
(&mut w).write_all(&y[..])?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_from<R: Read>(mut r: R, prime: crate::primes::Prime) -> io::Result<Self> {
|
||||||
|
let size = prime.byte_size();
|
||||||
|
let mut x = vec![0; size];
|
||||||
|
(&mut r).read_exact(&mut x[..])?;
|
||||||
|
let mut x = BigUint::from_bytes_le(&x[..]);
|
||||||
|
|
||||||
|
let mut y = vec![0; size];
|
||||||
|
(&mut r).read_exact(&mut y[..])?;
|
||||||
|
let mut y = BigUint::from_bytes_le(&y[..]);
|
||||||
|
|
||||||
|
if &x >= prime.modulus() || &y >= prime.modulus() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid point: out of range"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Share{ prime, x, y })
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user