From 1f27fa68918741100c89d88af0675168a27038fc Mon Sep 17 00:00:00 2001 From: Andreas Fackler Date: Tue, 19 Jun 2018 12:22:10 +0200 Subject: [PATCH] Implement Hash for "public" cryptographic types. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a `Hash` implementation for public keys, commitments, ciphertexts and signatures — types that might make sense to be included in special transactions. The `DynamicHoneyBadger` implementation will require some of them. --- src/crypto/mod.rs | 29 ++++++++++++++++++++++++++++- src/crypto/poly.rs | 19 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/crypto/mod.rs b/src/crypto/mod.rs index 1dd0bfe..2827de0 100644 --- a/src/crypto/mod.rs +++ b/src/crypto/mod.rs @@ -5,6 +5,7 @@ pub mod protobuf_impl; mod serde_impl; use std::fmt; +use std::hash::{Hash, Hasher}; use byteorder::{BigEndian, ByteOrder}; use init_with::InitWith; @@ -31,6 +32,12 @@ impl PartialEq 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 { @@ -85,6 +92,12 @@ impl PartialEq for Signature { } } +impl Hash for Signature { + fn hash(&self, state: &mut H) { + self.0.into_affine().into_compressed().as_ref().hash(state); + } +} + impl Signature { pub fn parity(&self) -> bool { let uncomp = self.0.into_affine().into_uncompressed(); @@ -160,6 +173,14 @@ impl PartialEq for Ciphertext { } } +impl Hash for Ciphertext { + fn hash(&self, state: &mut H) { + self.0.into_affine().into_compressed().as_ref().hash(state); + self.1.hash(state); + self.2.into_affine().into_compressed().as_ref().hash(state); + } +} + impl Ciphertext { /// Returns `true` if this is a valid ciphertext. This check is necessary to prevent /// chosen-ciphertext attacks. @@ -180,8 +201,14 @@ impl PartialEq 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)] +#[derive(Serialize, Deserialize, Clone, Debug, Hash)] 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`. diff --git a/src/crypto/poly.rs b/src/crypto/poly.rs index 989a875..7479f25 100644 --- a/src/crypto/poly.rs +++ b/src/crypto/poly.rs @@ -20,6 +20,7 @@ // TODO: Expand this explanation and add examples, once the API is complete and stable. use std::borrow::Borrow; +use std::hash::{Hash, Hasher}; use std::{cmp, iter, ops}; use pairing::{CurveAffine, CurveProjective, Engine, Field, PrimeField}; @@ -261,6 +262,15 @@ impl PartialEq for Commitment { } } +impl Hash for Commitment { + fn hash(&self, state: &mut H) { + self.coeff.len().hash(state); + for c in &self.coeff { + c.into_affine().into_compressed().as_ref().hash(state); + } + } +} + impl>, E: Engine> ops::AddAssign for Commitment { fn add_assign(&mut self, rhs: B) { let len = cmp::max(self.coeff.len(), rhs.borrow().coeff.len()); @@ -403,6 +413,15 @@ pub struct BivarCommitment { coeff: Vec, } +impl Hash for BivarCommitment { + fn hash(&self, state: &mut H) { + self.degree.hash(state); + for c in &self.coeff { + c.into_affine().into_compressed().as_ref().hash(state); + } + } +} + impl BivarCommitment { /// Returns the polynomial's degree: It is the same in both variables. pub fn degree(&self) -> usize {