use crypto_bigint::{Encoding, U256};
use crate::errors::Error;
use crate::share::{SecretShare, SigningShare, SubShare, SubShareInterpolator};
use crate::traits::IdentityProvider;
pub fn split(
secret_share: &SecretShare,
identity_provider: &impl IdentityProvider,
) -> Result<(SigningShare, SubShare), Error> {
let signing_share = SigningShare::generate();
let (r, s) = identity_provider.sign_message_share(&signing_share.to_be_bytes());
let sub_share_a = SubShare::new(U256::from_be_bytes(r), U256::from_be_bytes(s))?;
let sub_share_interpolator = SubShareInterpolator::new(
&SubShare::new(U256::ZERO, secret_share.as_u256())?,
&sub_share_a,
);
let sub_share_b = sub_share_interpolator.sub_share(U256::ONE)?;
Ok((signing_share, sub_share_b))
}
pub fn reconstruct(
signing_share: &SigningShare,
sub_share_b: &SubShare,
identity_provider: &impl IdentityProvider,
) -> Result<SecretShare, Error> {
let (r, s) = identity_provider.sign_message_share(&signing_share.to_be_bytes());
let sub_share_a = SubShare::new(U256::from_be_bytes(r), U256::from_be_bytes(s))?;
let sub_share_interpolator = SubShareInterpolator::new(&sub_share_a, sub_share_b);
Ok(sub_share_interpolator.secret().into())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::crypto::Random32Bytes;
use crate::test_utils::MockECDSAIdentityProvider;
#[test]
fn share_splitting_and_reconstruction_works() {
let secret_share = SecretShare::from(Random32Bytes::generate_mod_q());
let identity_provider = MockECDSAIdentityProvider::generate();
let (signing_share, sub_share_b) = split(&secret_share, &identity_provider).unwrap();
let reconstructed_secret_share =
reconstruct(&signing_share, &sub_share_b, &identity_provider).unwrap();
assert_eq!(
&reconstructed_secret_share.to_be_bytes(),
&secret_share.to_be_bytes()
);
}
}