1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//! SSS provides Shamir's secret sharing with raw data.

use errors::*;

mod share;
pub(crate) use self::share::*;

mod format;
// pub use self::format::*;

mod scheme;
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
///
/// ```
/// use rusty_secrets::sss::split_secret;
///
/// let secret = "These programs were never about terrorism: they’re about economic spying, \
///               social control, and diplomatic manipulation. They’re 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(k: u8, n: u8, secret: &[u8], sign_shares: bool) -> Result<Vec<String>> {
    let mut rng = OsRng::new().chain_err(|| ErrorKind::CannotGenerateRandomNumbers)?;
    SSS::default()
        .split_secret(&mut rng, 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
///
/// ```
/// # extern crate rusty_secrets;
/// # extern crate rand;
/// #
/// # use rand::{OsRng, ChaChaRng, SeedableRng};
/// #
/// # fn some_custom_rng() -> ChaChaRng {
/// #     ChaChaRng::from_rng(OsRng::new().unwrap()).unwrap()
/// # }
/// #
/// # fn main() {
/// use rusty_secrets::sss::split_secret_rng;
///
/// let secret = "These programs were never about terrorism: they’re about economic spying, \
///               social control, and diplomatic manipulation. They’re about power.";
///
/// let mut rng = some_custom_rng();
///
/// match split_secret_rng(&mut rng, 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())
}

/// Recovers the secret from a k-out-of-n Shamir's secret sharing scheme.
///
/// At least `k` distinct shares need to be provided to recover the secret.
///
/// # Examples
///
/// ```
/// use rusty_secrets::sss::recover_secret;
///
/// let share1 = "2-1-Cha7s14Q/mSwWko0ittr+/Uf79RHQMIP".to_string();
/// let share2 = "2-4-ChaydsUJDypD9ZWxwvIICh/cmZvzusOF".to_string();
/// let shares = vec![share1, share2];
///
/// match recover_secret(&shares, false) {
///     Ok(secret) => {
///         // Do something with the secret
///     },
///     Err(e) => {
///         // Deal with the error
///     }
/// }
/// ```
pub fn recover_secret(shares: &[String], verify_signatures: bool) -> Result<Vec<u8>> {
    let shares = Share::parse_all(shares, verify_signatures)?;
    SSS::recover_secret(shares, verify_signatures)
}