wamu_core/
share_split_reconstruct.rs

1//! Share splitting and reconstruction implementation.
2//!
3//! Ref: <https://wamu.tech/specification#share-splitting-and-reconstruction>.
4
5use crypto_bigint::{Encoding, U256};
6
7use crate::errors::Error;
8use crate::share::{SecretShare, SigningShare, SubShare, SubShareInterpolator};
9use crate::traits::IdentityProvider;
10
11/// Given a "secret share" and an identity provider, returns "signing share" and "sub-share"
12/// that can be used to reconstruct the "secret share" given the same identity provider.
13///
14/// Ref: <https://wamu.tech/specification#share-splitting>.
15pub fn split(
16    secret_share: &SecretShare,
17    identity_provider: &impl IdentityProvider,
18) -> Result<(SigningShare, SubShare), Error> {
19    // Generates "signing share".
20    let signing_share = SigningShare::generate();
21
22    // Computes "sub-share" a from "signing share".
23    let (r, s) = identity_provider.sign_message_share(&signing_share.to_be_bytes());
24    let sub_share_a = SubShare::new(U256::from_be_bytes(r), U256::from_be_bytes(s))?;
25
26    // Initializes the "sub-share" interpolator.
27    let sub_share_interpolator = SubShareInterpolator::new(
28        // The "secret share" is the constant term, so x = 0.
29        &SubShare::new(U256::ZERO, secret_share.as_u256())?,
30        &sub_share_a,
31    );
32
33    // Computes "sub-share" b.
34    let sub_share_b = sub_share_interpolator.sub_share(U256::ONE)?;
35
36    // Returns "signing share" and "sub-share" b.
37    Ok((signing_share, sub_share_b))
38}
39
40/// Returns "secret share" associated with "signing share", "sub-share" and identity provider.
41///
42/// Ref: <https://wamu.tech/specification#share-reconstruction>.
43pub fn reconstruct(
44    signing_share: &SigningShare,
45    sub_share_b: &SubShare,
46    identity_provider: &impl IdentityProvider,
47) -> Result<SecretShare, Error> {
48    // Computes "sub-share" a from "signing share".
49    let (r, s) = identity_provider.sign_message_share(&signing_share.to_be_bytes());
50    let sub_share_a = SubShare::new(U256::from_be_bytes(r), U256::from_be_bytes(s))?;
51
52    // Initializes the "sub-share" interpolator.
53    let sub_share_interpolator = SubShareInterpolator::new(&sub_share_a, sub_share_b);
54
55    // Returns "secret share".
56    Ok(sub_share_interpolator.secret().into())
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62    use crate::crypto::Random32Bytes;
63    use crate::test_utils::MockECDSAIdentityProvider;
64
65    #[test]
66    fn share_splitting_and_reconstruction_works() {
67        // Generates secret share.
68        let secret_share = SecretShare::from(Random32Bytes::generate_mod_q());
69
70        // Generates identity provider.
71        let identity_provider = MockECDSAIdentityProvider::generate();
72
73        // Computes "signing share" and "sub-share".
74        let (signing_share, sub_share_b) = split(&secret_share, &identity_provider).unwrap();
75
76        // Reconstructs "secret share" from "signing share" and "sub-share".
77        let reconstructed_secret_share =
78            reconstruct(&signing_share, &sub_share_b, &identity_provider).unwrap();
79
80        // Verifies reconstructed "secret share".
81        assert_eq!(
82            &reconstructed_secret_share.to_be_bytes(),
83            &secret_share.to_be_bytes()
84        );
85    }
86}