From 0c66e16010f8194a02a1beeb234a27fbce4da416 Mon Sep 17 00:00:00 2001 From: Andreas Fackler Date: Thu, 21 Jun 2018 17:31:15 +0200 Subject: [PATCH] Remove generic E: Engine from crypto. --- mod.rs | 235 ++++++++++++++++++++--------------------------- poly.rs | 183 +++++++++++++++++------------------- protobuf_impl.rs | 7 +- 3 files changed, 188 insertions(+), 237 deletions(-) diff --git a/mod.rs b/mod.rs index 9fa2678..cb3ba31 100644 --- a/mod.rs +++ b/mod.rs @@ -1,3 +1,7 @@ +// Clippy warns that it's dangerous to derive `PartialEq` and explicitly implement `Hash`, but the +// `pairing::bls12_381` types don't implement `Hash`, so we can't derive it. +#![cfg_attr(feature = "cargo-clippy", allow(derive_hash_xor_eq))] + pub mod error; pub mod poly; #[cfg(feature = "serialization-protobuf")] @@ -10,6 +14,7 @@ use std::hash::{Hash, Hasher}; use byteorder::{BigEndian, ByteOrder}; use clear_on_drop::ClearOnDrop; use init_with::InitWith; +use pairing::bls12_381::{Bls12, Fr, FrRepr, G1, G1Affine, G2, G2Affine}; use pairing::{CurveAffine, CurveProjective, Engine, Field, PrimeField}; use rand::{ChaChaRng, OsRng, Rng, SeedableRng}; use ring::digest; @@ -24,48 +29,42 @@ const CHACHA_RNG_SEED_SIZE: usize = 8; const ERR_OS_RNG: &str = "could not initialize the OS random number generator"; /// A public key, or a public key share. -#[derive(Deserialize, Serialize, Clone, Debug)] -pub struct PublicKey(#[serde(with = "serde_impl::projective")] E::G1); - -impl PartialEq for PublicKey { - fn eq(&self, other: &PublicKey) -> bool { - self.0 == other.0 - } -} +#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)] +pub struct PublicKey(#[serde(with = "serde_impl::projective")] G1); -impl Hash for PublicKey { +impl Hash for PublicKey { fn hash(&self, state: &mut H) { self.0.into_affine().into_compressed().as_ref().hash(state); } } -impl PublicKey { - /// Returns `true` if the signature matches the element of `E::G2`. - pub fn verify_g2>(&self, sig: &Signature, hash: H) -> bool { - E::pairing(self.0, hash) == E::pairing(E::G1Affine::one(), sig.0) +impl PublicKey { + /// Returns `true` if the signature matches the element of `G2`. + pub fn verify_g2>(&self, sig: &Signature, hash: H) -> bool { + Bls12::pairing(self.0, hash) == Bls12::pairing(G1Affine::one(), sig.0) } /// Returns `true` if the signature matches the message. - pub fn verify>(&self, sig: &Signature, msg: M) -> bool { - self.verify_g2(sig, hash_g2::(msg)) + pub fn verify>(&self, sig: &Signature, msg: M) -> bool { + self.verify_g2(sig, hash_g2(msg)) } /// Returns `true` if the decryption share matches the ciphertext. - pub fn verify_decryption_share(&self, share: &DecryptionShare, ct: &Ciphertext) -> bool { + pub fn verify_decryption_share(&self, share: &DecryptionShare, ct: &Ciphertext) -> bool { let Ciphertext(ref u, ref v, ref w) = *ct; - let hash = hash_g1_g2::(*u, v); - E::pairing(share.0, hash) == E::pairing(self.0, *w) + let hash = hash_g1_g2(*u, v); + Bls12::pairing(share.0, hash) == Bls12::pairing(self.0, *w) } /// Encrypts the message. - pub fn encrypt>(&self, msg: M) -> Ciphertext { - let r: E::Fr = OsRng::new().expect(ERR_OS_RNG).gen(); - let u = E::G1Affine::one().mul(r); + pub fn encrypt>(&self, msg: M) -> Ciphertext { + let r: Fr = OsRng::new().expect(ERR_OS_RNG).gen(); + let u = G1Affine::one().mul(r); let v: Vec = { let g = self.0.into_affine().mul(r); - xor_vec(&hash_bytes::(g, msg.as_ref().len()), msg.as_ref()) + xor_vec(&hash_bytes(g, msg.as_ref().len()), msg.as_ref()) }; - let w = hash_g1_g2::(u, &v).into_affine().mul(r); + let w = hash_g1_g2(u, &v).into_affine().mul(r); Ciphertext(u, v, w) } @@ -76,10 +75,10 @@ impl PublicKey { } /// A signature, or a signature share. -#[derive(Deserialize, Serialize, Clone)] -pub struct Signature(#[serde(with = "serde_impl::projective")] E::G2); +#[derive(Deserialize, Serialize, Clone, PartialEq, Eq)] +pub struct Signature(#[serde(with = "serde_impl::projective")] G2); -impl fmt::Debug for Signature { +impl fmt::Debug for Signature { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let uncomp = self.0.into_affine().into_uncompressed(); let bytes = uncomp.as_ref(); @@ -87,19 +86,13 @@ impl fmt::Debug for Signature { } } -impl PartialEq for Signature { - fn eq(&self, other: &Signature) -> bool { - self.0 == other.0 - } -} - -impl Hash for Signature { +impl Hash for Signature { fn hash(&self, state: &mut H) { self.0.into_affine().into_compressed().as_ref().hash(state); } } -impl Signature { +impl Signature { pub fn parity(&self) -> bool { let uncomp = self.0.into_affine().into_uncompressed(); let bytes = uncomp.as_ref(); @@ -111,58 +104,52 @@ impl Signature { } /// A secret key, or a secret key share. -#[derive(Debug)] -pub struct SecretKey(E::Fr); +#[derive(Debug, PartialEq, Eq)] +pub struct SecretKey(Fr); -impl PartialEq for SecretKey { - fn eq(&self, other: &SecretKey) -> bool { - self.0 == other.0 - } -} - -impl Default for SecretKey { +impl Default for SecretKey { fn default() -> Self { - SecretKey(E::Fr::zero()) + SecretKey(Fr::zero()) } } -impl SecretKey { +impl SecretKey { /// Creates a new secret key. pub fn new(rng: &mut R) -> Self { SecretKey(rng.gen()) } - pub fn from_value(f: E::Fr) -> Self { + pub fn from_value(f: Fr) -> Self { SecretKey(f) } /// Returns the matching public key. - pub fn public_key(&self) -> PublicKey { - PublicKey(E::G1Affine::one().mul(self.0)) + pub fn public_key(&self) -> PublicKey { + PublicKey(G1Affine::one().mul(self.0)) } - /// Signs the given element of `E::G2`. - pub fn sign_g2>(&self, hash: H) -> Signature { + /// Signs the given element of `G2`. + pub fn sign_g2>(&self, hash: H) -> Signature { Signature(hash.into().mul(self.0)) } /// Signs the given message. - pub fn sign>(&self, msg: M) -> Signature { - self.sign_g2(hash_g2::(msg)) + pub fn sign>(&self, msg: M) -> Signature { + self.sign_g2(hash_g2(msg)) } /// Returns the decrypted text, or `None`, if the ciphertext isn't valid. - pub fn decrypt(&self, ct: &Ciphertext) -> Option> { + pub fn decrypt(&self, ct: &Ciphertext) -> Option> { if !ct.verify() { return None; } let Ciphertext(ref u, ref v, _) = *ct; let g = u.into_affine().mul(self.0); - Some(xor_vec(&hash_bytes::(g, v.len()), v)) + Some(xor_vec(&hash_bytes(g, v.len()), v)) } /// Returns a decryption share, or `None`, if the ciphertext isn't valid. - pub fn decrypt_share(&self, ct: &Ciphertext) -> Option> { + pub fn decrypt_share(&self, ct: &Ciphertext) -> Option { if !ct.verify() { return None; } @@ -171,20 +158,14 @@ impl SecretKey { } /// An encrypted message. -#[derive(Deserialize, Serialize, Debug, Clone)] -pub struct Ciphertext( - #[serde(with = "serde_impl::projective")] E::G1, +#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)] +pub struct Ciphertext( + #[serde(with = "serde_impl::projective")] G1, Vec, - #[serde(with = "serde_impl::projective")] E::G2, + #[serde(with = "serde_impl::projective")] G2, ); -impl PartialEq for Ciphertext { - fn eq(&self, other: &Ciphertext) -> bool { - self.0 == other.0 && self.1 == other.1 && self.2 == other.2 - } -} - -impl Hash for Ciphertext { +impl Hash for Ciphertext { fn hash(&self, state: &mut H) { let Ciphertext(ref u, ref v, ref w) = *self; u.into_affine().into_compressed().as_ref().hash(state); @@ -193,59 +174,47 @@ impl Hash for Ciphertext { } } -impl Ciphertext { +impl Ciphertext { /// Returns `true` if this is a valid ciphertext. This check is necessary to prevent /// chosen-ciphertext attacks. pub fn verify(&self) -> bool { let Ciphertext(ref u, ref v, ref w) = *self; - let hash = hash_g1_g2::(*u, v); - E::pairing(E::G1Affine::one(), *w) == E::pairing(*u, hash) + let hash = hash_g1_g2(*u, v); + Bls12::pairing(G1Affine::one(), *w) == Bls12::pairing(*u, hash) } } /// A decryption share. A threshold of decryption shares can be used to decrypt a message. -#[derive(Deserialize, Serialize, Debug)] -pub struct DecryptionShare(#[serde(with = "serde_impl::projective")] E::G1); - -impl PartialEq for DecryptionShare { - fn eq(&self, other: &DecryptionShare) -> bool { - self.0 == other.0 - } -} +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)] +pub struct DecryptionShare(#[serde(with = "serde_impl::projective")] G1); -impl Hash for DecryptionShare { +impl Hash for DecryptionShare { fn hash(&self, state: &mut H) { self.0.into_affine().into_compressed().as_ref().hash(state); } } /// A public key and an associated set of public key shares. -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct PublicKeySet { +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +pub struct PublicKeySet { /// The coefficients of a polynomial whose value at `0` is the "master key", and value at /// `i + 1` is key share number `i`. - commit: Commitment, + commit: Commitment, } -impl PartialEq for PublicKeySet { - fn eq(&self, other: &Self) -> bool { - self.commit == other.commit - } -} - -impl Hash for PublicKeySet { +impl Hash for PublicKeySet { fn hash(&self, state: &mut H) { self.commit.hash(state); } } -impl From> for PublicKeySet { - fn from(commit: Commitment) -> PublicKeySet { +impl From for PublicKeySet { + fn from(commit: Commitment) -> PublicKeySet { PublicKeySet { commit } } } -impl PublicKeySet { +impl PublicKeySet { /// Returns the threshold `t`: any set of `t + 1` signature shares can be combined into a full /// signature. pub fn threshold(&self) -> usize { @@ -253,51 +222,51 @@ impl PublicKeySet { } /// Returns the public key. - pub fn public_key(&self) -> PublicKey { + pub fn public_key(&self) -> PublicKey { PublicKey(self.commit.evaluate(0)) } /// Returns the `i`-th public key share. - pub fn public_key_share::Repr>>(&self, i: T) -> PublicKey { - PublicKey(self.commit.evaluate(from_repr_plus_1::(i.into()))) + pub fn public_key_share>(&self, i: T) -> PublicKey { + PublicKey(self.commit.evaluate(from_repr_plus_1::(i.into()))) } /// Combines the shares into a signature that can be verified with the main public key. - pub fn combine_signatures<'a, ITR, IND>(&self, shares: ITR) -> Result> + pub fn combine_signatures<'a, ITR, IND>(&self, shares: ITR) -> Result where - ITR: IntoIterator)>, - IND: Into<::Repr> + Clone + 'a, + ITR: IntoIterator, + IND: Into + Clone + 'a, { let samples = shares.into_iter().map(|(i, share)| (i, &share.0)); Ok(Signature(interpolate(self.commit.degree() + 1, samples)?)) } /// Combines the shares to decrypt the ciphertext. - pub fn decrypt<'a, ITR, IND>(&self, shares: ITR, ct: &Ciphertext) -> Result> + pub fn decrypt<'a, ITR, IND>(&self, shares: ITR, ct: &Ciphertext) -> Result> where - ITR: IntoIterator)>, - IND: Into<::Repr> + Clone + 'a, + ITR: IntoIterator, + IND: Into + Clone + 'a, { let samples = shares.into_iter().map(|(i, share)| (i, &share.0)); let g = interpolate(self.commit.degree() + 1, samples)?; - Ok(xor_vec(&hash_bytes::(g, ct.1.len()), &ct.1)) + Ok(xor_vec(&hash_bytes(g, ct.1.len()), &ct.1)) } } /// A secret key and an associated set of secret key shares. -pub struct SecretKeySet { +pub struct SecretKeySet { /// The coefficients of a polynomial whose value at `0` is the "master key", and value at /// `i + 1` is key share number `i`. - poly: Poly, + poly: Poly, } -impl From> for SecretKeySet { - fn from(poly: Poly) -> SecretKeySet { +impl From for SecretKeySet { + fn from(poly: Poly) -> SecretKeySet { SecretKeySet { poly } } } -impl SecretKeySet { +impl SecretKeySet { /// Creates a set of secret key shares, where any `threshold + 1` of them can collaboratively /// sign and decrypt. pub fn random(threshold: usize, rng: &mut R) -> Self { @@ -313,17 +282,14 @@ impl SecretKeySet { } /// Returns the `i`-th secret key share. - pub fn secret_key_share(&self, i: T) -> ClearOnDrop>> - where - T: Into<::Repr>, - { + pub fn secret_key_share>(&self, i: T) -> ClearOnDrop> { ClearOnDrop::new(Box::new(SecretKey( - self.poly.evaluate(from_repr_plus_1::(i.into())), + self.poly.evaluate(from_repr_plus_1::(i.into())), ))) } /// Returns the corresponding public key set. That information can be shared publicly. - pub fn public_keys(&self) -> PublicKeySet { + pub fn public_keys(&self) -> PublicKeySet { PublicKeySet { commit: self.poly.commitment(), } @@ -331,13 +297,13 @@ impl SecretKeySet { /// Returns the secret master key. #[cfg(test)] - fn secret_key(&self) -> SecretKey { + fn secret_key(&self) -> SecretKey { SecretKey(self.poly.evaluate(0)) } } /// Returns a hash of the given message in `G2`. -fn hash_g2>(msg: M) -> E::G2 { +fn hash_g2>(msg: M) -> G2 { let digest = digest::digest(&digest::SHA256, msg.as_ref()); let seed = <[u32; CHACHA_RNG_SEED_SIZE]>::init_with_indices(|i| { BigEndian::read_u32(&digest.as_ref()[(4 * i)..(4 * i + 4)]) @@ -347,7 +313,7 @@ fn hash_g2>(msg: M) -> E::G2 { } /// Returns a hash of the group element and message, in the second group. -fn hash_g1_g2>(g1: E::G1, msg: M) -> E::G2 { +fn hash_g1_g2>(g1: G1, msg: M) -> G2 { // If the message is large, hash it, otherwise copy it. // TODO: Benchmark and optimize the threshold. let mut msg = if msg.as_ref().len() > 64 { @@ -357,11 +323,11 @@ fn hash_g1_g2>(g1: E::G1, msg: M) -> E::G2 { msg.as_ref().to_vec() }; msg.extend(g1.into_affine().into_compressed().as_ref()); - hash_g2::(&msg) + hash_g2(&msg) } /// Returns a hash of the group element with the specified length in bytes. -fn hash_bytes(g1: E::G1, len: usize) -> Vec { +fn hash_bytes(g1: G1, len: usize) -> Vec { let digest = digest::digest(&digest::SHA256, g1.into_affine().into_compressed().as_ref()); let seed = <[u32; CHACHA_RNG_SEED_SIZE]>::init_with_indices(|i| { BigEndian::read_u32(&digest.as_ref()[(4 * i)..(4 * i + 4)]) @@ -423,14 +389,13 @@ mod tests { use std::collections::BTreeMap; - use pairing::bls12_381::Bls12; use rand; #[test] fn test_simple_sig() { let mut rng = rand::thread_rng(); - let sk0 = SecretKey::::new(&mut rng); - let sk1 = SecretKey::::new(&mut rng); + let sk0 = SecretKey::new(&mut rng); + let sk1 = SecretKey::new(&mut rng); let pk0 = sk0.public_key(); let msg0 = b"Real news"; let msg1 = b"Fake news"; @@ -442,7 +407,7 @@ mod tests { #[test] fn test_threshold_sig() { let mut rng = rand::thread_rng(); - let sk_set = SecretKeySet::::random(3, &mut rng); + let sk_set = SecretKeySet::random(3, &mut rng); let pk_set = sk_set.public_keys(); // Make sure the keys are different, and the first coefficient is the main key. @@ -484,8 +449,8 @@ mod tests { #[test] fn test_simple_enc() { let mut rng = rand::thread_rng(); - let sk_bob = SecretKey::::new(&mut rng); - let sk_eve = SecretKey::::new(&mut rng); + let sk_bob = SecretKey::new(&mut rng); + let sk_eve = SecretKey::new(&mut rng); let pk_bob = sk_bob.public_key(); let msg = b"Muffins in the canteen today! Don't tell Eve!"; let ciphertext = pk_bob.encrypt(&msg[..]); @@ -501,7 +466,7 @@ mod tests { // Eve tries to trick Bob into decrypting `msg` xor `v`, but it doesn't validate. let Ciphertext(u, v, w) = ciphertext; - let fake_ciphertext = Ciphertext::(u, vec![0; v.len()], w); + let fake_ciphertext = Ciphertext(u, vec![0; v.len()], w); assert!(!fake_ciphertext.verify()); assert_eq!(None, sk_bob.decrypt(&fake_ciphertext)); } @@ -509,7 +474,7 @@ mod tests { #[test] fn test_threshold_enc() { let mut rng = rand::thread_rng(); - let sk_set = SecretKeySet::::random(3, &mut rng); + let sk_set = SecretKeySet::random(3, &mut rng); let pk_set = sk_set.public_keys(); let msg = b"Totally real news"; let ciphertext = pk_set.public_key().encrypt(&msg[..]); @@ -546,10 +511,9 @@ mod tests { let msg_end0: Vec = msg.iter().chain(b"end0").cloned().collect(); let msg_end1: Vec = msg.iter().chain(b"end1").cloned().collect(); - let hash = hash_g2::; - assert_eq!(hash(&msg), hash(&msg)); - assert_ne!(hash(&msg), hash(&msg_end0)); - assert_ne!(hash(&msg_end0), hash(&msg_end1)); + assert_eq!(hash_g2(&msg), hash_g2(&msg)); + assert_ne!(hash_g2(&msg), hash_g2(&msg_end0)); + assert_ne!(hash_g2(&msg_end0), hash_g2(&msg_end1)); } /// Some basic sanity checks for the `hash_g1_g2` function. @@ -562,11 +526,10 @@ mod tests { let g0 = rng.gen(); let g1 = rng.gen(); - let hash = hash_g1_g2::; - assert_eq!(hash(g0, &msg), hash(g0, &msg)); - assert_ne!(hash(g0, &msg), hash(g0, &msg_end0)); - assert_ne!(hash(g0, &msg_end0), hash(g0, &msg_end1)); - assert_ne!(hash(g0, &msg), hash(g1, &msg)); + assert_eq!(hash_g1_g2(g0, &msg), hash_g1_g2(g0, &msg)); + assert_ne!(hash_g1_g2(g0, &msg), hash_g1_g2(g0, &msg_end0)); + assert_ne!(hash_g1_g2(g0, &msg_end0), hash_g1_g2(g0, &msg_end1)); + assert_ne!(hash_g1_g2(g0, &msg), hash_g1_g2(g1, &msg)); } /// Some basic sanity checks for the `hash_bytes` function. @@ -575,7 +538,7 @@ mod tests { let mut rng = rand::thread_rng(); let g0 = rng.gen(); let g1 = rng.gen(); - let hash = hash_bytes::; + let hash = hash_bytes; assert_eq!(hash(g0, 5), hash(g0, 5)); assert_ne!(hash(g0, 5), hash(g1, 5)); assert_eq!(5, hash(g0, 5).len()); @@ -588,7 +551,7 @@ mod tests { use bincode; let mut rng = rand::thread_rng(); - let sk = SecretKey::::new(&mut rng); + let sk = SecretKey::new(&mut rng); let sig = sk.sign("Please sign here: ______"); let pk = sk.public_key(); let ser_pk = bincode::serialize(&pk).expect("serialize public key"); diff --git a/poly.rs b/poly.rs index 6ffc3ea..b58ad01 100644 --- a/poly.rs +++ b/poly.rs @@ -20,27 +20,22 @@ use std::borrow::Borrow; use std::hash::{Hash, Hasher}; use std::{cmp, iter, ops}; -use pairing::{CurveAffine, CurveProjective, Engine, Field, PrimeField}; +use pairing::bls12_381::{Fr, FrRepr, G1, G1Affine}; +use pairing::{CurveAffine, CurveProjective, Field, PrimeField}; use rand::Rng; /// A univariate polynomial in the prime field. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct Poly { +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct Poly { /// The coefficients of a polynomial. #[serde(with = "super::serde_impl::field_vec")] - coeff: Vec, + coeff: Vec, } -impl PartialEq for Poly { - fn eq(&self, other: &Self) -> bool { - self.coeff == other.coeff - } -} - -impl>, E: Engine> ops::AddAssign for Poly { +impl> ops::AddAssign for Poly { fn add_assign(&mut self, rhs: B) { let len = cmp::max(self.coeff.len(), rhs.borrow().coeff.len()); - self.coeff.resize(len, E::Fr::zero()); + self.coeff.resize(len, Fr::zero()); for (self_c, rhs_c) in self.coeff.iter_mut().zip(&rhs.borrow().coeff) { self_c.add_assign(rhs_c); } @@ -48,27 +43,27 @@ impl>, E: Engine> ops::AddAssign for Poly { } } -impl<'a, B: Borrow>, E: Engine> ops::Add for &'a Poly { - type Output = Poly; +impl<'a, B: Borrow> ops::Add for &'a Poly { + type Output = Poly; - fn add(self, rhs: B) -> Poly { + fn add(self, rhs: B) -> Poly { (*self).clone() + rhs } } -impl>, E: Engine> ops::Add for Poly { - type Output = Poly; +impl> ops::Add for Poly { + type Output = Poly; - fn add(mut self, rhs: B) -> Poly { + fn add(mut self, rhs: B) -> Poly { self += rhs; self } } -impl>, E: Engine> ops::SubAssign for Poly { +impl> ops::SubAssign for Poly { fn sub_assign(&mut self, rhs: B) { let len = cmp::max(self.coeff.len(), rhs.borrow().coeff.len()); - self.coeff.resize(len, E::Fr::zero()); + self.coeff.resize(len, Fr::zero()); for (self_c, rhs_c) in self.coeff.iter_mut().zip(&rhs.borrow().coeff) { self_c.sub_assign(rhs_c); } @@ -76,18 +71,18 @@ impl>, E: Engine> ops::SubAssign for Poly { } } -impl<'a, B: Borrow>, E: Engine> ops::Sub for &'a Poly { - type Output = Poly; +impl<'a, B: Borrow> ops::Sub for &'a Poly { + type Output = Poly; - fn sub(self, rhs: B) -> Poly { + fn sub(self, rhs: B) -> Poly { (*self).clone() - rhs } } -impl>, E: Engine> ops::Sub for Poly { - type Output = Poly; +impl> ops::Sub for Poly { + type Output = Poly; - fn sub(mut self, rhs: B) -> Poly { + fn sub(mut self, rhs: B) -> Poly { self -= rhs; self } @@ -95,13 +90,13 @@ impl>, E: Engine> ops::Sub for Poly { // Clippy thinks using any `+` and `-` in a `Mul` implementation is suspicious. #[cfg_attr(feature = "cargo-clippy", allow(suspicious_arithmetic_impl))] -impl<'a, B: Borrow>, E: Engine> ops::Mul for &'a Poly { - type Output = Poly; +impl<'a, B: Borrow> ops::Mul for &'a Poly { + type Output = Poly; fn mul(self, rhs: B) -> Self::Output { let coeff = (0..(self.coeff.len() + rhs.borrow().coeff.len() - 1)) .map(|i| { - let mut c = E::Fr::zero(); + let mut c = Fr::zero(); for j in i.saturating_sub(rhs.borrow().degree())..(1 + cmp::min(i, self.degree())) { let mut s = self.coeff[j]; s.mul_assign(&rhs.borrow().coeff[i - j]); @@ -114,21 +109,21 @@ impl<'a, B: Borrow>, E: Engine> ops::Mul for &'a Poly { } } -impl>, E: Engine> ops::Mul for Poly { - type Output = Poly; +impl> ops::Mul for Poly { + type Output = Poly; fn mul(self, rhs: B) -> Self::Output { &self * rhs } } -impl, E: Engine> ops::MulAssign for Poly { +impl> ops::MulAssign for Poly { fn mul_assign(&mut self, rhs: B) { *self = &*self * rhs; } } -impl Poly { +impl Poly { /// Creates a random polynomial. pub fn random(degree: usize, rng: &mut R) -> Self { Poly { @@ -147,7 +142,7 @@ impl Poly { } /// Returns the polynomial with constant value `c`. - pub fn constant(c: E::Fr) -> Self { + pub fn constant(c: Fr) -> Self { Poly { coeff: vec![c] } } @@ -159,9 +154,9 @@ impl Poly { /// Returns the (monic) monomial "`x.pow(degree)`". pub fn monomial(degree: usize) -> Self { Poly { - coeff: iter::repeat(E::Fr::zero()) + coeff: iter::repeat(Fr::zero()) .take(degree) - .chain(iter::once(E::Fr::one())) + .chain(iter::once(Fr::one())) .collect(), } } @@ -170,14 +165,14 @@ impl Poly { /// `(x, f(x))`. pub fn interpolate<'a, T, I>(samples_repr: I) -> Self where - I: IntoIterator, - T: Into<::Repr> + Clone + 'a, + I: IntoIterator, + T: Into + Clone + 'a, { - let convert = |(x_repr, y): (&T, &E::Fr)| { - let x = E::Fr::from_repr(x_repr.clone().into()).expect("invalid index"); + let convert = |(x_repr, y): (&T, &Fr)| { + let x = Fr::from_repr(x_repr.clone().into()).expect("invalid index"); (x, *y) }; - let samples: Vec<(E::Fr, E::Fr)> = samples_repr.into_iter().map(convert).collect(); + let samples: Vec<(Fr, Fr)> = samples_repr.into_iter().map(convert).collect(); Self::compute_interpolation(&samples) } @@ -187,12 +182,12 @@ impl Poly { } /// Returns the value at the point `i`. - pub fn evaluate::Repr>>(&self, i: T) -> E::Fr { + pub fn evaluate>(&self, i: T) -> Fr { let mut result = match self.coeff.last() { - None => return E::Fr::zero(), + None => return Fr::zero(), Some(c) => *c, }; - let x = E::Fr::from_repr(i.into()).expect("invalid index"); + let x = Fr::from_repr(i.into()).expect("invalid index"); for c in self.coeff.iter().rev().skip(1) { result.mul_assign(&x); result.add_assign(c); @@ -201,8 +196,8 @@ impl Poly { } /// Returns the corresponding commitment. - pub fn commitment(&self) -> Commitment { - let to_g1 = |c: &E::Fr| E::G1Affine::one().mul(*c); + pub fn commitment(&self) -> Commitment { + let to_g1 = |c: &Fr| G1Affine::one().mul(*c); Commitment { coeff: self.coeff.iter().map(to_g1).collect(), } @@ -217,7 +212,7 @@ impl Poly { /// Returns the unique polynomial `f` of degree `samples.len() - 1` with the given values /// `(x, f(x))`. - fn compute_interpolation(samples: &[(E::Fr, E::Fr)]) -> Self { + fn compute_interpolation(samples: &[(Fr, Fr)]) -> Self { if samples.is_empty() { return Poly::zero(); } else if samples.len() == 1 { @@ -234,7 +229,7 @@ impl Poly { } /// Returns the Lagrange base polynomial that is `1` in `p` and `0` in every `samples[i].0`. - fn lagrange(p: E::Fr, samples: &[(E::Fr, E::Fr)]) -> Self { + fn lagrange(p: Fr, samples: &[(Fr, Fr)]) -> Self { let mut result = Self::one(); for &(sx, _) in samples { let mut denom = p; @@ -247,20 +242,14 @@ impl Poly { } /// A commitment to a univariate polynomial. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Commitment { +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct Commitment { /// The coefficients of the polynomial. #[serde(with = "super::serde_impl::projective_vec")] - coeff: Vec, + coeff: Vec, } -impl PartialEq for Commitment { - fn eq(&self, other: &Self) -> bool { - self.coeff == other.coeff - } -} - -impl Hash for Commitment { +impl Hash for Commitment { fn hash(&self, state: &mut H) { self.coeff.len().hash(state); for c in &self.coeff { @@ -269,10 +258,10 @@ impl Hash for Commitment { } } -impl>, E: Engine> ops::AddAssign for Commitment { +impl> ops::AddAssign for Commitment { fn add_assign(&mut self, rhs: B) { let len = cmp::max(self.coeff.len(), rhs.borrow().coeff.len()); - self.coeff.resize(len, E::G1::zero()); + self.coeff.resize(len, G1::zero()); for (self_c, rhs_c) in self.coeff.iter_mut().zip(&rhs.borrow().coeff) { self_c.add_assign(rhs_c); } @@ -280,36 +269,36 @@ impl>, E: Engine> ops::AddAssign for Commitment { } } -impl<'a, B: Borrow>, E: Engine> ops::Add for &'a Commitment { - type Output = Commitment; +impl<'a, B: Borrow> ops::Add for &'a Commitment { + type Output = Commitment; - fn add(self, rhs: B) -> Commitment { + fn add(self, rhs: B) -> Commitment { (*self).clone() + rhs } } -impl>, E: Engine> ops::Add for Commitment { - type Output = Commitment; +impl> ops::Add for Commitment { + type Output = Commitment; - fn add(mut self, rhs: B) -> Commitment { + fn add(mut self, rhs: B) -> Commitment { self += rhs; self } } -impl Commitment { +impl Commitment { /// Returns the polynomial's degree. pub fn degree(&self) -> usize { self.coeff.len() - 1 } /// Returns the `i`-th public key share. - pub fn evaluate::Repr>>(&self, i: T) -> E::G1 { + pub fn evaluate>(&self, i: T) -> G1 { let mut result = match self.coeff.last() { - None => return E::G1::zero(), + None => return G1::zero(), Some(c) => *c, }; - let x = E::Fr::from_repr(i.into()).expect("invalid index"); + let x = Fr::from_repr(i.into()).expect("invalid index"); for c in self.coeff.iter().rev().skip(1) { result.mul_assign(x); result.add_assign(c); @@ -330,15 +319,15 @@ impl Commitment { /// This can be used for Verifiable Secret Sharing and Distributed Key Generation. See the module /// documentation for details. #[derive(Debug, Clone)] -pub struct BivarPoly { +pub struct BivarPoly { /// The polynomial's degree in each of the two variables. degree: usize, /// The coefficients of the polynomial. Coefficient `(i, j)` for `i <= j` is in position /// `j * (j + 1) / 2 + i`. - coeff: Vec, + coeff: Vec, } -impl BivarPoly { +impl BivarPoly { /// Creates a random polynomial. pub fn random(degree: usize, rng: &mut R) -> Self { BivarPoly { @@ -353,11 +342,11 @@ impl BivarPoly { } /// Returns the polynomial's value at the point `(x, y)`. - pub fn evaluate::Repr>>(&self, x: T, y: T) -> E::Fr { + pub fn evaluate>(&self, x: T, y: T) -> Fr { let x_pow = self.powers(x); let y_pow = self.powers(y); // TODO: Can we save a few multiplication steps here due to the symmetry? - let mut result = E::Fr::zero(); + let mut result = Fr::zero(); for (i, x_pow_i) in x_pow.into_iter().enumerate() { for (j, y_pow_j) in y_pow.iter().enumerate() { let mut summand = self.coeff[coeff_pos(i, j)]; @@ -370,11 +359,11 @@ impl BivarPoly { } /// Returns the `x`-th row, as a univariate polynomial. - pub fn row::Repr>>(&self, x: T) -> Poly { + pub fn row>(&self, x: T) -> Poly { let x_pow = self.powers(x); - let coeff: Vec = (0..=self.degree) + let coeff: Vec = (0..=self.degree) .map(|i| { - let mut result = E::Fr::zero(); + let mut result = Fr::zero(); for (j, x_pow_j) in x_pow.iter().enumerate() { let mut summand = self.coeff[coeff_pos(i, j)]; summand.mul_assign(x_pow_j); @@ -387,8 +376,8 @@ impl BivarPoly { } /// Returns the corresponding commitment. That information can be shared publicly. - pub fn commitment(&self) -> BivarCommitment { - let to_pub = |c: &E::Fr| E::G1Affine::one().mul(*c); + pub fn commitment(&self) -> BivarCommitment { + let to_pub = |c: &Fr| G1Affine::one().mul(*c); BivarCommitment { degree: self.degree, coeff: self.coeff.iter().map(to_pub).collect(), @@ -396,22 +385,22 @@ impl BivarPoly { } /// Returns the `0`-th to `degree`-th power of `x`. - fn powers::Repr>>(&self, x_repr: T) -> Vec { + fn powers>(&self, x_repr: T) -> Vec { powers(x_repr, self.degree) } } /// A commitment to a bivariate polynomial. #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct BivarCommitment { +pub struct BivarCommitment { /// The polynomial's degree in each of the two variables. degree: usize, /// The commitments to the coefficients. #[serde(with = "super::serde_impl::projective_vec")] - coeff: Vec, + coeff: Vec, } -impl Hash for BivarCommitment { +impl Hash for BivarCommitment { fn hash(&self, state: &mut H) { self.degree.hash(state); for c in &self.coeff { @@ -420,18 +409,18 @@ impl Hash for BivarCommitment { } } -impl BivarCommitment { +impl BivarCommitment { /// Returns the polynomial's degree: It is the same in both variables. pub fn degree(&self) -> usize { self.degree } /// Returns the commitment's value at the point `(x, y)`. - pub fn evaluate::Repr>>(&self, x: T, y: T) -> E::G1 { + pub fn evaluate>(&self, x: T, y: T) -> G1 { let x_pow = self.powers(x); let y_pow = self.powers(y); // TODO: Can we save a few multiplication steps here due to the symmetry? - let mut result = E::G1::zero(); + let mut result = G1::zero(); for (i, x_pow_i) in x_pow.into_iter().enumerate() { for (j, y_pow_j) in y_pow.iter().enumerate() { let mut summand = self.coeff[coeff_pos(i, j)]; @@ -444,11 +433,11 @@ impl BivarCommitment { } /// Returns the `x`-th row, as a commitment to a univariate polynomial. - pub fn row::Repr>>(&self, x: T) -> Commitment { + pub fn row>(&self, x: T) -> Commitment { let x_pow = self.powers(x); - let coeff: Vec = (0..=self.degree) + let coeff: Vec = (0..=self.degree) .map(|i| { - let mut result = E::G1::zero(); + let mut result = G1::zero(); for (j, x_pow_j) in x_pow.iter().enumerate() { let mut summand = self.coeff[coeff_pos(i, j)]; summand.mul_assign(*x_pow_j); @@ -461,7 +450,7 @@ impl BivarCommitment { } /// Returns the `0`-th to `degree`-th power of `x`. - fn powers::Repr>>(&self, x_repr: T) -> Vec { + fn powers>(&self, x_repr: T) -> Vec { powers(x_repr, self.degree) } } @@ -495,12 +484,10 @@ mod tests { use super::{coeff_pos, BivarPoly, Poly}; - use pairing::bls12_381::Bls12; - use pairing::{CurveAffine, Engine, Field, PrimeField}; + use pairing::bls12_381::{Fr, G1Affine}; + use pairing::{CurveAffine, Field, PrimeField}; use rand; - type Fr = ::Fr; - fn fr(x: i64) -> Fr { let mut result = Fr::from_repr((x.abs() as u64).into()).unwrap(); if x < 0 { @@ -527,7 +514,7 @@ mod tests { #[test] fn poly() { // The polynomial "`5 * x.pow(3) + x.pow(1) - 2`". - let poly: Poly = + let poly = Poly::monomial(3) * Poly::constant(fr(5)) + Poly::monomial(1) - Poly::constant(fr(2)); let coeff = vec![fr(-2), fr(1), fr(0), fr(5)]; assert_eq!(Poly { coeff }, poly); @@ -554,7 +541,7 @@ mod tests { // For distributed key generation, a number of dealers, only one of who needs to be honest, // generates random bivariate polynomials and publicly commits to them. In partice, the // dealers can e.g. be any `faulty_num + 1` nodes. - let bi_polys: Vec> = (0..dealer_num) + let bi_polys: Vec = (0..dealer_num) .map(|_| BivarPoly::random(faulty_num, &mut rng)) .collect(); let pub_bi_commits: Vec<_> = bi_polys.iter().map(BivarPoly::commitment).collect(); @@ -573,7 +560,7 @@ mod tests { // Node `s` receives the `s`-th value and verifies it. for s in 1..=node_num { let val = row_poly.evaluate(s as u64); - let val_g1 = ::G1Affine::one().mul(val); + let val_g1 = G1Affine::one().mul(val); assert_eq!(bi_commit.evaluate(m as u64, s as u64), val_g1); // The node can't verify this directly, but it should have the correct value: assert_eq!(bi_poly.evaluate(m as u64, s as u64), val); diff --git a/protobuf_impl.rs b/protobuf_impl.rs index 69ecf51..2067933 100644 --- a/protobuf_impl.rs +++ b/protobuf_impl.rs @@ -1,14 +1,15 @@ use super::Signature; -use pairing::{CurveAffine, CurveProjective, EncodedPoint, Engine}; +use pairing::bls12_381::G2Compressed; +use pairing::{CurveAffine, CurveProjective, EncodedPoint}; -impl Signature { +impl Signature { pub fn to_vec(&self) -> Vec { let comp = self.0.into_affine().into_compressed(); comp.as_ref().to_vec() } pub fn from_bytes(bytes: &[u8]) -> Option { - let mut comp = ::Compressed::empty(); + let mut comp = G2Compressed::empty(); comp.as_mut().copy_from_slice(bytes); if let Ok(affine) = comp.into_affine() { Some(Signature(affine.into_projective()))