Skip to content

Commit

Permalink
Merge pull request #136 from nucypher/pk-static-bytes
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-roslaniec authored Jul 5, 2023
2 parents 2057782 + 3bc28d7 commit 2b64c2e
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 105 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ferveo-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ ark-ec = "0.4"
ark-serialize = { version = "0.4", features = ["derive"] }
ark-std = "0.4"
bincode = "1.3.3"
generic-array = "0.14.7"
rand = "0.8"
rand_core = "0.6"
serde = { version = "1.0", features = ["derive"] }
serde_with = "2.2.0"

Expand Down
48 changes: 27 additions & 21 deletions ferveo-common/src/keypair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,26 @@ use ark_std::{
rand::{prelude::StdRng, RngCore, SeedableRng},
UniformRand,
};
use rand_core::Error;
use generic_array::{typenum::U96, GenericArray};
use serde::*;
use serde_with::serde_as;

use crate::serialization;
use crate::{serialization, Error, Result};

// 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
// and Fr types. So instead, we're using this shared utility function:
pub fn to_bytes<T: CanonicalSerialize>(
item: &T,
) -> Result<Vec<u8>, ark_serialize::SerializationError> {
pub fn to_bytes<T: CanonicalSerialize>(item: &T) -> Result<Vec<u8>> {
let mut writer = Vec::new();
item.serialize_compressed(&mut writer)?;
item.serialize_compressed(&mut writer)
.map_err(Error::SerializationError)?;
Ok(writer)
}

pub fn from_bytes<T: CanonicalDeserialize>(
bytes: &[u8],
) -> Result<T, ark_serialize::SerializationError> {
pub fn from_bytes<T: CanonicalDeserialize>(bytes: &[u8]) -> Result<T> {
let mut reader = io::Cursor::new(bytes);
let item = T::deserialize_compressed(&mut reader)?;
let item = T::deserialize_compressed(&mut reader)
.map_err(Error::SerializationError)?;
Ok(item)
}

Expand All @@ -39,17 +37,25 @@ pub struct PublicKey<E: Pairing> {
}

impl<E: Pairing> PublicKey<E> {
pub fn to_bytes(
&self,
) -> Result<Vec<u8>, ark_serialize::SerializationError> {
to_bytes(&self.encryption_key)
pub fn to_bytes(&self) -> Result<GenericArray<u8, U96>> {
let as_bytes = to_bytes(&self.encryption_key)?;
Ok(GenericArray::<u8, U96>::from_slice(&as_bytes).to_owned())
}

pub fn from_bytes(
bytes: &[u8],
) -> Result<Self, ark_serialize::SerializationError> {
let encryption_key = from_bytes(bytes)?;
Ok(PublicKey::<E> { encryption_key })
pub fn from_bytes(bytes: &[u8]) -> Result<PublicKey<E>> {
let bytes =
GenericArray::<u8, U96>::from_exact_iter(bytes.iter().cloned())
.ok_or_else(|| {
Error::InvalidByteLength(
Self::serialized_size(),
bytes.len(),
)
})?;
from_bytes(&bytes).map(|encryption_key| PublicKey { encryption_key })
}

pub fn serialized_size() -> usize {
96
}
}

Expand Down Expand Up @@ -129,9 +135,9 @@ impl<E: Pairing> Keypair<E> {
32
}

pub fn from_secure_randomness(bytes: &[u8]) -> Result<Self, Error> {
pub fn from_secure_randomness(bytes: &[u8]) -> Result<Self> {
if bytes.len() != Self::secure_randomness_size() {
return Err(Error::new("Invalid seed length"));
return Err(Error::InvalidSeedLength(bytes.len()));
}
let mut seed = [0; 32];
seed.copy_from_slice(bytes);
Expand Down
31 changes: 31 additions & 0 deletions ferveo-common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
pub mod keypair;
pub mod serialization;

use std::{fmt, fmt::Formatter};

pub use keypair::*;
pub use serialization::*;

#[derive(Debug)]
pub enum Error {
InvalidByteLength(usize, usize),
SerializationError(ark_serialize::SerializationError),
InvalidSeedLength(usize),
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Error::InvalidByteLength(expected, actual) => {
write!(
f,
"Invalid byte length: expected {}, actual {}",
expected, actual
)
}
Error::SerializationError(e) => {
write!(f, "Serialization error: {}", e)
}
Error::InvalidSeedLength(len) => {
write!(f, "Invalid seed length: {}", len)
}
}
}
}

type Result<T> = std::result::Result<T, Error>;
3 changes: 3 additions & 0 deletions ferveo-python/ferveo/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class FerveoPublicKey:
def __hash__(self) -> int:
...

def __richcmp__(self, other: FerveoPublicKey, op: int) -> bool:
...


class Validator:

Expand Down
34 changes: 27 additions & 7 deletions ferveo-python/test/test_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
Keypair,
Validator,
Dkg,
DkgPublicKey
DkgPublicKey,
FerveoPublicKey,
SharedSecret,
)


Expand Down Expand Up @@ -34,26 +36,44 @@ def make_dkg_public_key():


def make_shared_secret():
# TODO: implement this
# TODO: Implement this
# SharedSecret.from_bytes(os.urandom(584))
pass


def make_pk():
return Keypair.random().public_key()


# def test_shared_secret_serialization():
# shared_secret = create_shared_secret_instance()
# shared_secret = make_shared_secret()
# serialized = bytes(shared_secret)
# deserialized = SharedSecret.from_bytes(serialized)
# TODO: Implement comparison
# assert shared_secret == deserialized
# # TODO: Implement __richcmp__
# # assert shared_secret == deserialized
# assert serialized == bytes(deserialized)

def test_keypair_serialization():
keypair = Keypair.random()
serialized = bytes(keypair)
deserialized = Keypair.from_bytes(serialized)
# TODO: Implement comparison
# assert keypair == deserialized
# TODO: Implement __richcmp__
# assert serialized == deserialized
assert serialized == bytes(deserialized)


def test_dkg_public_key_serialization():
dkg_pk = make_dkg_public_key()
serialized = bytes(dkg_pk)
deserialized = DkgPublicKey.from_bytes(serialized)
# TODO: Implement __richcmp__
assert serialized == bytes(deserialized)
assert len(serialized) == DkgPublicKey.serialized_size()


def test_public_key_serialization():
pk = make_pk()
serialized = bytes(pk)
deserialized = FerveoPublicKey.from_bytes(serialized)
assert pk == deserialized
assert len(serialized) == FerveoPublicKey.serialized_size()
17 changes: 15 additions & 2 deletions ferveo/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,12 @@ impl DkgPublicKey {
pub fn from_bytes(bytes: &[u8]) -> Result<DkgPublicKey> {
let bytes =
GenericArray::<u8, U48>::from_exact_iter(bytes.iter().cloned())
.ok_or(Error::InvalidByteLength(48, bytes.len()))?;
.ok_or_else(|| {
Error::InvalidByteLength(
Self::serialized_size(),
bytes.len(),
)
})?;
from_bytes(&bytes).map(DkgPublicKey)
}

Expand Down Expand Up @@ -198,7 +203,7 @@ impl AggregatedTranscript {
shares_num: u32,
messages: &[ValidatorMessage],
) -> Result<bool> {
let pvss_params = crate::pvss::PubliclyVerifiableParams::<E>::default();
let pvss_params = PubliclyVerifiableParams::<E>::default();
let domain = Radix2EvaluationDomain::<Fr>::new(shares_num as usize)
.expect("Unable to construct an evaluation domain");

Expand Down Expand Up @@ -357,6 +362,14 @@ mod test_ferveo_api {
(messages, validators, validator_keypairs)
}

#[test]
fn test_dkg_pk_serialization() {
let dkg_pk = DkgPublicKey::random();
let serialized = dkg_pk.to_bytes().unwrap();
let deserialized = DkgPublicKey::from_bytes(&serialized).unwrap();
assert_eq!(dkg_pk, deserialized);
}

#[test]
fn test_server_api_tdec_precomputed() {
let rng = &mut StdRng::seed_from_u64(0);
Expand Down
Loading

0 comments on commit 2b64c2e

Please sign in to comment.