Skip to content

Commit

Permalink
refactor: avoid using crypto primitives directly, part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-roslaniec committed Feb 6, 2024
1 parent 6fd65bd commit 039f329
Show file tree
Hide file tree
Showing 10 changed files with 378 additions and 249 deletions.
6 changes: 3 additions & 3 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
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
34 changes: 23 additions & 11 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 Down Expand Up @@ -226,6 +227,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 +250,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 +313,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
13 changes: 2 additions & 11 deletions ferveo-tdec/src/key_share.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use rand_core::RngCore;
use 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 +16,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 @@ -60,6 +51,7 @@ impl<E: Pairing> BlindedKeyShare<E> {

#[derive(Debug, Clone, PartialEq, Eq, ZeroizeOnDrop)]
pub struct PrivateKeyShare<E: Pairing> {
// TODO: Replace with a tuple?
pub private_key_share: E::G2Affine,
}

Expand All @@ -68,7 +60,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
34 changes: 25 additions & 9 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,15 +267,23 @@ 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
Expand Down
33 changes: 19 additions & 14 deletions ferveo/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ use bincode;
use ferveo_common::serialization;
pub use ferveo_tdec::api::{
prepare_combine_simple, share_combine_precomputed, share_combine_simple,
Fr, G1Affine, G1Prepared, G2Affine, SecretBox, E,
DecryptionSharePrecomputed, Fr, G1Affine, G1Prepared, G2Affine, SecretBox,
E,
};
use ferveo_tdec::PublicKeyShare;
use generic_array::{
typenum::{Unsigned, U48},
GenericArray,
Expand All @@ -17,13 +19,6 @@ use rand::RngCore;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;

pub type PublicKey = ferveo_common::PublicKey<E>;
pub type Keypair = ferveo_common::Keypair<E>;
pub type Validator = crate::Validator<E>;
pub type Transcript = PubliclyVerifiableSS<E>;

pub type ValidatorMessage = (Validator, Transcript);

#[cfg(feature = "bindings-python")]
use crate::bindings_python;
#[cfg(feature = "bindings-wasm")]
Expand All @@ -34,8 +29,11 @@ use crate::{
PubliclyVerifiableSS, Result,
};

pub type DecryptionSharePrecomputed =
ferveo_tdec::api::DecryptionSharePrecomputed;
pub type PublicKey = ferveo_common::PublicKey<E>;
pub type Keypair = ferveo_common::Keypair<E>;
pub type Validator = crate::Validator<E>;
pub type Transcript = PubliclyVerifiableSS<E>;
pub type ValidatorMessage = (Validator, Transcript);

// Normally, we would use a custom trait for this, but we can't because
// the arkworks will not let us create a blanket implementation for G1Affine
Expand All @@ -58,8 +56,14 @@ pub fn encrypt(
pubkey: &DkgPublicKey,
) -> Result<Ciphertext> {
let mut rng = rand::thread_rng();
let ciphertext =
ferveo_tdec::api::encrypt(message, aad, &pubkey.0, &mut rng)?;
let ciphertext = ferveo_tdec::api::encrypt(
message,
aad,
&PublicKeyShare {
public_key_share: pubkey.0,
},
&mut rng,
)?;
Ok(Ciphertext(ciphertext))
}

Expand Down Expand Up @@ -91,7 +95,7 @@ impl Ciphertext {
}
}

#[serde_as]
#[serde_as] // TODO: Redundant serde_as?
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct CiphertextHeader(ferveo_tdec::api::CiphertextHeader);

Expand Down Expand Up @@ -146,6 +150,7 @@ impl From<bindings_wasm::FerveoVariant> for FerveoVariant {
#[serde_as]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct DkgPublicKey(
// TODO: Consider not using G1Affine directly here
#[serde_as(as = "serialization::SerdeAs")] pub(crate) G1Affine,
);

Expand Down Expand Up @@ -218,7 +223,7 @@ impl Dkg {
}

pub fn public_key(&self) -> DkgPublicKey {
DkgPublicKey(self.0.public_key())
DkgPublicKey(self.0.public_key().public_key_share)
}

pub fn generate_transcript<R: RngCore>(
Expand Down
Loading

0 comments on commit 039f329

Please sign in to comment.