diff --git a/ferveo-tdec/src/context.rs b/ferveo-tdec/src/context.rs index e8162d07..18965bd5 100644 --- a/ferveo-tdec/src/context.rs +++ b/ferveo-tdec/src/context.rs @@ -11,7 +11,7 @@ use crate::{ #[derive(Clone, Debug)] pub struct PublicDecryptionContextFast { pub domain: E::ScalarField, - pub public_key: ShareCommitment, // FIXME + pub public_key: ShareCommitment, // FIXME pub blinded_key_share: BlindedKeyShare, // This decrypter's contribution to N(0), namely (-1)^|domain| * \prod_i omega_i pub lagrange_n_0: E::ScalarField, diff --git a/ferveo-tdec/src/key_share.rs b/ferveo-tdec/src/key_share.rs index 951750ca..66431ca4 100644 --- a/ferveo-tdec/src/key_share.rs +++ b/ferveo-tdec/src/key_share.rs @@ -1,10 +1,7 @@ use std::ops::Mul; use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup}; - - use ferveo_common::serialization; - use serde::{Deserialize, Serialize}; use serde_with::serde_as; use zeroize::{Zeroize, ZeroizeOnDrop}; @@ -21,10 +18,12 @@ pub struct ShareCommitment( #[serde_as(as = "serialization::SerdeAs")] pub E::G1Affine, // A_{i, \omega_i} ); +// TODO: Improve by adding share commitment here +// TODO: Is this a test utility perhaps? #[derive(Debug, Copy, Clone)] pub struct BlindedKeyShare { - pub validator_public_key: E::G2Affine, // [b] H - pub blinded_key_share: E::G2Affine, // [b] Z_{i, \omega_i} + pub validator_public_key: E::G2Affine, // [b] H + pub blinded_key_share: E::G2Affine, // [b] Z_{i, \omega_i} } impl BlindedKeyShare { @@ -55,6 +54,14 @@ impl BlindedKeyShare { // self.blinded_key_share = // self.blinded_key_share.mul(-*omega_inv).into_affine(); // } + pub fn unblind( + &self, + unblinding_factor: E::ScalarField, + ) -> PrivateKeyShare { + PrivateKeyShare::( + self.blinded_key_share.mul(unblinding_factor).into_affine(), + ) + } } #[serde_as] @@ -69,7 +76,8 @@ pub struct PrivateKeyShare( // #[cfg(test)] impl PrivateKeyShare { pub fn blind(&self, b: E::ScalarField) -> BlindedKeyShare { - let validator_public_key = E::G2Affine::generator().mul(b).into_affine(); + let validator_public_key = + E::G2Affine::generator().mul(b).into_affine(); BlindedKeyShare:: { validator_public_key, blinded_key_share: self.0.mul(b).into_affine(), diff --git a/ferveo-tdec/src/lib.rs b/ferveo-tdec/src/lib.rs index c4113fd8..8ba22849 100644 --- a/ferveo-tdec/src/lib.rs +++ b/ferveo-tdec/src/lib.rs @@ -138,7 +138,8 @@ pub mod test_common { ) .enumerate() { - let private_key_share: PrivateKeyShare = PrivateKeyShare(*private); + let private_key_share: PrivateKeyShare = + PrivateKeyShare(*private); let b = E::ScalarField::rand(rng); let blinded_key_shares = private_key_share.blind(b); // blinded_key_shares.multiply_by_omega_inv(domain_inv); // FIXME @@ -191,23 +192,23 @@ pub mod test_common { // The dealer chooses a uniformly random polynomial f of degree t-1 let threshold_poly = DensePolynomial::::rand(threshold - 1, rng); - + // Domain, or omega Ω let fft_domain = ark_poly::GeneralEvaluationDomain::::new( shares_num, ) .unwrap(); - + // domain points: - ω_j in Ω let domain_points = fft_domain.elements().collect::>(); - + // `evals` are evaluations of the polynomial f over the domain, omega: f(ω_j) for ω_j in Ω let evals = threshold_poly.evaluate_over_domain_by_ref(fft_domain); // A_j, share commitments of participants: [f(ω_j)] G let share_commitments = fast_multiexp(&evals.evals, g.into_group()); - + // FIXME: These 2 lines don't make sense //let pubkey_share = g.mul(evals.evals[0]); //debug_assert!(share_commitments[0] == E::G1Affine::from(pubkey_share)); @@ -218,10 +219,10 @@ pub mod test_common { // The shared secret is the free coefficient from threshold poly let a_0 = threshold_poly.coeffs[0]; - + // F_0, group's public key let group_pubkey = g.mul(a_0); - + // group's private key (NOTE: just for tests, this is NEVER constructed in production) let group_privkey = h.mul(a_0); @@ -233,18 +234,23 @@ pub mod test_common { let mut public_contexts = vec![]; // (domain_point, A, Z) - for (index, (domain_point, share_commit, private_share)) in - izip!(domain_points.iter(), share_commitments.iter(), privkey_shares.iter()) - .enumerate() + for (index, (domain_point, share_commit, private_share)) in izip!( + domain_points.iter(), + share_commitments.iter(), + privkey_shares.iter() + ) + .enumerate() { let private_key_share = PrivateKeyShare::(*private_share); - let b = E::ScalarField::one(); // FIXME: rand(rng); - let blinded_key_share: BlindedKeyShare = private_key_share.blind(b); + let blinding_factor = E::ScalarField::rand(rng); + let blinded_key_share: BlindedKeyShare = + private_key_share.blind(blinding_factor); + private_contexts.push(PrivateDecryptionContextSimple:: { index, setup_params: SetupParams { - b, - b_inv: b.inverse().unwrap(), + b: blinding_factor, + b_inv: blinding_factor.inverse().unwrap(), g, h_inv: E::G2Prepared::from(-h.into_group()), g_inv: E::G1Prepared::from(-g.into_group()), @@ -255,10 +261,12 @@ pub mod test_common { }); public_contexts.push(PublicDecryptionContextSimple:: { domain: *domain_point, - share_commitment: ShareCommitment::(*share_commit), // FIXME + share_commitment: ShareCommitment::(*share_commit), // FIXME blinded_key_share, h, - validator_public_key: blinded_key_share.validator_public_key.into_group() + validator_public_key: blinded_key_share + .validator_public_key + .into_group(), }); } for private_ctxt in private_contexts.iter_mut() { diff --git a/ferveo/src/refresh.rs b/ferveo/src/refresh.rs index d4b5aa93..44b246ae 100644 --- a/ferveo/src/refresh.rs +++ b/ferveo/src/refresh.rs @@ -46,7 +46,7 @@ impl PrivateKeyShare { &self, share_updates: &[ShareUpdate], ) -> UpdatedPrivateKeyShare { - // TODO: Validate commitments from share update + // TODO: Validate commitments from share update // FIXME: Don't forget!!!!! let updated_key_share = share_updates .iter() .fold(self.0 .0, |acc, delta| (acc + delta.update).into()); @@ -316,7 +316,8 @@ mod tests_refresh { use ark_bls12_381::Fr; use ark_std::{test_rng, UniformRand, Zero}; use ferveo_tdec::{ - test_common::setup_simple, PrivateDecryptionContextSimple, + test_common::setup_simple, + BlindedKeyShare, PrivateDecryptionContextSimple, }; use rand_core::RngCore; use test_case::{test_case, test_matrix}; @@ -601,9 +602,26 @@ mod tests_refresh { .collect(); // And creates a new, refreshed share - let updated_share = - PrivateKeyShare(p.private_key_share.clone()) - .create_updated_key_share(&updates_for_participant); + let blinded_key_share = + p.public_decryption_contexts[p.index].blinded_key_share; + + // TODO: Encapsulate this somewhere, originally from PrivateKeyShare.create_updated_key_share + // FIXME: Validate commitments from share update, don't forget!!!!! + let updated_blinded_key_share: BlindedKeyShare = + BlindedKeyShare { + validator_public_key: blinded_key_share + .validator_public_key, + blinded_key_share: updates_for_participant.iter().fold( + blinded_key_share.blinded_key_share, + |acc, delta| (acc + delta.update).into(), + ), + }; + + let unblinding_factor = p.setup_params.b_inv; + let updated_share = UpdatedPrivateKeyShare( + updated_blinded_key_share.unblind(unblinding_factor), + ); + (p.index as u32, updated_share) }) // We only need `threshold` refreshed shares to recover the original share