diff --git a/rust/catalyst-voting/Cargo.toml b/rust/catalyst-voting/Cargo.toml index 9f31c6b2c0..e26728cea5 100644 --- a/rust/catalyst-voting/Cargo.toml +++ b/rust/catalyst-voting/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] thiserror = "1.0.56" rand_core = "0.6.4" -curve25519-dalek = { version = "4.0" } +curve25519-dalek = { version = "4.0", features = ["digest"] } blake2b_simd = "1.0.2" [dev-dependencies] diff --git a/rust/catalyst-voting/src/crypto/group/ristretto255.rs b/rust/catalyst-voting/src/crypto/group/ristretto255.rs index 5167a52bf4..cc0ce54209 100644 --- a/rust/catalyst-voting/src/crypto/group/ristretto255.rs +++ b/rust/catalyst-voting/src/crypto/group/ristretto255.rs @@ -9,6 +9,7 @@ use std::{ use curve25519_dalek::{ constants::{RISTRETTO_BASEPOINT_POINT, RISTRETTO_BASEPOINT_TABLE}, + digest::{consts::U64, Digest}, ristretto::{CompressedRistretto, RistrettoPoint as Point}, scalar::Scalar as IScalar, traits::Identity, @@ -77,6 +78,12 @@ impl Scalar { pub fn from_bytes(bytes: [u8; 32]) -> Option { IScalar::from_canonical_bytes(bytes).map(Scalar).into() } + + /// Generate a `Scalar` from a hash digest. + pub fn from_hash(hash: D) -> Scalar + where D: Digest { + Scalar(IScalar::from_hash(hash)) + } } impl GroupElement { diff --git a/rust/catalyst-voting/src/crypto/hash.rs b/rust/catalyst-voting/src/crypto/hash.rs index 0e6763d48e..77e65173ec 100644 --- a/rust/catalyst-voting/src/crypto/hash.rs +++ b/rust/catalyst-voting/src/crypto/hash.rs @@ -2,60 +2,51 @@ #![allow(dead_code)] -/// Blake2b-256 hasher instance. -pub(crate) struct Blake2b256Hasher(blake2b_simd::State); +use curve25519_dalek::digest::{ + consts::U64, typenum::Unsigned, FixedOutput, HashMarker, Output, OutputSizeUser, Update, +}; -impl Blake2b256Hasher { +/// Blake2b-512 hasher instance. +pub(crate) struct Blake2b512Hasher(blake2b_simd::State); + +impl Blake2b512Hasher { /// Create a new `Blake2b256Hasher`. pub(crate) fn new() -> Self { Self( blake2b_simd::Params::new() - .hash_length(Blake2b256::HASH_SIZE) + .hash_length(Self::output_size()) .to_state(), ) } +} - /// Incrementally add bytes to the hasher. - pub(crate) fn update(&mut self, bytes: &[u8]) { - self.0.update(bytes); - } +// Implementation of the `digest::Digest` trait for `Blake2b256Hasher`. - /// Finalize the state and return a `Hash`. - pub(crate) fn finalize(self) -> Blake2b256 { - let hash = self.0.finalize(); - Blake2b256::from_bytes_unchecked(hash.as_bytes()) +impl Default for Blake2b512Hasher { + fn default() -> Self { + Self::new() } } -/// Blake2b-256 hash instance. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub(crate) struct Blake2b256([u8; Self::HASH_SIZE]); - -impl Blake2b256 { - /// Blake2b-256 hash size. - const HASH_SIZE: usize = 32; - - /// Create a new `Blake2b256` from bytes. - /// It does not validate the size of the bytes, so all checks should be done by - /// the caller. - fn from_bytes_unchecked(bytes: &[u8]) -> Self { - let mut hash_bytes = [0; Self::HASH_SIZE]; - hash_bytes.copy_from_slice(bytes); - - Self(hash_bytes) +impl Update for Blake2b512Hasher { + fn update(&mut self, data: &[u8]) { + self.0.update(data); } +} - /// Calculate a new `Blake2b256` from bytes. - pub(crate) fn hash(bytes: &[u8]) -> Self { - let hash = blake2b_simd::Params::new() - .hash_length(Self::HASH_SIZE) - .hash(bytes); +impl OutputSizeUser for Blake2b512Hasher { + type OutputSize = U64; - Self::from_bytes_unchecked(hash.as_bytes()) + fn output_size() -> usize { + Self::OutputSize::USIZE } +} - /// Return the hash bytes. - pub(crate) fn to_bytes(&self) -> [u8; Self::HASH_SIZE] { - self.0 +impl FixedOutput for Blake2b512Hasher { + fn finalize_into(self, out: &mut Output) { + let hash = self.0.finalize(); + out.copy_from_slice(hash.as_bytes()); } } + +impl HashMarker for Blake2b512Hasher {} diff --git a/rust/catalyst-voting/src/crypto/zk_dl_equality.rs b/rust/catalyst-voting/src/crypto/zk_dl_equality.rs index 51f50602ba..391e617a7f 100644 --- a/rust/catalyst-voting/src/crypto/zk_dl_equality.rs +++ b/rust/catalyst-voting/src/crypto/zk_dl_equality.rs @@ -12,7 +12,12 @@ #![allow(dead_code, unused_variables)] -use super::group::{GroupElement, Scalar}; +use curve25519_dalek::digest::Update; + +use super::{ + group::{GroupElement, Scalar}, + hash::Blake2b512Hasher, +}; /// DLEQ proof struct pub struct DleqProof(Scalar, Scalar); @@ -25,15 +30,13 @@ pub fn generate_dleq_proof( let a_1 = base_1 * randomness; let a_2 = base_2 * randomness; - let mut blake2b_hasher = blake2b_simd::State::new(); - blake2b_hasher.update(&a_1.to_bytes()); - blake2b_hasher.update(&a_2.to_bytes()); - blake2b_hasher.update(&point_1.to_bytes()); - blake2b_hasher.update(&point_2.to_bytes()); - let hash = blake2b_hasher.finalize(); - hash.as_bytes(); + let blake2b_hasher = Blake2b512Hasher::new() + .chain(a_1.to_bytes()) + .chain(a_2.to_bytes()) + .chain(point_1.to_bytes()) + .chain(point_2.to_bytes()); - let challenge = Scalar::zero(); + let challenge = Scalar::from_hash(blake2b_hasher); let response = &(dlog * &challenge) + randomness; DleqProof(challenge, response)