Add support for custom RNGs in SSS and WrappedSecrets (#64)

This commit is contained in:
Eyal Kalderon
2018-05-04 16:52:41 +08:00
committed by Romain Ruetschi
parent e84ff133bd
commit f83ef1b2b6
5 changed files with 103 additions and 10 deletions

View File

@ -39,6 +39,7 @@ default-features = false
itertools = "^0.7"
quickcheck = "^0.4"
flate2 = "^0.2"
rand = "^0.4.2"
[profile.bench]
opt-level = 3

View File

@ -13,11 +13,14 @@ pub(crate) use self::scheme::*;
mod encode;
use rand::{OsRng, Rng};
use ring::digest::{Algorithm, SHA512};
static HASH_ALGO: &'static Algorithm = &SHA512;
/// Performs threshold k-out-of-n Shamir's secret sharing.
///
/// Uses a `rand::OsRng` as a source of entropy.
///
/// # Examples
///
/// ```
@ -37,7 +40,38 @@ static HASH_ALGO: &'static Algorithm = &SHA512;
/// ```
pub fn split_secret(k: u8, n: u8, secret: &[u8], sign_shares: bool) -> Result<Vec<String>> {
SSS::default()
.split_secret(k, n, secret, sign_shares)
.split_secret(&mut OsRng::new()?, k, n, secret, sign_shares)
.map(|shares| shares.into_iter().map(Share::into_string).collect())
}
/// Performs threshold k-out-of-n Shamir's secret sharing with a custom RNG.
///
/// # Examples
///
/// ```
/// use rusty_secrets::sss::split_secret;
///
/// let secret = "These programs were never about terrorism: theyre about economic spying, \
/// social control, and diplomatic manipulation. Theyre about power.";
///
/// match split_secret(7, 10, &secret.as_bytes(), true) {
/// Ok(shares) => {
/// // Do something with the shares
/// },
/// Err(_) => {
/// // Deal with error
/// }
/// }
/// ```
pub fn split_secret_rng<R: Rng>(
rng: &mut R,
k: u8,
n: u8,
secret: &[u8],
sign_shares: bool,
) -> Result<Vec<String>> {
SSS::default()
.split_secret(rng, k, n, secret, sign_shares)
.map(|shares| shares.into_iter().map(Share::into_string).collect())
}

View File

@ -1,7 +1,7 @@
//! SSS provides Shamir's secret sharing with raw data.
use merkle_sigs::sign_data_vec;
use rand::{OsRng, Rng};
use rand::Rng;
use errors::*;
use lagrange::interpolate_at;
@ -17,15 +17,16 @@ pub(crate) struct SSS;
impl SSS {
/// Performs threshold k-out-of-n Shamir's secret sharing.
pub fn split_secret(
pub fn split_secret<R: Rng>(
&self,
rng: &mut R,
threshold: u8,
shares_count: u8,
secret: &[u8],
sign_shares: bool,
) -> Result<Vec<Share>> {
let (threshold, shares_count) = validate_share_count(threshold, shares_count)?;
let shares = Self::secret_share(secret, threshold, shares_count)?;
let shares = Self::secret_share(rng, secret, threshold, shares_count)?;
let signatures = if sign_shares {
let shares_to_sign = shares
@ -67,19 +68,23 @@ impl SSS {
Ok(result.collect())
}
fn secret_share(src: &[u8], threshold: u8, shares_count: u8) -> Result<Vec<Vec<u8>>> {
fn secret_share<R: Rng>(
rng: &mut R,
src: &[u8],
threshold: u8,
shares_count: u8,
) -> Result<Vec<Vec<u8>>> {
let mut result = Vec::with_capacity(shares_count as usize);
for _ in 0..(shares_count as usize) {
result.push(vec![0u8; src.len()]);
}
let mut col_in = vec![0u8; threshold as usize];
let mut col_out = Vec::with_capacity(shares_count as usize);
let mut osrng = OsRng::new()?;
for (c, &s) in src.iter().enumerate() {
col_in[0] = s;
// NOTE: switch to `try_fill_bytes` when it lands in a stable release:
// https://github.com/rust-lang-nursery/rand/commit/230b2258dbd99ff8bd991008c972d923d4b5d10c
osrng.fill_bytes(&mut col_in[1..]);
rng.fill_bytes(&mut col_in[1..]);
col_out.clear();
encode_secret_byte(&*col_in, shares_count, &mut col_out)?;
for (&y, share) in col_out.iter().zip(result.iter_mut()) {

View File

@ -3,11 +3,15 @@
use errors::*;
use proto::wrapped::SecretProto;
use rand::{OsRng, Rng};
mod scheme;
pub(crate) use self::scheme::*;
/// Performs threshold k-out-of-n Shamir's secret sharing.
///
/// Uses an `OsRng` as a source of entropy.
///
/// # Examples
///
/// ```
@ -41,7 +45,54 @@ pub fn split_secret(
sign_shares: bool,
) -> Result<Vec<String>> {
WrappedSecrets::default()
.split_secret(k, n, secret, mime_type, sign_shares)
.split_secret(&mut OsRng::new()?, k, n, secret, mime_type, sign_shares)
.map(|shares| shares.into_iter().map(Share::into_string).collect())
}
/// Performs threshold k-out-of-n Shamir's secret sharing with a custom RNG.
///
/// # Examples
///
/// ```
/// # extern crate rusty_secrets;
/// # extern crate rand;
/// #
/// # fn main() {
/// use rusty_secrets::wrapped_secrets::split_secret_rng;
/// use rand::ChaChaRng;
///
/// let secret = "These programs were never about terrorism: theyre about economic spying, \
/// social control, and diplomatic manipulation. Theyre about power.";
///
/// let result = split_secret_rng(
/// &mut ChaChaRng::new_unseeded(),
/// 7,
/// 10,
/// &secret.as_bytes(),
/// Some("text/html".to_string()),
/// true,
/// );
///
/// match result {
/// Ok(shares) => {
/// // Do something with the shares
/// },
/// Err(_) => {
/// // Deal with error
/// }
/// }
/// # }
/// ```
pub fn split_secret_rng<R: Rng>(
rng: &mut R,
k: u8,
n: u8,
secret: &[u8],
mime_type: Option<String>,
sign_shares: bool,
) -> Result<Vec<String>> {
WrappedSecrets::default()
.split_secret(rng, k, n, secret, mime_type, sign_shares)
.map(|shares| shares.into_iter().map(Share::into_string).collect())
}

View File

@ -3,6 +3,7 @@ use proto::VersionProto;
use proto::wrapped::SecretProto;
use protobuf;
use protobuf::Message;
use rand::Rng;
use sss::SSS;
pub(crate) use sss::Share;
@ -12,8 +13,9 @@ pub(crate) struct WrappedSecrets;
impl WrappedSecrets {
/// Performs threshold k-out-of-n Shamir's secret sharing.
pub fn split_secret(
pub fn split_secret<R: Rng>(
&self,
rng: &mut R,
k: u8,
n: u8,
secret: &[u8],
@ -30,7 +32,7 @@ impl WrappedSecrets {
let data = rusty_secret.write_to_bytes().unwrap();
SSS::default().split_secret(k, n, data.as_slice(), sign_shares)
SSS::default().split_secret(rng, k, n, data.as_slice(), sign_shares)
}
/// Recovers the secret from a k-out-of-n Shamir's secret sharing.