use vsss_rs::elliptic_curve::rand_core::OsRng;
use vsss_rs::Gf256;
use crate::QosCryptoError;
pub fn shares_generate(
secret: &[u8],
share_count: usize,
threshold: usize,
) -> Result<Vec<Vec<u8>>, QosCryptoError> {
Gf256::split_array(threshold, share_count, secret, OsRng)
.map_err(QosCryptoError::Vsss)
}
pub fn shares_reconstruct<B: AsRef<[Vec<u8>]>>(
shares: B,
) -> Result<Vec<u8>, QosCryptoError> {
Gf256::combine_array(shares).map_err(QosCryptoError::Vsss)
}
#[cfg(test)]
mod test {
use rand::prelude::SliceRandom;
use super::*;
#[test]
fn make_and_reconstruct_shares() {
let secret = b"this is a crazy secret";
let n = 6;
let k = 3;
let all_shares = shares_generate(secret, n, k).unwrap();
let shares = all_shares.clone();
let reconstructed = shares_reconstruct(shares).unwrap();
assert_eq!(secret.to_vec(), reconstructed);
let shares = &all_shares[..k];
let reconstructed = shares_reconstruct(shares).unwrap();
assert_eq!(secret.to_vec(), reconstructed);
let shares = &all_shares[..(k - 1)];
let reconstructed = shares_reconstruct(shares).unwrap();
let old_reconstructed = shares_reconstruct(shares).unwrap();
assert!(secret.to_vec() != reconstructed);
assert!(secret.to_vec() != old_reconstructed);
let mut shares = all_shares.clone()[..k].to_vec();
shares.shuffle(&mut rand::rng());
let reconstructed = shares_reconstruct(&shares).unwrap();
assert_eq!(secret.to_vec(), reconstructed);
for combo in crate::n_choose_k::combinations(&all_shares, k) {
let reconstructed = shares_reconstruct(&combo).unwrap();
assert_eq!(secret.to_vec(), reconstructed);
}
}
#[test]
fn can_reconstruct_from_old_shares() {
let shares = [
qos_hex::decode("01661fc0cc265daa4e7bde354c281dcc23a80c590249")
.unwrap(),
qos_hex::decode("027bb5fb26d326e0fc421cf604e495e3d3e4bd24ab0e")
.unwrap(),
qos_hex::decode("0370d31b89800f2f9255abb73ca0ed0f8329d20fcc33")
.unwrap(),
];
let reconstructed1 =
shares_reconstruct(vec![shares[0].clone(), shares[1].clone()])
.unwrap();
let reconstructed2 =
shares_reconstruct(vec![shares[1].clone(), shares[2].clone()])
.unwrap();
let reconstructed3 =
shares_reconstruct(vec![shares[0].clone(), shares[2].clone()])
.unwrap();
let expected_secret = b"my cute little secret";
assert_eq!(reconstructed1, expected_secret);
assert_eq!(reconstructed2, expected_secret);
assert_eq!(reconstructed3, expected_secret);
}
}