Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Key share refreshing ceremony refactor #175

Merged
merged 3 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions ferveo-common/src/keypair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use ark_std::{
rand::{prelude::StdRng, RngCore, SeedableRng},
UniformRand,
};
use generic_array::{typenum::U96, GenericArray};
use generic_array::{
typenum::{Unsigned, U96},
GenericArray,
};
use serde::*;
use serde_with::serde_as;

Expand Down Expand Up @@ -55,7 +58,7 @@ impl<E: Pairing> PublicKey<E> {
}

pub fn serialized_size() -> usize {
96
U96::to_usize()
}
}

Expand Down Expand Up @@ -106,7 +109,6 @@ impl<E: Pairing> Ord for Keypair<E> {

impl<E: Pairing> Keypair<E> {
/// Returns the public session key for the publicly verifiable DKG participant

pub fn public_key(&self) -> PublicKey<E> {
PublicKey::<E> {
encryption_key: E::G2Affine::generator()
Expand All @@ -116,7 +118,6 @@ impl<E: Pairing> Keypair<E> {
}

/// Creates a new ephemeral session key for participating in the DKG

pub fn new<R: RngCore>(rng: &mut R) -> Self {
Self {
decryption_key: E::ScalarField::rand(rng),
Expand Down
1 change: 1 addition & 0 deletions ferveo-python/ferveo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@
DuplicatedShareIndex,
NoTranscriptsToAggregate,
InvalidAggregateVerificationParameters,
UnknownValidator,
)
3 changes: 3 additions & 0 deletions ferveo-python/ferveo/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,6 @@ class NoTranscriptsToAggregate(Exception):

class InvalidAggregateVerificationParameters(Exception):
pass

class UnknownValidator(Exception):
pass
8 changes: 4 additions & 4 deletions ferveo-tdec/benches/tpke.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![allow(clippy::redundant_closure)]

use ark_bls12_381::{Bls12_381, Fr, G1Affine as G1, G2Affine as G2};
use ark_bls12_381::{Bls12_381, Fr};
use ark_ec::pairing::Pairing;
use criterion::{
black_box, criterion_group, criterion_main, BenchmarkId, Criterion,
Expand All @@ -25,8 +25,8 @@ struct SetupShared {
shares_num: usize,
msg: Vec<u8>,
aad: Vec<u8>,
pubkey: G1,
privkey: G2,
pubkey: PublicKeyShare<E>,
privkey: PrivateKeyShare<E>,
ciphertext: Ciphertext<E>,
shared_secret: SharedSecret<E>,
}
Expand Down Expand Up @@ -550,7 +550,7 @@ pub fn bench_decryption_share_validity_checks(c: &mut Criterion) {
// for &shares_num in NUM_SHARES_CASES.iter() {
// let setup = SetupSimple::new(shares_num, msg_size, rng);
// let threshold = setup.shared.threshold;
// let polynomial = make_random_polynomial_with_root::<E>(
// let polynomial = create_random_polynomial_with_root::<E>(
// threshold - 1,
// &Fr::zero(),
// rng,
Expand Down
14 changes: 9 additions & 5 deletions ferveo-tdec/src/ciphertext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ use serde_with::serde_as;
use sha2::{digest::Digest, Sha256};
use zeroize::ZeroizeOnDrop;

use crate::{htp_bls12381_g2, Error, Result, SecretBox, SharedSecret};
use crate::{
htp_bls12381_g2, Error, PrivateKeyShare, PublicKeyShare, Result, SecretBox,
SharedSecret,
};

#[serde_as]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
Expand Down Expand Up @@ -95,7 +98,7 @@ impl<E: Pairing> CiphertextHeader<E> {
pub fn encrypt<E: Pairing>(
message: SecretBox<Vec<u8>>,
aad: &[u8],
pubkey: &E::G1Affine,
pubkey: &PublicKeyShare<E>,
rng: &mut impl rand::Rng,
) -> Result<Ciphertext<E>> {
// r
Expand All @@ -105,7 +108,8 @@ pub fn encrypt<E: Pairing>(
// h
let h_gen = E::G2Affine::generator();

let ry_prep = E::G1Prepared::from(pubkey.mul(rand_element).into());
let ry_prep =
E::G1Prepared::from(pubkey.public_key_share.mul(rand_element).into());
// s
let product = E::pairing(ry_prep, h_gen).0;
// u
Expand Down Expand Up @@ -140,13 +144,13 @@ pub fn encrypt<E: Pairing>(
pub fn decrypt_symmetric<E: Pairing>(
ciphertext: &Ciphertext<E>,
aad: &[u8],
private_key: &E::G2Affine,
private_key: &PrivateKeyShare<E>,
g_inv: &E::G1Prepared,
) -> Result<Vec<u8>> {
ciphertext.check(aad, g_inv)?;
let shared_secret = E::pairing(
E::G1Prepared::from(ciphertext.commitment),
E::G2Prepared::from(*private_key),
E::G2Prepared::from(private_key.private_key_share),
)
.0;
let shared_secret = SharedSecret(shared_secret);
Expand Down
2 changes: 0 additions & 2 deletions ferveo-tdec/src/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ pub fn prepare_combine_fast<E: Pairing>(
.collect::<Vec<_>>()
}

// TODO: Combine `tpke::prepare_combine_simple` and `tpke::share_combine_simple` into
// one function and expose it in the tpke::api?
pub fn prepare_combine_simple<E: Pairing>(
domain: &[E::ScalarField],
) -> Vec<E::ScalarField> {
Expand Down
37 changes: 23 additions & 14 deletions ferveo-tdec/src/decryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ use std::ops::Mul;

use ark_ec::{pairing::Pairing, CurveGroup};
use ark_ff::{Field, One, Zero};
use ark_std::UniformRand;
use ferveo_common::serialization;
use itertools::{izip, zip_eq};
use rand_core::RngCore;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_with::serde_as;

use crate::{
generate_random, Ciphertext, CiphertextHeader, PrivateKeyShare,
PublicDecryptionContextFast, PublicDecryptionContextSimple, Result,
Ciphertext, CiphertextHeader, PrivateKeyShare, PublicDecryptionContextFast,
PublicDecryptionContextSimple, Result,
};

#[serde_as]
Expand All @@ -36,9 +37,6 @@ impl<E: Pairing> ValidatorShareChecksum<E> {
// C_i = dk_i^{-1} * U
let checksum = ciphertext_header
.commitment
// TODO: Should we panic here? I think we should since that would mean that the decryption key is invalid.
// And so, the validator should not be able to create a decryption share.
// And so, the validator should remake their keypair.
.mul(
validator_decryption_key
.inverse()
Expand Down Expand Up @@ -226,6 +224,15 @@ impl<E: Pairing> DecryptionSharePrecomputed<E> {
}
}

pub fn generate_random_scalars<R: RngCore, E: Pairing>(
n: usize,
rng: &mut R,
) -> Vec<E::ScalarField> {
(0..n)
.map(|_| E::ScalarField::rand(rng))
.collect::<Vec<_>>()
}

// TODO: Remove this code? Currently only used in benchmarks. Move to benchmark suite?
pub fn batch_verify_decryption_shares<R: RngCore, E: Pairing>(
pub_contexts: &[PublicDecryptionContextFast<E>],
Expand All @@ -240,16 +247,17 @@ pub fn batch_verify_decryption_shares<R: RngCore, E: Pairing>(
let blinding_keys = decryption_shares[0]
.iter()
.map(|d| {
pub_contexts[d.decrypter_index]
.blinded_key_share
.blinding_key_prepared
.clone()
E::G2Prepared::from(
pub_contexts[d.decrypter_index]
.blinded_key_share
.blinding_key,
)
})
.collect::<Vec<_>>();

// For each ciphertext, generate num_shares random scalars
let alpha_ij = (0..num_ciphertexts)
.map(|_| generate_random::<_, E>(num_shares, rng))
.map(|_| generate_random_scalars::<_, E>(num_shares, rng))
.collect::<Vec<_>>();

let mut pairings_a = Vec::with_capacity(num_shares + 1);
Expand Down Expand Up @@ -302,10 +310,11 @@ pub fn verify_decryption_shares_fast<E: Pairing>(
let blinding_keys = decryption_shares
.iter()
.map(|d| {
pub_contexts[d.decrypter_index]
.blinded_key_share
.blinding_key_prepared
.clone()
E::G2Prepared::from(
pub_contexts[d.decrypter_index]
.blinded_key_share
.blinding_key,
)
})
.collect::<Vec<_>>();

Expand Down
24 changes: 11 additions & 13 deletions ferveo-tdec/src/key_share.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ use std::ops::Mul;
use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup};
use ark_ff::One;
use ark_std::UniformRand;
use ferveo_common::serialization;
use rand_core::RngCore;
use zeroize::ZeroizeOnDrop;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use zeroize::{Zeroize, ZeroizeOnDrop};

#[derive(Debug, Clone)]
// TODO: Should we rename it to PublicKey or SharedPublicKey?
pub struct PublicKeyShare<E: Pairing> {
pub public_key_share: E::G1Affine, // A_{i, \omega_i}
}
Expand All @@ -15,16 +19,6 @@ pub struct PublicKeyShare<E: Pairing> {
pub struct BlindedKeyShare<E: Pairing> {
pub blinding_key: E::G2Affine, // [b] H
pub blinded_key_share: E::G2Affine, // [b] Z_{i, \omega_i}
pub blinding_key_prepared: E::G2Prepared,
}

pub fn generate_random<R: RngCore, E: Pairing>(
n: usize,
rng: &mut R,
) -> Vec<E::ScalarField> {
(0..n)
.map(|_| E::ScalarField::rand(rng))
.collect::<Vec<_>>()
}

impl<E: Pairing> BlindedKeyShare<E> {
Expand Down Expand Up @@ -58,8 +52,13 @@ impl<E: Pairing> BlindedKeyShare<E> {
}
}

#[derive(Debug, Clone, PartialEq, Eq, ZeroizeOnDrop)]
#[serde_as]
#[derive(
Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize, ZeroizeOnDrop,
)]
pub struct PrivateKeyShare<E: Pairing> {
// TODO: Replace with a tuple?
#[serde_as(as = "serialization::SerdeAs")]
pub private_key_share: E::G2Affine,
}

Expand All @@ -68,7 +67,6 @@ impl<E: Pairing> PrivateKeyShare<E> {
let blinding_key = E::G2Affine::generator().mul(b).into_affine();
BlindedKeyShare::<E> {
blinding_key,
blinding_key_prepared: E::G2Prepared::from(blinding_key),
blinded_key_share: self.private_key_share.mul(b).into_affine(),
}
}
Expand Down
42 changes: 29 additions & 13 deletions ferveo-tdec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ pub mod test_common {
shares_num: usize,
rng: &mut impl RngCore,
) -> (
E::G1Affine,
E::G2Affine,
PublicKeyShare<E>,
PrivateKeyShare<E>,
Vec<PrivateDecryptionContextFast<E>>,
) {
assert!(shares_num >= threshold);
Expand Down Expand Up @@ -138,7 +138,7 @@ pub mod test_common {
)
.enumerate()
{
let private_key_share = PrivateKeyShare::<E> {
let private_key_share = PrivateKeyShare {
private_key_share: *private,
};
let b = E::ScalarField::rand(rng);
Expand Down Expand Up @@ -171,16 +171,24 @@ pub mod test_common {
private.public_decryption_contexts = public_contexts.clone();
}

(pubkey.into(), privkey.into(), private_contexts)
(
PublicKeyShare {
public_key_share: pubkey.into(),
},
PrivateKeyShare {
private_key_share: privkey.into(),
},
private_contexts,
)
}

pub fn setup_simple<E: Pairing>(
threshold: usize,
shares_num: usize,
rng: &mut impl rand::Rng,
) -> (
E::G1Affine,
E::G2Affine,
PublicKeyShare<E>,
PrivateKeyShare<E>,
Vec<PrivateDecryptionContextSimple<E>>,
) {
assert!(shares_num >= threshold);
Expand Down Expand Up @@ -259,22 +267,30 @@ pub mod test_common {
private.public_decryption_contexts = public_contexts.clone();
}

(pubkey.into(), privkey.into(), private_contexts)
(
PublicKeyShare {
public_key_share: pubkey.into(),
},
PrivateKeyShare {
private_key_share: privkey.into(),
},
private_contexts,
)
}

pub fn setup_precomputed<E: Pairing>(
shares_num: usize,
rng: &mut impl rand::Rng,
) -> (
E::G1Affine,
E::G2Affine,
PublicKeyShare<E>,
PrivateKeyShare<E>,
Vec<PrivateDecryptionContextSimple<E>>,
) {
// In precomputed variant, the security threshold is equal to the number of shares
setup_simple::<E>(shares_num, shares_num, rng)
}

pub fn make_shared_secret<E: Pairing>(
pub fn create_shared_secret<E: Pairing>(
pub_contexts: &[PublicDecryptionContextSimple<E>],
decryption_shares: &[DecryptionShareSimple<E>],
) -> SharedSecret<E> {
Expand All @@ -292,7 +308,7 @@ mod tests {
use ark_std::{test_rng, UniformRand};
use ferveo_common::{FromBytes, ToBytes};

use crate::test_common::{make_shared_secret, setup_simple, *};
use crate::test_common::{create_shared_secret, setup_simple, *};

type E = ark_bls12_381::Bls12_381;
type TargetField = <E as Pairing>::TargetField;
Expand Down Expand Up @@ -465,7 +481,7 @@ mod tests {
let pub_contexts =
contexts[0].public_decryption_contexts[..threshold].to_vec();
let shared_secret =
make_shared_secret(&pub_contexts, &decryption_shares);
create_shared_secret(&pub_contexts, &decryption_shares);

test_ciphertext_validation_fails(
&msg,
Expand All @@ -479,7 +495,7 @@ mod tests {
let decryption_shares = decryption_shares[..threshold - 1].to_vec();
let pub_contexts = pub_contexts[..threshold - 1].to_vec();
let shared_secret =
make_shared_secret(&pub_contexts, &decryption_shares);
create_shared_secret(&pub_contexts, &decryption_shares);

let result =
decrypt_with_shared_secret(&ciphertext, aad, &shared_secret, g_inv);
Expand Down
Loading
Loading