From 3c37fc557d8cba76df787daed870b347836184fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=BA=C3=B1ez?= Date: Mon, 1 Apr 2024 19:48:43 +0200 Subject: [PATCH] Introduce UpdatableBlindedKeyShare as part of refresh API Get rid of PrivateKeyShare and UpdatedPrivateKeyShare at the refresh level. Instead, we'll continue to deal with BlindedKeyShares, since they're semantically similar to transcripts at the pvss & dkg level --- ferveo/src/refresh.rs | 92 ++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 50 deletions(-) diff --git a/ferveo/src/refresh.rs b/ferveo/src/refresh.rs index a7af4f2c..408242d0 100644 --- a/ferveo/src/refresh.rs +++ b/ferveo/src/refresh.rs @@ -1,14 +1,14 @@ use std::{collections::HashMap, ops::Mul, usize}; use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup, Group}; -use ark_ff::Zero; +use ark_ff::{Field, Zero}; use ark_poly::{ univariate::DensePolynomial, DenseUVPolynomial, EvaluationDomain, Polynomial, }; use ferveo_common::{serialization, Keypair}; use ferveo_tdec::{ - lagrange_basis_at, prepare_combine_simple, CiphertextHeader, + lagrange_basis_at, prepare_combine_simple, BlindedKeyShare, CiphertextHeader, DecryptionSharePrecomputed, DecryptionShareSimple, }; use itertools::{zip_eq, Itertools}; @@ -23,38 +23,39 @@ use crate::{ Result, }; -type InnerPrivateKeyShare = ferveo_tdec::PrivateKeyShare; +type InnerBlindedKeyShare = ferveo_tdec::BlindedKeyShare; -/// Private key share held by a participant in the DKG protocol. +/// Blinded key share held by a participant in the DKG protocol +// TODO: What about the commented macros? #[derive( - Debug, Clone, PartialEq, Eq, ZeroizeOnDrop, Serialize, Deserialize, + Debug, Clone, //PartialEq, Eq, ZeroizeOnDrop, Serialize, Deserialize, )] - -// Q to Piotr: Why do we need this? -pub struct PrivateKeyShare( - #[serde(bound( - serialize = "ferveo_tdec::PrivateKeyShare: Serialize", - deserialize = "ferveo_tdec::PrivateKeyShare: DeserializeOwned" - ))] - pub InnerPrivateKeyShare, +pub struct UpdatableBlindedKeyShare( + // #[serde(bound( + // serialize = "ferveo_tdec::PrivateKeyShare: Serialize", + // deserialize = "ferveo_tdec::PrivateKeyShare: DeserializeOwned" + // ))] + pub InnerBlindedKeyShare, ); -impl PrivateKeyShare { - pub fn new(private_key_share: InnerPrivateKeyShare) -> Self { - Self(private_key_share) +impl UpdatableBlindedKeyShare { + pub fn new(blinded_key_share: InnerBlindedKeyShare) -> Self { + Self(blinded_key_share) } /// From PSS paper, section 4.2.3, (https://link.springer.com/content/pdf/10.1007/3-540-44750-4_27.pdf) - pub fn create_updated_key_share( + pub fn apply_share_updates( &self, share_updates: &[ShareUpdate], - ) -> UpdatedPrivateKeyShare { + ) -> UpdatableBlindedKeyShare { // 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()); - let updated_key_share = ferveo_tdec::PrivateKeyShare(updated_key_share); - UpdatedPrivateKeyShare(updated_key_share) + .fold(self.0.blinded_key_share, |acc, delta| (acc + delta.update).into()); + UpdatableBlindedKeyShare(BlindedKeyShare{ + validator_public_key: self.0.validator_public_key, + blinded_key_share: updated_key_share + }) // let updates_for_participant: Vec<_> = // update_transcripts_by_producer @@ -129,6 +130,20 @@ impl PrivateKeyShare { ))) } + pub fn unblind_private_key_share( + &self, + validator_keypair: &Keypair, + ) -> Result> { + // Decrypt private key share https://nikkolasg.github.io/ferveo/pvss.html#validator-decryption-of-private-key-shares + let blinded_key_share = &self.0; + let private_key_share = blinded_key_share.unblind( + validator_keypair.decryption_key.inverse().expect( + "Validator decryption key must have an inverse", + ) + ); + Ok(private_key_share) + } + pub fn create_decryption_share_simple( &self, ciphertext_header: &CiphertextHeader, @@ -136,9 +151,10 @@ impl PrivateKeyShare { validator_keypair: &Keypair, ) -> Result> { let g_inv = PubliclyVerifiableParams::::default().g_inv(); + let private_key_share = self.unblind_private_key_share(validator_keypair); DecryptionShareSimple::create( &validator_keypair.decryption_key, - &self.0, + &private_key_share.unwrap(), ciphertext_header, aad, &g_inv, @@ -191,10 +207,11 @@ impl PrivateKeyShare { // Finally, pick the lagrange coefficient for the current share index let lagrange_coeff = &lagrange_coeffs[adjusted_share_index]; let g_inv = PubliclyVerifiableParams::::default().g_inv(); + let private_key_share = self.unblind_private_key_share(validator_keypair); DecryptionSharePrecomputed::create( share_index as usize, &validator_keypair.decryption_key, - &self.0, + &private_key_share.unwrap(), ciphertext_header, aad, lagrange_coeff, @@ -204,29 +221,6 @@ impl PrivateKeyShare { } } -/// An updated private key share, resulting from an intermediate step in a share recovery or refresh operation. -#[derive( - Debug, Clone, PartialEq, Eq, ZeroizeOnDrop, Serialize, Deserialize, -)] -pub struct UpdatedPrivateKeyShare( - #[serde(bound( - serialize = "ferveo_tdec::PrivateKeyShare: Serialize", - deserialize = "ferveo_tdec::PrivateKeyShare: DeserializeOwned" - ))] - pub(crate) InnerPrivateKeyShare, -); - -impl UpdatedPrivateKeyShare { - /// One-way conversion from `UpdatedPrivateKeyShare` to `PrivateKeyShare`. - /// Use this method to eject from the `UpdatedPrivateKeyShare` type and use the resulting `PrivateKeyShare` in further operations. - pub fn inner(&self) -> PrivateKeyShare { - PrivateKeyShare(self.0.clone()) - } - - pub fn new(private_key_share: InnerPrivateKeyShare) -> Self { - Self(private_key_share) - } -} /// An update to a private key share generated by a participant in a share refresh operation. #[serde_as] @@ -451,8 +445,7 @@ mod tests_refresh { use test_case::{test_case, test_matrix}; use crate::{ - test_common::*, DomainPoint, PrivateKeyShare, UpdateTranscript, - UpdatedPrivateKeyShare, + test_common::*, DomainPoint, UpdateTranscript, }; type ScalarField = @@ -535,8 +528,7 @@ mod tests_refresh { .last() .unwrap() .domain; - let original_private_key_share = - PrivateKeyShare(selected_participant.private_key_share); + let original_private_key_share = selected_participant.private_key_share; // Remove the selected participant from the contexts and all nested structures let mut remaining_participants = contexts;