Skip to content

Commit

Permalink
trim external apis
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-roslaniec committed Feb 16, 2023
1 parent a9b4331 commit 0b95048
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 329 deletions.
9 changes: 9 additions & 0 deletions ferveo-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ pub struct ExternalValidator<E: Pairing> {
pub public_key: PublicKey<E>,
}

impl<E: Pairing> ExternalValidator<E> {
pub fn new(address: String, public_key: PublicKey<E>) -> Self {
Self {
address,
public_key,
}
}
}

#[derive(Clone, Debug)]
pub struct Validator<E: Pairing> {
pub validator: ExternalValidator<E>,
Expand Down
33 changes: 20 additions & 13 deletions ferveo-python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ pub fn encrypt(
aad: &[u8],
public_key: &DkgPublicKey,
) -> PyResult<Ciphertext> {
let ciphertext = ferveo::api::encrypt(message, aad, &public_key.0)
let rng = &mut thread_rng();
let ciphertext = ferveo::api::encrypt(message, aad, &public_key.0, rng)
.map_err(|err| PyValueError::new_err(format!("{}", err)))?;
Ok(Ciphertext(ciphertext))
}
Expand All @@ -23,7 +24,7 @@ pub fn combine_decryption_shares(shares: Vec<DecryptionShare>) -> SharedSecret {
.iter()
.map(|share| share.0.clone())
.collect::<Vec<_>>();
SharedSecret(ferveo::api::combine_decryption_shares(&shares))
SharedSecret(ferveo::api::share_combine_simple_precomputed(&shares))
}

#[pyfunction]
Expand All @@ -43,11 +44,11 @@ pub fn decrypt_with_shared_secret(
}

#[pyclass(module = "ferveo")]
#[derive(derive_more::From, derive_more::AsRef)]
#[derive(derive_more::AsRef)]
pub struct G1Prepared(ferveo::api::G1Prepared);

#[pyclass(module = "ferveo")]
#[derive(derive_more::From, derive_more::AsRef)]
#[derive(derive_more::AsRef)]
pub struct SharedSecret(ferveo::api::SharedSecret);

#[pyclass(module = "ferveo")]
Expand All @@ -61,6 +62,8 @@ impl Keypair {
Self(ferveo::api::Keypair::new(&mut thread_rng()))
}

// TODO: Consider moving from_bytes and __bytes__ to a separate trait

#[staticmethod]
pub fn from_bytes(bytes: &[u8]) -> PyResult<Self> {
let keypair = ferveo::api::Keypair::from_bytes(bytes)
Expand Down Expand Up @@ -106,7 +109,7 @@ impl PublicKey {

#[pyclass(module = "ferveo")]
#[derive(Clone, derive_more::From, derive_more::AsRef)]
pub struct ExternalValidator(ferveo::api::ExternalValidator);
pub struct ExternalValidator(ferveo::api::ExternalValidator<E>);

#[pymethods]
impl ExternalValidator {
Expand All @@ -118,7 +121,7 @@ impl ExternalValidator {

#[pyclass(module = "ferveo")]
#[derive(Clone, derive_more::From, derive_more::AsRef)]
pub struct Transcript(ferveo::api::Transcript);
pub struct Transcript(ferveo::api::Transcript<E>);

#[pymethods]
impl Transcript {
Expand Down Expand Up @@ -214,13 +217,17 @@ impl AggregatedTranscript {
ciphertext: &Ciphertext,
aad: &[u8],
validator_keypair: &Keypair,
) -> DecryptionShare {
DecryptionShare(self.0.create_decryption_share(
&dkg.0,
&ciphertext.0,
aad,
&validator_keypair.0,
))
) -> PyResult<DecryptionShare> {
let decryption_share = self
.0
.create_decryption_share(
&dkg.0,
&ciphertext.0,
aad,
&validator_keypair.0,
)
.map_err(|err| PyValueError::new_err(format!("{}", err)))?;
Ok(DecryptionShare(decryption_share))
}

#[staticmethod]
Expand Down
147 changes: 38 additions & 109 deletions ferveo/src/api.rs
Original file line number Diff line number Diff line change
@@ -1,79 +1,18 @@
use ark_poly::EvaluationDomain;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use bincode::Options;
use ferveo_common::serialization::ser::serialize;
pub use ferveo_common::{Keypair, PublicKey};
pub use ferveo_common::{ExternalValidator, Keypair, PublicKey};
use group_threshold_cryptography as tpke;
use group_threshold_cryptography::api::TpkeResult;
use rand::rngs::StdRng;
use rand::{thread_rng, RngCore, SeedableRng};
use serde::{Deserialize, Serialize};
pub use tpke::api::{
decrypt_with_shared_secret, encrypt, share_combine_simple_precomputed,
Ciphertext, DecryptionShareSimplePrecomputed as DecryptionShare,
DkgPublicKey, G1Prepared, Result, SharedSecret, UnblindingKey, E,
};

pub type E = ark_bls12_381::Bls12_381;

pub fn encrypt(
message: &[u8],
aad: &[u8],
public_key: &DkgPublicKey,
) -> TpkeResult<Ciphertext> {
Ok(Ciphertext(tpke::api::encrypt(message, aad, &public_key.0)?))
}

pub fn combine_decryption_shares(
decryption_shares: &[DecryptionShare],
) -> SharedSecret {
let shares = decryption_shares
.iter()
.map(|share| share.0.clone())
.collect::<Vec<_>>();
SharedSecret(tpke::share_combine_simple_precomputed::<E>(&shares))
}

pub fn decrypt_with_shared_secret(
ciphertext: &Ciphertext,
aad: &[u8],
shared_secret: &SharedSecret,
g_inv: &G1Prepared,
) -> TpkeResult<Vec<u8>> {
tpke::api::decrypt_with_shared_secret(
&ciphertext.0,
aad,
&shared_secret.0,
&g_inv.0,
)
}

pub struct G1Prepared(pub tpke::api::TpkeG1Prepared);

pub struct SharedSecret(tpke::api::TpkeSharedSecret);

#[derive(Clone)]
pub struct ExternalValidator(ferveo_common::ExternalValidator<E>);

impl ExternalValidator {
pub fn new(address: String, public_key: PublicKey<E>) -> Self {
Self(ferveo_common::ExternalValidator {
address,
public_key,
})
}
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Transcript(crate::PubliclyVerifiableSS<E>);

impl Transcript {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, crate::Error> {
Ok(Self(bincode::deserialize(bytes)?))
}

pub fn to_bytes(&self) -> Result<Vec<u8>, crate::Error> {
Ok(bincode::serialize(&self.0)?)
}
}

#[derive(Clone)]
pub struct DkgPublicKey(pub tpke::api::TpkeDkgPublicKey);
pub use crate::PubliclyVerifiableSS as Transcript;

#[derive(Clone)]
pub struct Dkg(crate::PubliclyVerifiableDkg<E>);
Expand All @@ -83,14 +22,9 @@ impl Dkg {
tau: u64,
shares_num: u32,
security_threshold: u32,
validators: &[ExternalValidator],
me: &ExternalValidator,
) -> Result<Self, crate::Error> {
let validators = &validators
.iter()
.map(|v| v.0.clone())
.collect::<Vec<ferveo_common::ExternalValidator<E>>>();
let me = &me.0;
validators: &[ExternalValidator<E>],
me: &ExternalValidator<E>,
) -> Result<Self> {
let params = crate::Params {
tau,
security_threshold,
Expand All @@ -109,36 +43,29 @@ impl Dkg {
}

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

pub fn generate_transcript<R: RngCore>(
&self,
rng: &mut R,
) -> Result<Transcript, crate::Error> {
Ok(Transcript(self.0.create_share(rng)?))
) -> Result<crate::PubliclyVerifiableSS<E>> {
self.0.create_share(rng)
}

pub fn aggregate_transcripts(
&mut self,
messages: &Vec<(ExternalValidator, Transcript)>,
) -> Result<AggregatedTranscript, crate::Error> {
messages: &Vec<(ExternalValidator<E>, Transcript<E>)>,
) -> Result<AggregatedTranscript> {
// Avoid mutating current state
// TODO: Rewrite `deal` to not require mutability after validating this API design
for (validator, transcript) in messages {
self.0.deal(validator.0.clone(), transcript.0.clone())?;
self.0.deal(validator.clone(), transcript.clone())?;
}
Ok(AggregatedTranscript(crate::pvss::aggregate(&self.0)))
}
}

pub struct Ciphertext(pub tpke::api::Ciphertext);

pub struct UnblindingKey(tpke::api::TpkeUnblindingKey);

#[derive(Clone)]
pub struct DecryptionShare(tpke::api::TpkeDecryptionShareSimplePrecomputed);

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct AggregatedTranscript(
crate::PubliclyVerifiableSS<E, crate::Aggregated>,
Expand All @@ -155,23 +82,23 @@ impl AggregatedTranscript {
ciphertext: &Ciphertext,
aad: &[u8],
validator_keypair: &Keypair<E>,
) -> DecryptionShare {
) -> Result<DecryptionShare> {
let domain_points: Vec<_> = dkg.0.domain.elements().collect();
DecryptionShare(self.0.make_decryption_share_simple_precomputed(
&ciphertext.0 .0,
self.0.make_decryption_share_simple_precomputed(
ciphertext,
aad,
&validator_keypair.decryption_key,
dkg.0.me,
&domain_points,
&dkg.0.pvss_params.g_inv(),
))
)
}

pub fn from_bytes(bytes: &[u8]) -> Result<Self, crate::Error> {
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
Ok(Self(bincode::deserialize(bytes)?))
}

pub fn to_bytes(&self) -> Result<Vec<u8>, crate::Error> {
pub fn to_bytes(&self) -> Result<Vec<u8>> {
Ok(bincode::serialize(&self.0)?)
}
}
Expand Down Expand Up @@ -207,11 +134,9 @@ mod test_ferveo_api {
let validators = validator_keypairs
.iter()
.enumerate()
.map(|(i, keypair)| {
ExternalValidator(ferveo_common::ExternalValidator {
address: format!("validator-{}", i),
public_key: keypair.public(),
})
.map(|(i, keypair)| ExternalValidator {
address: format!("validator-{}", i),
public_key: keypair.public(),
})
.collect::<Vec<_>>();

Expand Down Expand Up @@ -246,7 +171,8 @@ mod test_ferveo_api {
// In the meantime, the client creates a ciphertext and decryption request
let msg: &[u8] = "abc".as_bytes();
let aad: &[u8] = "my-aad".as_bytes();
let ciphertext = encrypt(msg, aad, &public_key).unwrap();
let rng = &mut thread_rng();
let ciphertext = encrypt(msg, aad, &public_key, rng).unwrap();

// Having aggregated the transcripts, the validators can now create decryption shares
let decryption_shares: Vec<_> = izip!(&validators, &validator_keypairs)
Expand All @@ -262,25 +188,28 @@ mod test_ferveo_api {
.unwrap();
let aggregate = dkg.aggregate_transcripts(&messages).unwrap();
assert!(pvss_aggregated.validate(&dkg));
aggregate.create_decryption_share(
&dkg,
&ciphertext,
aad,
validator_keypair,
)
aggregate
.create_decryption_share(
&dkg,
&ciphertext,
aad,
validator_keypair,
)
.unwrap()
})
.collect();

// Now, the decryption share can be used to decrypt the ciphertext
// This part is part of the client API

let shared_secret = combine_decryption_shares(&decryption_shares);
let shared_secret =
share_combine_simple_precomputed(&decryption_shares);

let plaintext = decrypt_with_shared_secret(
&ciphertext,
aad,
&shared_secret,
&G1Prepared(dkg.0.pvss_params.g_inv()),
&dkg.0.pvss_params.g_inv(),
)
.unwrap();
assert_eq!(plaintext, msg);
Expand Down
Loading

0 comments on commit 0b95048

Please sign in to comment.