use vsss_rs::Gf256; #[derive(Debug, thiserror::Error)] pub enum ShamirError { #[error("Failed to split key: {0}")] Split(String), #[error("Failed to combine shares: {0}")] Combine(String), } /// Split `key` into `total` shares where any `threshold` shares can reconstruct it. /// Each returned Vec is a share with format [`identifier_byte`, `value_bytes`...]. pub fn split_key( threshold: usize, total: usize, key: &[u8; 32], rng: impl rand_core::RngCore + rand_core::CryptoRng, ) -> Result>, ShamirError> { Gf256::split_array(threshold, total, key.as_slice(), rng) .map_err(|e| ShamirError::Split(format!("{e:?}"))) } /// Returns the minimum number of shares required to reconstruct the secret /// for a committee of `n` operators. #[must_use] pub const fn shamir_threshold(n: usize) -> usize { match n { 0 => panic!("No operators"), 1 => 1, 2 => 2, n => n / 2 + 1, } } /// Reconstruct the secret from `threshold` or more shares. pub fn combine_shares(shares: &[Vec]) -> Result<[u8; 32], ShamirError> { let bytes = Gf256::combine_array(shares) .map_err(|e| ShamirError::Combine(format!("{e:?}")))?; <[u8; 32]>::try_from(bytes.as_slice()) .map_err(|_| ShamirError::Combine("unexpected reconstructed key length".to_owned())) }