Skip to content

Commit

Permalink
draft new ciphertext api
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-roslaniec committed Aug 14, 2023
1 parent 03b4e35 commit 5062f40
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 23 deletions.
1 change: 1 addition & 0 deletions ferveo-python/ferveo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
Transcript,
Dkg,
Ciphertext,
CiphertextHeader,
DecryptionShareSimple,
DecryptionSharePrecomputed,
AggregatedTranscript,
Expand Down
13 changes: 13 additions & 0 deletions ferveo-python/ferveo/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,19 @@ class Dkg:

@final
class Ciphertext:
header: CiphertextHeader
payload: bytes

@staticmethod
def from_bytes(data: bytes) -> Ciphertext:
...

def __bytes__(self) -> bytes:
...


@final
class CiphertextHeader:
@staticmethod
def from_bytes(data: bytes) -> Ciphertext:
...
Expand Down
62 changes: 41 additions & 21 deletions ferveo/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize};
use serde_with::serde_as;
pub use tpke::api::{
prepare_combine_simple, share_combine_precomputed, share_combine_simple,
Ciphertext, Fr, G1Affine, G1Prepared, SecretBox, E,
Fr, G1Affine, G1Prepared, G2Affine, SecretBox, E,
};

pub type PublicKey = ferveo_common::PublicKey<E>;
Expand Down Expand Up @@ -55,7 +55,7 @@ pub fn encrypt(
) -> Result<Ciphertext> {
let mut rng = rand::thread_rng();
let ciphertext = tpke::api::encrypt(message, aad, &pubkey.0, &mut rng)?;
Ok(ciphertext)
Ok(Ciphertext(ciphertext))
}

pub fn decrypt_with_shared_secret(
Expand All @@ -65,14 +65,43 @@ pub fn decrypt_with_shared_secret(
) -> Result<Vec<u8>> {
let dkg_public_params = DkgPublicParameters::default();
tpke::api::decrypt_with_shared_secret(
ciphertext,
&ciphertext.0,
aad,
&shared_secret.0,
&dkg_public_params.g1_inv,
)
.map_err(Error::from)
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Eq)]
pub struct Ciphertext(pub(crate) tpke::api::Ciphertext);

impl Ciphertext {
pub fn header(&self) -> CiphertextHeader {
let ciphertext_hash = self.0.ciphertext_hash();
CiphertextHeader {
commitment: self.0.commitment,
auth_tag: self.0.auth_tag,
ciphertext_hash,
}
}

pub fn payload(&self) -> Vec<u8> {
// TODO: Do we want to return a Vec<u8> here or rather obfuscate the type with a newtype/struct?
self.0.ciphertext.clone()
}
}

#[serde_as]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct CiphertextHeader {
#[serde_as(as = "serialization::SerdeAs")]
commitment: G1Affine,
#[serde_as(as = "serialization::SerdeAs")]
auth_tag: G2Affine,
ciphertext_hash: [u8; 32],
}

/// The ferveo variant to use for the decryption share derivation.
#[derive(
PartialEq, Eq, Debug, Serialize, Deserialize, Copy, Clone, PartialOrd,
Expand Down Expand Up @@ -297,7 +326,7 @@ impl AggregatedTranscript {
.take(dkg.0.dkg_params.shares_num as usize)
.collect();
self.0.make_decryption_share_simple_precomputed(
ciphertext,
&ciphertext.0,
aad,
&validator_keypair.decryption_key,
dkg.0.me.share_index,
Expand All @@ -314,7 +343,7 @@ impl AggregatedTranscript {
validator_keypair: &Keypair,
) -> Result<DecryptionShareSimple> {
let share = self.0.make_decryption_share_simple(
ciphertext,
&ciphertext.0,
aad,
&validator_keypair.decryption_key,
dkg.0.me.share_index,
Expand Down Expand Up @@ -458,14 +487,10 @@ mod test_ferveo_api {
// In the meantime, the client creates a ciphertext and decryption request
let msg = "my-msg".as_bytes().to_vec();
let aad: &[u8] = "my-aad".as_bytes();
let rng = &mut thread_rng();
let ciphertext = tpke::api::encrypt(
SecretBox::new(msg.clone()),
aad,
&dkg_public_key.0,
rng,
)
.unwrap();
let _rng = &mut thread_rng();
let ciphertext =
encrypt(SecretBox::new(msg.clone()), aad, &dkg_public_key)
.unwrap();

// Having aggregated the transcripts, the validators can now create decryption shares
let decryption_shares: Vec<_> =
Expand Down Expand Up @@ -557,14 +582,9 @@ mod test_ferveo_api {
// In the meantime, the client creates a ciphertext and decryption request
let msg = "my-msg".as_bytes().to_vec();
let aad: &[u8] = "my-aad".as_bytes();
let rng = &mut thread_rng();
let ciphertext = tpke::api::encrypt(
SecretBox::new(msg.clone()),
aad,
&public_key.0,
rng,
)
.unwrap();
let _rng = &mut thread_rng();
let ciphertext =
encrypt(SecretBox::new(msg.clone()), aad, &public_key).unwrap();

// Having aggregated the transcripts, the validators can now create decryption shares
let decryption_shares: Vec<_> =
Expand Down
30 changes: 30 additions & 0 deletions ferveo/src/bindings_python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,37 @@ impl Dkg {
)]
pub struct Ciphertext(api::Ciphertext);

#[pymethods]
impl Ciphertext {
#[getter]
pub fn header(&self) -> CiphertextHeader {
CiphertextHeader(self.0.header())
}

#[getter]
pub fn payload(&self) -> Vec<u8> {
self.0.payload().to_vec()
}
}

generate_bytes_serialization!(Ciphertext);

#[pyclass(module = "ferveo")]
#[derive(
Clone,
Debug,
PartialEq,
Eq,
Serialize,
Deserialize,
derive_more::From,
derive_more::AsRef,
derive_more::Into,
)]
pub struct CiphertextHeader(api::CiphertextHeader);

generate_bytes_serialization!(CiphertextHeader);

#[pyclass(module = "ferveo")]
#[derive(Clone, derive_more::AsRef, derive_more::From)]
pub struct DecryptionShareSimple(api::DecryptionShareSimple);
Expand Down Expand Up @@ -631,6 +660,7 @@ pub fn make_ferveo_py_module(py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_class::<Transcript>()?;
m.add_class::<Dkg>()?;
m.add_class::<Ciphertext>()?;
m.add_class::<CiphertextHeader>()?;
m.add_class::<DecryptionShareSimple>()?;
m.add_class::<DecryptionSharePrecomputed>()?;
m.add_class::<AggregatedTranscript>()?;
Expand Down
1 change: 1 addition & 0 deletions tpke/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pub type E = ark_bls12_381::Bls12_381;
pub type G1Prepared = <E as ark_ec::pairing::Pairing>::G1Prepared;
pub type G1Affine = <E as ark_ec::pairing::Pairing>::G1Affine;
pub type G2Affine = <E as ark_ec::pairing::Pairing>::G2Affine;
pub type Fr = ark_bls12_381::Fr;
pub type PrivateKey = ark_bls12_381::G2Affine;
pub type Result<T> = crate::Result<T>;
Expand Down
8 changes: 6 additions & 2 deletions tpke/src/ciphertext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ impl<E: Pairing> Ciphertext<E> {
+ self.auth_tag.serialized_size(Compress::No)
+ self.ciphertext.len()
}

pub fn ciphertext_hash(&self) -> [u8; 32] {
sha256(&self.ciphertext)
}
}

pub fn encrypt<E: Pairing>(
Expand Down Expand Up @@ -165,11 +169,11 @@ pub fn decrypt_with_shared_secret<E: Pairing>(
decrypt_with_shared_secret_unchecked(ciphertext, shared_secret)
}

fn sha256(input: &[u8]) -> Vec<u8> {
fn sha256(input: &[u8]) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(input);
let result = hasher.finalize();
result.to_vec()
result.into()
}

pub fn shared_secret_to_chacha<E: Pairing>(
Expand Down

0 comments on commit 5062f40

Please sign in to comment.