From f523ec68b60fb3203e6d0cd44ab8471c3cea73c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Wed, 22 Mar 2023 22:56:41 +0100 Subject: [PATCH 01/25] Z_pad without Vec --- ff/src/fields/field_hashers/expander/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index 8b1ef0a12..fdbe68ed5 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -52,6 +52,8 @@ pub(super) struct ExpanderXmd { pub(super) block_size: usize, } +static Z_PAD: [u8; 256] = [0u8; 256]; + impl Expander for ExpanderXmd { fn construct_dst_prime(&self) -> Vec { let mut dst_prime = if self.dst.len() > MAX_DST_LENGTH { @@ -76,14 +78,13 @@ impl Expander for ExpanderXmd { ); let dst_prime = self.construct_dst_prime(); - let z_pad: Vec = vec![0; self.block_size]; // Represent `len_in_bytes` as a 2-byte array. // As per I2OSP method outlined in https://tools.ietf.org/pdf/rfc8017.pdf, // The program should abort if integer that we're trying to convert is too large. assert!(n < (1 << 16), "Length should be smaller than 2^16"); let lib_str: [u8; 2] = (n as u16).to_be_bytes(); - hasher.update(&z_pad); + hasher.update(&Z_PAD[0..self.block_size]); hasher.update(msg); hasher.update(&lib_str); hasher.update(&[0u8]); From f64df4e7ad9ccf5df962a63c53eb5d0f7433f9cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Wed, 22 Mar 2023 22:58:37 +0100 Subject: [PATCH 02/25] inherent method for construct_dst_prime --- ff/src/fields/field_hashers/expander/mod.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index fdbe68ed5..4f69773b2 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -4,7 +4,6 @@ use ark_std::vec::Vec; use digest::{DynDigest, ExtendableOutput, Update}; pub trait Expander { - fn construct_dst_prime(&self) -> Vec; fn expand(&self, msg: &[u8], length: usize) -> Vec; } const MAX_DST_LENGTH: usize = 255; @@ -21,7 +20,7 @@ pub(super) struct ExpanderXof { pub(super) k: usize, } -impl Expander for ExpanderXof { +impl ExpanderXof { fn construct_dst_prime(&self) -> Vec { let mut dst_prime = if self.dst.len() > MAX_DST_LENGTH { let mut xofer = self.xofer.clone(); @@ -34,6 +33,9 @@ impl Expander for ExpanderXof { dst_prime.push(dst_prime.len() as u8); dst_prime } +} + +impl Expander for ExpanderXof { fn expand(&self, msg: &[u8], n: usize) -> Vec { let dst_prime = self.construct_dst_prime(); let lib_str = &[((n >> 8) & 0xFF) as u8, (n & 0xFF) as u8]; @@ -54,7 +56,7 @@ pub(super) struct ExpanderXmd { static Z_PAD: [u8; 256] = [0u8; 256]; -impl Expander for ExpanderXmd { +impl ExpanderXmd { fn construct_dst_prime(&self) -> Vec { let mut dst_prime = if self.dst.len() > MAX_DST_LENGTH { let mut hasher = self.hasher.clone(); @@ -67,6 +69,9 @@ impl Expander for ExpanderXmd { dst_prime.push(dst_prime.len() as u8); dst_prime } +} + +impl Expander for ExpanderXmd { fn expand(&self, msg: &[u8], n: usize) -> Vec { let mut hasher = self.hasher.clone(); // output size of the hash function, e.g. 32 bytes = 256 bits for sha2::Sha256 From ad1ac7a0cd74ee8f5fa5e116679672e8a1f7e000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Thu, 23 Mar 2023 02:24:24 +0100 Subject: [PATCH 03/25] Use update directly for ExpanderXoF --- ff/src/fields/field_hashers/expander/mod.rs | 35 +++++++++++---------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index 4f69773b2..c6a2c3a7d 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -14,36 +14,39 @@ const LONG_DST_PREFIX: [u8; 17] = [ 0x2d, ]; -pub(super) struct ExpanderXof { - pub(super) xofer: T, +pub(super) struct ExpanderXof { + pub(super) xofer: H, pub(super) dst: Vec, pub(super) k: usize, } -impl ExpanderXof { - fn construct_dst_prime(&self) -> Vec { - let mut dst_prime = if self.dst.len() > MAX_DST_LENGTH { - let mut xofer = self.xofer.clone(); - xofer.update(&LONG_DST_PREFIX.clone()); - xofer.update(&self.dst); - xofer.finalize_boxed((2 * self.k + 7) >> 3).to_vec() +impl ExpanderXof { + fn update_dst_prime(&self, h: &mut H) { + if self.dst.len() > MAX_DST_LENGTH { + let mut long = H::default(); + long.update(&LONG_DST_PREFIX.clone()); + long.update(&self.dst); + + let mut new_dst = [0u8; MAX_DST_LENGTH]; + let new_dst = &mut new_dst[0..((2 * self.k + 7) >> 3)]; + long.finalize_xof_into(new_dst); + h.update(new_dst); + h.update(&[new_dst.len() as u8]); } else { - self.dst.clone() - }; - dst_prime.push(dst_prime.len() as u8); - dst_prime + h.update(&self.dst); + h.update(&[self.dst.len() as u8]); + } } } -impl Expander for ExpanderXof { +impl Expander for ExpanderXof { fn expand(&self, msg: &[u8], n: usize) -> Vec { - let dst_prime = self.construct_dst_prime(); let lib_str = &[((n >> 8) & 0xFF) as u8, (n & 0xFF) as u8]; let mut xofer = self.xofer.clone(); xofer.update(msg); xofer.update(lib_str); - xofer.update(&dst_prime); + self.update_dst_prime(&mut xofer); xofer.finalize_boxed(n).to_vec() } } From 052711f391459878408f73dadf55bb9d4353de05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Thu, 23 Mar 2023 02:26:27 +0100 Subject: [PATCH 04/25] More idiomatic lib_str --- ff/src/fields/field_hashers/expander/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index c6a2c3a7d..102f8bc2f 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -41,11 +41,13 @@ impl ExpanderXof { impl Expander for ExpanderXof { fn expand(&self, msg: &[u8], n: usize) -> Vec { - let lib_str = &[((n >> 8) & 0xFF) as u8, (n & 0xFF) as u8]; - let mut xofer = self.xofer.clone(); xofer.update(msg); - xofer.update(lib_str); + + // I2OSP(len,2) https://www.rfc-editor.org/rfc/rfc8017.txt + let lib_str = (n as u16).to_be_bytes(); + xofer.update(&lib_str); + self.update_dst_prime(&mut xofer); xofer.finalize_boxed(n).to_vec() } From f644cb74f54272db6b8d6d47fd876acf8d06be9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Thu, 23 Mar 2023 13:24:48 +0100 Subject: [PATCH 05/25] DST abstraction Originally 545ac36 361b2fa 05b86ad --- ff/Cargo.toml | 1 + ff/src/fields/field_hashers/expander/mod.rs | 58 +++++++++++++++------ 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/ff/Cargo.toml b/ff/Cargo.toml index f66d38cf1..04e69644e 100644 --- a/ff/Cargo.toml +++ b/ff/Cargo.toml @@ -18,6 +18,7 @@ ark-ff-asm = { version = "0.4.2", path = "../ff-asm" } ark-ff-macros = { version = "0.4.2", path = "../ff-macros" } ark-std = { version = "0.4.0", default-features = false } ark-serialize = { version = "0.4.2", path = "../serialize", default-features = false } +arrayvec = { version = "0.7", default-features = false } derivative = { version = "2", features = ["use_core"] } num-traits = { version = "0.2", default-features = false } paste = "1.0" diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index 102f8bc2f..f5cc4cca3 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -2,7 +2,11 @@ // With some optimisations use ark_std::vec::Vec; -use digest::{DynDigest, ExtendableOutput, Update}; + +use digest::{DynDigest, FixedOutput, ExtendableOutput, Update}; +use arrayvec::ArrayVec; + + pub trait Expander { fn expand(&self, msg: &[u8], length: usize) -> Vec; } @@ -14,31 +18,51 @@ const LONG_DST_PREFIX: [u8; 17] = [ 0x2d, ]; -pub(super) struct ExpanderXof { - pub(super) xofer: H, - pub(super) dst: Vec, - pub(super) k: usize, -} -impl ExpanderXof { - fn update_dst_prime(&self, h: &mut H) { - if self.dst.len() > MAX_DST_LENGTH { +pub(super) struct DST(arrayvec::ArrayVec); + +impl DST { + pub fn new_fixed(dst: &[u8]) -> DST { + DST(if dst.len() > MAX_DST_LENGTH { let mut long = H::default(); long.update(&LONG_DST_PREFIX.clone()); - long.update(&self.dst); + long.update(&dst); + ArrayVec::try_from( long.finalize_fixed().as_ref() ).unwrap() + } else { + ArrayVec::try_from(dst).unwrap() + }) + } + + pub fn new_xof(dst: &[u8], k: usize) -> DST { + DST(if dst.len() > MAX_DST_LENGTH { + let mut long = H::default(); + long.update(&LONG_DST_PREFIX.clone()); + long.update(&dst); let mut new_dst = [0u8; MAX_DST_LENGTH]; - let new_dst = &mut new_dst[0..((2 * self.k + 7) >> 3)]; + let new_dst = &mut new_dst[0..((2 * k + 7) >> 3)]; long.finalize_xof_into(new_dst); - h.update(new_dst); - h.update(&[new_dst.len() as u8]); + ArrayVec::try_from( &*new_dst ).unwrap() } else { - h.update(&self.dst); - h.update(&[self.dst.len() as u8]); - } + ArrayVec::try_from(dst).unwrap() + }) + } + + pub fn update(&self, h: &mut H) { + h.update(self.0.as_ref()); + // I2OSP(len,1) https://www.rfc-editor.org/rfc/rfc8017.txt + h.update(&[self.0.len() as u8]); } } + + +pub(super) struct ExpanderXof { + pub(super) xofer: H, + pub(super) dst: Vec, + pub(super) k: usize, +} + impl Expander for ExpanderXof { fn expand(&self, msg: &[u8], n: usize) -> Vec { let mut xofer = self.xofer.clone(); @@ -48,7 +72,7 @@ impl Expander for ExpanderXof { let lib_str = (n as u16).to_be_bytes(); xofer.update(&lib_str); - self.update_dst_prime(&mut xofer); + DST::new_xof::(self.dst.as_ref(), self.k).update(&mut xofer); xofer.finalize_boxed(n).to_vec() } } From 014b7b28c166ac19692965ad4765e200382798ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Thu, 23 Mar 2023 13:47:41 +0100 Subject: [PATCH 06/25] defalt instead of clone --- ff/src/fields/field_hashers/expander/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index f5cc4cca3..ecb26c678 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -65,7 +65,7 @@ pub(super) struct ExpanderXof { impl Expander for ExpanderXof { fn expand(&self, msg: &[u8], n: usize) -> Vec { - let mut xofer = self.xofer.clone(); + let mut xofer = H::default(); xofer.update(msg); // I2OSP(len,2) https://www.rfc-editor.org/rfc/rfc8017.txt From 0e8b344d59ec34b6c3433159f0a9e0cda78b25ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Thu, 23 Mar 2023 13:51:37 +0100 Subject: [PATCH 07/25] Default insead of Clone --- ff/src/fields/field_hashers/expander/mod.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index ecb26c678..aa22c2817 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -77,15 +77,15 @@ impl Expander for ExpanderXof { } } -pub(super) struct ExpanderXmd { - pub(super) hasher: T, +pub(super) struct ExpanderXmd { + pub(super) hasher: H, pub(super) dst: Vec, pub(super) block_size: usize, } static Z_PAD: [u8; 256] = [0u8; 256]; -impl ExpanderXmd { +impl ExpanderXmd { fn construct_dst_prime(&self) -> Vec { let mut dst_prime = if self.dst.len() > MAX_DST_LENGTH { let mut hasher = self.hasher.clone(); @@ -100,7 +100,7 @@ impl ExpanderXmd { } } -impl Expander for ExpanderXmd { +impl Expander for ExpanderXmd { fn expand(&self, msg: &[u8], n: usize) -> Vec { let mut hasher = self.hasher.clone(); // output size of the hash function, e.g. 32 bytes = 256 bits for sha2::Sha256 @@ -118,6 +118,7 @@ impl Expander for ExpanderXmd { assert!(n < (1 << 16), "Length should be smaller than 2^16"); let lib_str: [u8; 2] = (n as u16).to_be_bytes(); + let mut hasher = H::default(); hasher.update(&Z_PAD[0..self.block_size]); hasher.update(msg); hasher.update(&lib_str); @@ -125,6 +126,7 @@ impl Expander for ExpanderXmd { hasher.update(&dst_prime); let b0 = hasher.finalize_reset(); + let mut hasher = H::default(); hasher.update(&b0); hasher.update(&[1u8]); hasher.update(&dst_prime); @@ -133,6 +135,7 @@ impl Expander for ExpanderXmd { let mut uniform_bytes: Vec = Vec::with_capacity(n); uniform_bytes.extend_from_slice(&bi); for i in 2..=ell { + let mut hasher = H::default(); // update the hasher with xor of b_0 and b_i elements for (l, r) in b0.iter().zip(bi.iter()) { hasher.update(&[*l ^ *r]); From 74a18a0b13bc8ac01b80ecbbb85d18ab53d6c7d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Fri, 14 Apr 2023 08:12:40 +0200 Subject: [PATCH 08/25] use const len in hash_to_field --- ec/src/hashing/map_to_curve_hasher.rs | 2 +- ff/src/fields/field_hashers/mod.rs | 30 +++++++++++---------------- test-templates/src/h2c/mod.rs | 6 +++--- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/ec/src/hashing/map_to_curve_hasher.rs b/ec/src/hashing/map_to_curve_hasher.rs index fa50a5e57..e0f46f323 100644 --- a/ec/src/hashing/map_to_curve_hasher.rs +++ b/ec/src/hashing/map_to_curve_hasher.rs @@ -56,7 +56,7 @@ where // 5. P = clear_cofactor(R) // 6. return P - let rand_field_elems = self.field_hasher.hash_to_field(msg, 2); + let rand_field_elems = self.field_hasher.hash_to_field::<2>(msg); let rand_curve_elem_0 = M2C::map_to_curve(rand_field_elems[0])?; let rand_curve_elem_1 = M2C::map_to_curve(rand_field_elems[1])?; diff --git a/ff/src/fields/field_hashers/mod.rs b/ff/src/fields/field_hashers/mod.rs index bfd44f231..c81b271c6 100644 --- a/ff/src/fields/field_hashers/mod.rs +++ b/ff/src/fields/field_hashers/mod.rs @@ -18,7 +18,7 @@ pub trait HashToField: Sized { fn new(domain: &[u8]) -> Self; /// Hash an arbitrary `msg` to #`count` elements from field `F`. - fn hash_to_field(&self, msg: &[u8], count: usize) -> Vec; + fn hash_to_field(&self, msg: &[u8]) -> [F; N]; } /// This field hasher constructs a Hash-To-Field based on a fixed-output hash function, @@ -33,7 +33,7 @@ pub trait HashToField: Sized { /// use sha2::Sha256; /// /// let hasher = as HashToField>::new(&[1, 2, 3]); -/// let field_elements: Vec = hasher.hash_to_field(b"Hello, World!", 2); +/// let field_elements: [Fq; 2] = hasher.hash_to_field(b"Hello, World!"); /// /// assert_eq!(field_elements.len(), 2); /// ``` @@ -62,30 +62,24 @@ impl HashToFie } } - fn hash_to_field(&self, message: &[u8], count: usize) -> Vec { + fn hash_to_field(&self, message: &[u8]) -> [F; N] { let m = F::extension_degree() as usize; // The user imposes a `count` of elements of F_p^m to output per input msg, // each field element comprising `m` BasePrimeField elements. - let len_in_bytes = count * m * self.len_per_base_elem; + let len_in_bytes = N * m * self.len_per_base_elem; let uniform_bytes = self.expander.expand(message, len_in_bytes); - let mut output = Vec::with_capacity(count); - let mut base_prime_field_elems = Vec::with_capacity(m); - for i in 0..count { - base_prime_field_elems.clear(); - for j in 0..m { + let cb = |i| { + let base_prime_field_elem = |j| { let elm_offset = self.len_per_base_elem * (j + i * m); - let val = F::BasePrimeField::from_be_bytes_mod_order( + F::BasePrimeField::from_be_bytes_mod_order( &uniform_bytes[elm_offset..][..self.len_per_base_elem], - ); - base_prime_field_elems.push(val); - } - let f = F::from_base_prime_field_elems(base_prime_field_elems.drain(..)).unwrap(); - output.push(f); - } - - output + ) + }; + F::from_base_prime_field_elems( (0..m).map( base_prime_field_elem ) ).unwrap() + }; + ark_std::array::from_fn::(cb) } } diff --git a/test-templates/src/h2c/mod.rs b/test-templates/src/h2c/mod.rs index 4cd52eb35..378aed971 100644 --- a/test-templates/src/h2c/mod.rs +++ b/test-templates/src/h2c/mod.rs @@ -52,11 +52,11 @@ macro_rules! test_h2c { for v in data.vectors.iter() { // first, hash-to-field tests - let got: Vec<$base_prime_field> = - hasher.hash_to_field(&v.msg.as_bytes(), 2 * $m); + let got: [$base_prime_field; { 2* $m } ] = + hasher.hash_to_field(&v.msg.as_bytes()); let want: Vec<$base_prime_field> = v.u.iter().map(read_fq_vec).flatten().collect(); - assert_eq!(got, want); + assert_eq!(got[..], *want); // then, test curve points let x = read_fq_vec(&v.p.x); From 8e5fcdd2339acffc5fcc7868181fde76b8e93bd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Fri, 14 Apr 2023 08:13:22 +0200 Subject: [PATCH 09/25] Remove unecessary Vec -> Vec --- ff/src/fields/field_hashers/expander/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index aa22c2817..411ba1c75 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -145,7 +145,8 @@ impl Expander for ExpanderXmd { bi = hasher.finalize_reset(); uniform_bytes.extend_from_slice(&bi); } - uniform_bytes[0..n].to_vec() + uniform_bytes.truncate(n); + uniform_bytes } } From 5f3889c6ff997853b3f6585657a473d8261ba865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Fri, 14 Apr 2023 08:32:16 +0200 Subject: [PATCH 10/25] Kill DynDigest --- ff/src/fields/field_hashers/expander/mod.rs | 20 ++++++++++---------- ff/src/fields/field_hashers/mod.rs | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index 411ba1c75..d9789e839 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -3,7 +3,7 @@ use ark_std::vec::Vec; -use digest::{DynDigest, FixedOutput, ExtendableOutput, Update}; +use digest::{FixedOutput, ExtendableOutput, Update}; use arrayvec::ArrayVec; @@ -77,7 +77,7 @@ impl Expander for ExpanderXof { } } -pub(super) struct ExpanderXmd { +pub(super) struct ExpanderXmd { pub(super) hasher: H, pub(super) dst: Vec, pub(super) block_size: usize, @@ -85,13 +85,13 @@ pub(super) struct ExpanderXmd { static Z_PAD: [u8; 256] = [0u8; 256]; -impl ExpanderXmd { +impl ExpanderXmd { fn construct_dst_prime(&self) -> Vec { let mut dst_prime = if self.dst.len() > MAX_DST_LENGTH { let mut hasher = self.hasher.clone(); hasher.update(&LONG_DST_PREFIX); hasher.update(&self.dst); - hasher.finalize_reset().to_vec() + hasher.finalize_fixed().to_vec() } else { self.dst.clone() }; @@ -100,11 +100,11 @@ impl ExpanderXmd { } } -impl Expander for ExpanderXmd { +impl Expander for ExpanderXmd { fn expand(&self, msg: &[u8], n: usize) -> Vec { - let mut hasher = self.hasher.clone(); + use digest::typenum::Unsigned; // output size of the hash function, e.g. 32 bytes = 256 bits for sha2::Sha256 - let b_len = hasher.output_size(); + let b_len = H::OutputSize::to_usize(); let ell = (n + (b_len - 1)) / b_len; assert!( ell <= 255, @@ -124,13 +124,13 @@ impl Expander for ExpanderXmd { hasher.update(&lib_str); hasher.update(&[0u8]); hasher.update(&dst_prime); - let b0 = hasher.finalize_reset(); + let b0 = hasher.finalize_fixed(); let mut hasher = H::default(); hasher.update(&b0); hasher.update(&[1u8]); hasher.update(&dst_prime); - let mut bi = hasher.finalize_reset(); + let mut bi = hasher.finalize_fixed(); let mut uniform_bytes: Vec = Vec::with_capacity(n); uniform_bytes.extend_from_slice(&bi); @@ -142,7 +142,7 @@ impl Expander for ExpanderXmd { } hasher.update(&[i as u8]); hasher.update(&dst_prime); - bi = hasher.finalize_reset(); + bi = hasher.finalize_fixed(); uniform_bytes.extend_from_slice(&bi); } uniform_bytes.truncate(n); diff --git a/ff/src/fields/field_hashers/mod.rs b/ff/src/fields/field_hashers/mod.rs index c81b271c6..aa6d5550b 100644 --- a/ff/src/fields/field_hashers/mod.rs +++ b/ff/src/fields/field_hashers/mod.rs @@ -3,7 +3,7 @@ mod expander; use crate::{Field, PrimeField}; use ark_std::vec::Vec; -use digest::DynDigest; +use digest::FixedOutput; use expander::Expander; use self::expander::ExpanderXmd; @@ -37,12 +37,12 @@ pub trait HashToField: Sized { /// /// assert_eq!(field_elements.len(), 2); /// ``` -pub struct DefaultFieldHasher { +pub struct DefaultFieldHasher { expander: ExpanderXmd, len_per_base_elem: usize, } -impl HashToField +impl HashToField for DefaultFieldHasher { fn new(dst: &[u8]) -> Self { From 07537827ea4c7c81c0bae7e33b75c0436eefbc83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Fri, 14 Apr 2023 08:45:01 +0200 Subject: [PATCH 11/25] Idiomatic const --- ff/src/fields/field_hashers/expander/mod.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index d9789e839..d9ca235d1 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -12,11 +12,7 @@ pub trait Expander { } const MAX_DST_LENGTH: usize = 255; -const LONG_DST_PREFIX: [u8; 17] = [ - //'H', '2', 'C', '-', 'O', 'V', 'E', 'R', 'S', 'I', 'Z', 'E', '-', 'D', 'S', 'T', '-', - 0x48, 0x32, 0x43, 0x2d, 0x4f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x5a, 0x45, 0x2d, 0x44, 0x53, 0x54, - 0x2d, -]; +const LONG_DST_PREFIX: &[u8; 17] = b"H2C-OVERSIZE-DST-"; pub(super) struct DST(arrayvec::ArrayVec); @@ -25,7 +21,7 @@ impl DST { pub fn new_fixed(dst: &[u8]) -> DST { DST(if dst.len() > MAX_DST_LENGTH { let mut long = H::default(); - long.update(&LONG_DST_PREFIX.clone()); + long.update(&LONG_DST_PREFIX[..]); long.update(&dst); ArrayVec::try_from( long.finalize_fixed().as_ref() ).unwrap() } else { @@ -36,7 +32,7 @@ impl DST { pub fn new_xof(dst: &[u8], k: usize) -> DST { DST(if dst.len() > MAX_DST_LENGTH { let mut long = H::default(); - long.update(&LONG_DST_PREFIX.clone()); + long.update(&LONG_DST_PREFIX[..]); long.update(&dst); let mut new_dst = [0u8; MAX_DST_LENGTH]; From 560c1612841eaf3e80b96eccb2b36fffa7f9aa2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Fri, 14 Apr 2023 08:45:58 +0200 Subject: [PATCH 12/25] semi-merge dst_prime --- ff/src/fields/field_hashers/expander/mod.rs | 24 +++++---------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index d9ca235d1..c199a6720 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -81,21 +81,6 @@ pub(super) struct ExpanderXmd { static Z_PAD: [u8; 256] = [0u8; 256]; -impl ExpanderXmd { - fn construct_dst_prime(&self) -> Vec { - let mut dst_prime = if self.dst.len() > MAX_DST_LENGTH { - let mut hasher = self.hasher.clone(); - hasher.update(&LONG_DST_PREFIX); - hasher.update(&self.dst); - hasher.finalize_fixed().to_vec() - } else { - self.dst.clone() - }; - dst_prime.push(dst_prime.len() as u8); - dst_prime - } -} - impl Expander for ExpanderXmd { fn expand(&self, msg: &[u8], n: usize) -> Vec { use digest::typenum::Unsigned; @@ -107,7 +92,7 @@ impl Expander for ExpanderXmd { "The ratio of desired output to the output size of hash function is too large!" ); - let dst_prime = self.construct_dst_prime(); + let dst_prime = DST::new_fixed::(self.dst.as_ref()); // Represent `len_in_bytes` as a 2-byte array. // As per I2OSP method outlined in https://tools.ietf.org/pdf/rfc8017.pdf, // The program should abort if integer that we're trying to convert is too large. @@ -119,13 +104,14 @@ impl Expander for ExpanderXmd { hasher.update(msg); hasher.update(&lib_str); hasher.update(&[0u8]); - hasher.update(&dst_prime); + dst_prime.update(& mut hasher); let b0 = hasher.finalize_fixed(); + let mut hasher = H::default(); hasher.update(&b0); hasher.update(&[1u8]); - hasher.update(&dst_prime); + dst_prime.update(& mut hasher); let mut bi = hasher.finalize_fixed(); let mut uniform_bytes: Vec = Vec::with_capacity(n); @@ -137,7 +123,7 @@ impl Expander for ExpanderXmd { hasher.update(&[*l ^ *r]); } hasher.update(&[i as u8]); - hasher.update(&dst_prime); + dst_prime.update(& mut hasher); bi = hasher.finalize_fixed(); uniform_bytes.extend_from_slice(&bi); } From 41ee3aee02707faa6d7b7d064a9beab05d686c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Fri, 14 Apr 2023 08:52:18 +0200 Subject: [PATCH 13/25] FixedOutputReset instead of FixedOutput --- ff/src/fields/field_hashers/expander/mod.rs | 13 ++++++------- ff/src/fields/field_hashers/mod.rs | 6 +++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index c199a6720..675ad0982 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -3,7 +3,7 @@ use ark_std::vec::Vec; -use digest::{FixedOutput, ExtendableOutput, Update}; +use digest::{FixedOutputReset, ExtendableOutput, Update}; use arrayvec::ArrayVec; @@ -18,7 +18,7 @@ const LONG_DST_PREFIX: &[u8; 17] = b"H2C-OVERSIZE-DST-"; pub(super) struct DST(arrayvec::ArrayVec); impl DST { - pub fn new_fixed(dst: &[u8]) -> DST { + pub fn new_fixed(dst: &[u8]) -> DST { DST(if dst.len() > MAX_DST_LENGTH { let mut long = H::default(); long.update(&LONG_DST_PREFIX[..]); @@ -73,7 +73,7 @@ impl Expander for ExpanderXof { } } -pub(super) struct ExpanderXmd { +pub(super) struct ExpanderXmd { pub(super) hasher: H, pub(super) dst: Vec, pub(super) block_size: usize, @@ -81,7 +81,7 @@ pub(super) struct ExpanderXmd { static Z_PAD: [u8; 256] = [0u8; 256]; -impl Expander for ExpanderXmd { +impl Expander for ExpanderXmd { fn expand(&self, msg: &[u8], n: usize) -> Vec { use digest::typenum::Unsigned; // output size of the hash function, e.g. 32 bytes = 256 bits for sha2::Sha256 @@ -107,7 +107,6 @@ impl Expander for ExpanderXmd { dst_prime.update(& mut hasher); let b0 = hasher.finalize_fixed(); - let mut hasher = H::default(); hasher.update(&b0); hasher.update(&[1u8]); @@ -116,15 +115,15 @@ impl Expander for ExpanderXmd { let mut uniform_bytes: Vec = Vec::with_capacity(n); uniform_bytes.extend_from_slice(&bi); + let mut hasher = H::default(); for i in 2..=ell { - let mut hasher = H::default(); // update the hasher with xor of b_0 and b_i elements for (l, r) in b0.iter().zip(bi.iter()) { hasher.update(&[*l ^ *r]); } hasher.update(&[i as u8]); dst_prime.update(& mut hasher); - bi = hasher.finalize_fixed(); + bi = hasher.finalize_fixed_reset(); uniform_bytes.extend_from_slice(&bi); } uniform_bytes.truncate(n); diff --git a/ff/src/fields/field_hashers/mod.rs b/ff/src/fields/field_hashers/mod.rs index aa6d5550b..ef257cf4c 100644 --- a/ff/src/fields/field_hashers/mod.rs +++ b/ff/src/fields/field_hashers/mod.rs @@ -3,7 +3,7 @@ mod expander; use crate::{Field, PrimeField}; use ark_std::vec::Vec; -use digest::FixedOutput; +use digest::FixedOutputReset; use expander::Expander; use self::expander::ExpanderXmd; @@ -37,12 +37,12 @@ pub trait HashToField: Sized { /// /// assert_eq!(field_elements.len(), 2); /// ``` -pub struct DefaultFieldHasher { +pub struct DefaultFieldHasher { expander: ExpanderXmd, len_per_base_elem: usize, } -impl HashToField +impl HashToField for DefaultFieldHasher { fn new(dst: &[u8]) -> Self { From b89237c67932fad3fc6d59ce701c0a09eaf0cf74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Fri, 14 Apr 2023 09:06:21 +0200 Subject: [PATCH 14/25] Remove another double Vec --- ff/src/fields/field_hashers/expander/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index 675ad0982..ca49c5b75 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -69,7 +69,7 @@ impl Expander for ExpanderXof { xofer.update(&lib_str); DST::new_xof::(self.dst.as_ref(), self.k).update(&mut xofer); - xofer.finalize_boxed(n).to_vec() + xofer.finalize_boxed(n).into_vec() } } From 614bc732529b753d98cb2e0cd0c3ee6c37a0e2dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Fri, 14 Apr 2023 09:25:11 +0200 Subject: [PATCH 15/25] Initial XofReader based hash_to_field --- ff/src/fields/field_hashers/mod.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/ff/src/fields/field_hashers/mod.rs b/ff/src/fields/field_hashers/mod.rs index ef257cf4c..436003958 100644 --- a/ff/src/fields/field_hashers/mod.rs +++ b/ff/src/fields/field_hashers/mod.rs @@ -3,7 +3,7 @@ mod expander; use crate::{Field, PrimeField}; use ark_std::vec::Vec; -use digest::FixedOutputReset; +use digest::{FixedOutputReset,XofReader}; use expander::Expander; use self::expander::ExpanderXmd; @@ -83,11 +83,28 @@ impl Ha } } +pub fn hash_to_field(h: &mut H) -> F { + // The final output of `hash_to_field` will be an array of field + // elements from F::BaseField, each of size `len_per_elem`. + let len_per_base_elem = get_len_per_elem::(); + // Rust *still* lacks alloca, hence this ugly hack. + let mut alloca = [0u8; 2048]; + let alloca = &mut alloca[0..len_per_base_elem]; + + let m = F::extension_degree() as usize; + + let base_prime_field_elem = |_| { + h.read(alloca); + F::BasePrimeField::from_be_bytes_mod_order(alloca) + }; + F::from_base_prime_field_elems( (0..m).map(base_prime_field_elem) ).unwrap() +} + /// This function computes the length in bytes that a hash function should output /// for hashing an element of type `Field`. /// See section 5.1 and 5.3 of the /// [IETF hash standardization draft](https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/14/) -fn get_len_per_elem() -> usize { +const fn get_len_per_elem() -> usize { // ceil(log(p)) let base_field_size_in_bits = F::BasePrimeField::MODULUS_BIT_SIZE as usize; // ceil(log(p)) + security_parameter From dcd818a7c8c53e577e34c96757ea330b4e8750b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Mon, 17 Apr 2023 06:53:22 +0200 Subject: [PATCH 16/25] Expose DST --- ff/src/fields/field_hashers/expander/mod.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index ca49c5b75..928bcedc9 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -14,11 +14,13 @@ const MAX_DST_LENGTH: usize = 255; const LONG_DST_PREFIX: &[u8; 17] = b"H2C-OVERSIZE-DST-"; - -pub(super) struct DST(arrayvec::ArrayVec); +/// Implements section [5.3.3](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3) +/// "Using DSTs longer than 255 bytes" of the +/// [IRTF CFRG hash-to-curve draft #16](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3). +pub struct DST(arrayvec::ArrayVec); impl DST { - pub fn new_fixed(dst: &[u8]) -> DST { + pub fn new_xmd(dst: &[u8]) -> DST { DST(if dst.len() > MAX_DST_LENGTH { let mut long = H::default(); long.update(&LONG_DST_PREFIX[..]); @@ -52,7 +54,6 @@ impl DST { } - pub(super) struct ExpanderXof { pub(super) xofer: H, pub(super) dst: Vec, @@ -92,7 +93,7 @@ impl Expander for ExpanderXmd { "The ratio of desired output to the output size of hash function is too large!" ); - let dst_prime = DST::new_fixed::(self.dst.as_ref()); + let dst_prime = DST::new_xmd::(self.dst.as_ref()); // Represent `len_in_bytes` as a 2-byte array. // As per I2OSP method outlined in https://tools.ietf.org/pdf/rfc8017.pdf, // The program should abort if integer that we're trying to convert is too large. From 03219cdc41f1d269647487baef1e699bb5496e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Mon, 17 Apr 2023 07:24:13 +0200 Subject: [PATCH 17/25] use reset --- ff/src/fields/field_hashers/expander/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index 928bcedc9..6da786ee7 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -106,17 +106,15 @@ impl Expander for ExpanderXmd { hasher.update(&lib_str); hasher.update(&[0u8]); dst_prime.update(& mut hasher); - let b0 = hasher.finalize_fixed(); + let b0 = hasher.finalize_fixed_reset(); - let mut hasher = H::default(); hasher.update(&b0); hasher.update(&[1u8]); dst_prime.update(& mut hasher); - let mut bi = hasher.finalize_fixed(); + let mut bi = hasher.finalize_fixed_reset(); let mut uniform_bytes: Vec = Vec::with_capacity(n); uniform_bytes.extend_from_slice(&bi); - let mut hasher = H::default(); for i in 2..=ell { // update the hasher with xor of b_0 and b_i elements for (l, r) in b0.iter().zip(bi.iter()) { From 271e7af181c3ef10baa51ccdef1f837be6df153d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Fri, 8 Sep 2023 23:33:14 +0200 Subject: [PATCH 18/25] cargo fmt --- ff/src/fields/field_hashers/expander/mod.rs | 22 ++++++++++----------- ff/src/fields/field_hashers/mod.rs | 10 +++++----- test-templates/src/h2c/mod.rs | 2 +- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index 6da786ee7..1d6c451c7 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -3,9 +3,8 @@ use ark_std::vec::Vec; -use digest::{FixedOutputReset, ExtendableOutput, Update}; use arrayvec::ArrayVec; - +use digest::{ExtendableOutput, FixedOutputReset, Update}; pub trait Expander { fn expand(&self, msg: &[u8], length: usize) -> Vec; @@ -15,23 +14,23 @@ const MAX_DST_LENGTH: usize = 255; const LONG_DST_PREFIX: &[u8; 17] = b"H2C-OVERSIZE-DST-"; /// Implements section [5.3.3](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3) -/// "Using DSTs longer than 255 bytes" of the +/// "Using DSTs longer than 255 bytes" of the /// [IRTF CFRG hash-to-curve draft #16](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3). -pub struct DST(arrayvec::ArrayVec); +pub struct DST(arrayvec::ArrayVec); impl DST { - pub fn new_xmd(dst: &[u8]) -> DST { + pub fn new_xmd(dst: &[u8]) -> DST { DST(if dst.len() > MAX_DST_LENGTH { let mut long = H::default(); long.update(&LONG_DST_PREFIX[..]); long.update(&dst); - ArrayVec::try_from( long.finalize_fixed().as_ref() ).unwrap() + ArrayVec::try_from(long.finalize_fixed().as_ref()).unwrap() } else { ArrayVec::try_from(dst).unwrap() }) } - pub fn new_xof(dst: &[u8], k: usize) -> DST { + pub fn new_xof(dst: &[u8], k: usize) -> DST { DST(if dst.len() > MAX_DST_LENGTH { let mut long = H::default(); long.update(&LONG_DST_PREFIX[..]); @@ -40,7 +39,7 @@ impl DST { let mut new_dst = [0u8; MAX_DST_LENGTH]; let new_dst = &mut new_dst[0..((2 * k + 7) >> 3)]; long.finalize_xof_into(new_dst); - ArrayVec::try_from( &*new_dst ).unwrap() + ArrayVec::try_from(&*new_dst).unwrap() } else { ArrayVec::try_from(dst).unwrap() }) @@ -53,7 +52,6 @@ impl DST { } } - pub(super) struct ExpanderXof { pub(super) xofer: H, pub(super) dst: Vec, @@ -105,12 +103,12 @@ impl Expander for ExpanderXmd { hasher.update(msg); hasher.update(&lib_str); hasher.update(&[0u8]); - dst_prime.update(& mut hasher); + dst_prime.update(&mut hasher); let b0 = hasher.finalize_fixed_reset(); hasher.update(&b0); hasher.update(&[1u8]); - dst_prime.update(& mut hasher); + dst_prime.update(&mut hasher); let mut bi = hasher.finalize_fixed_reset(); let mut uniform_bytes: Vec = Vec::with_capacity(n); @@ -121,7 +119,7 @@ impl Expander for ExpanderXmd { hasher.update(&[*l ^ *r]); } hasher.update(&[i as u8]); - dst_prime.update(& mut hasher); + dst_prime.update(&mut hasher); bi = hasher.finalize_fixed_reset(); uniform_bytes.extend_from_slice(&bi); } diff --git a/ff/src/fields/field_hashers/mod.rs b/ff/src/fields/field_hashers/mod.rs index 436003958..f0fdaebb9 100644 --- a/ff/src/fields/field_hashers/mod.rs +++ b/ff/src/fields/field_hashers/mod.rs @@ -3,7 +3,7 @@ mod expander; use crate::{Field, PrimeField}; use ark_std::vec::Vec; -use digest::{FixedOutputReset,XofReader}; +use digest::{FixedOutputReset, XofReader}; use expander::Expander; use self::expander::ExpanderXmd; @@ -77,13 +77,13 @@ impl Ha &uniform_bytes[elm_offset..][..self.len_per_base_elem], ) }; - F::from_base_prime_field_elems( (0..m).map( base_prime_field_elem ) ).unwrap() + F::from_base_prime_field_elems((0..m).map(base_prime_field_elem)).unwrap() }; - ark_std::array::from_fn::(cb) + ark_std::array::from_fn::(cb) } } -pub fn hash_to_field(h: &mut H) -> F { +pub fn hash_to_field(h: &mut H) -> F { // The final output of `hash_to_field` will be an array of field // elements from F::BaseField, each of size `len_per_elem`. let len_per_base_elem = get_len_per_elem::(); @@ -97,7 +97,7 @@ pub fn hash_to_field(h: &mut H) - h.read(alloca); F::BasePrimeField::from_be_bytes_mod_order(alloca) }; - F::from_base_prime_field_elems( (0..m).map(base_prime_field_elem) ).unwrap() + F::from_base_prime_field_elems((0..m).map(base_prime_field_elem)).unwrap() } /// This function computes the length in bytes that a hash function should output diff --git a/test-templates/src/h2c/mod.rs b/test-templates/src/h2c/mod.rs index 378aed971..77b9a1a42 100644 --- a/test-templates/src/h2c/mod.rs +++ b/test-templates/src/h2c/mod.rs @@ -52,7 +52,7 @@ macro_rules! test_h2c { for v in data.vectors.iter() { // first, hash-to-field tests - let got: [$base_prime_field; { 2* $m } ] = + let got: [$base_prime_field; { 2 * $m }] = hasher.hash_to_field(&v.msg.as_bytes()); let want: Vec<$base_prime_field> = v.u.iter().map(read_fq_vec).flatten().collect(); From cf2e957dbecb997e97ab236aaa9d9d8e3740a396 Mon Sep 17 00:00:00 2001 From: Jeff Burdges Date: Tue, 12 Sep 2023 14:29:25 +0200 Subject: [PATCH 19/25] Update ff/src/fields/field_hashers/expander/mod.rs Co-authored-by: Pratyush Mishra --- ff/src/fields/field_hashers/expander/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index 1d6c451c7..f7603d494 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -31,7 +31,7 @@ impl DST { } pub fn new_xof(dst: &[u8], k: usize) -> DST { - DST(if dst.len() > MAX_DST_LENGTH { + let array = if dst.len() > MAX_DST_LENGTH { let mut long = H::default(); long.update(&LONG_DST_PREFIX[..]); long.update(&dst); @@ -39,10 +39,11 @@ impl DST { let mut new_dst = [0u8; MAX_DST_LENGTH]; let new_dst = &mut new_dst[0..((2 * k + 7) >> 3)]; long.finalize_xof_into(new_dst); - ArrayVec::try_from(&*new_dst).unwrap() + new_dst.try_into() } else { - ArrayVec::try_from(dst).unwrap() - }) + dst.try_into() + }; + DST(array.unwrap()) } pub fn update(&self, h: &mut H) { From 0ff682442ee0a612f5579a575fe395c307a0ff02 Mon Sep 17 00:00:00 2001 From: Jeff Burdges Date: Tue, 12 Sep 2023 14:29:34 +0200 Subject: [PATCH 20/25] Update ff/src/fields/field_hashers/expander/mod.rs Co-authored-by: Pratyush Mishra --- ff/src/fields/field_hashers/expander/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index f7603d494..c948ee515 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -20,14 +20,15 @@ pub struct DST(arrayvec::ArrayVec); impl DST { pub fn new_xmd(dst: &[u8]) -> DST { - DST(if dst.len() > MAX_DST_LENGTH { + let array = if dst.len() > MAX_DST_LENGTH { let mut long = H::default(); long.update(&LONG_DST_PREFIX[..]); long.update(&dst); - ArrayVec::try_from(long.finalize_fixed().as_ref()).unwrap() + (long.finalize_fixed().as_ref()).try_into() } else { - ArrayVec::try_from(dst).unwrap() - }) + dst.try_into() + }; + DST(array.unwrap()) } pub fn new_xof(dst: &[u8], k: usize) -> DST { From 10dfaff60bdb50309501f4b70e21ebd88b151797 Mon Sep 17 00:00:00 2001 From: Jeff Burdges Date: Tue, 12 Sep 2023 14:36:56 +0200 Subject: [PATCH 21/25] Update mod.rs s/count/N/ --- ff/src/fields/field_hashers/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ff/src/fields/field_hashers/mod.rs b/ff/src/fields/field_hashers/mod.rs index f0fdaebb9..76e17f6dd 100644 --- a/ff/src/fields/field_hashers/mod.rs +++ b/ff/src/fields/field_hashers/mod.rs @@ -17,7 +17,7 @@ pub trait HashToField: Sized { /// * `domain` - bytes that get concatenated with the `msg` during hashing, in order to separate potentially interfering instantiations of the hasher. fn new(domain: &[u8]) -> Self; - /// Hash an arbitrary `msg` to #`count` elements from field `F`. + /// Hash an arbitrary `msg` to `N` elements of the field `F`. fn hash_to_field(&self, msg: &[u8]) -> [F; N]; } @@ -65,7 +65,7 @@ impl Ha fn hash_to_field(&self, message: &[u8]) -> [F; N] { let m = F::extension_degree() as usize; - // The user imposes a `count` of elements of F_p^m to output per input msg, + // The user requests `N` of elements of F_p^m to output per input msg, // each field element comprising `m` BasePrimeField elements. let len_in_bytes = N * m * self.len_per_base_elem; let uniform_bytes = self.expander.expand(message, len_in_bytes); From dddf9f7b2a9751633d9c8869c8e7479e44a5e8a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Tue, 12 Sep 2023 14:49:31 +0200 Subject: [PATCH 22/25] Fix breakage from style fix --- ff/src/fields/field_hashers/expander/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index c948ee515..af41974fe 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -24,11 +24,11 @@ impl DST { let mut long = H::default(); long.update(&LONG_DST_PREFIX[..]); long.update(&dst); - (long.finalize_fixed().as_ref()).try_into() + ArrayVec::try_from(long.finalize_fixed().as_ref()).unwrap() } else { - dst.try_into() - }; - DST(array.unwrap()) + ArrayVec::try_from(dst).unwrap() + }; + DST(array) } pub fn new_xof(dst: &[u8], k: usize) -> DST { @@ -40,11 +40,11 @@ impl DST { let mut new_dst = [0u8; MAX_DST_LENGTH]; let new_dst = &mut new_dst[0..((2 * k + 7) >> 3)]; long.finalize_xof_into(new_dst); - new_dst.try_into() + ArrayVec::try_from(&*new_dst).unwrap() } else { - dst.try_into() + ArrayVec::try_from(dst).unwrap() }; - DST(array.unwrap()) + DST(array) } pub fn update(&self, h: &mut H) { From 5aa053b31e8562c5a61c96e6d849d74b880d3dd6 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Thu, 14 Sep 2023 16:34:32 -0700 Subject: [PATCH 23/25] Remove `ark_std::vec::Vec` --- ff/src/fields/field_hashers/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/ff/src/fields/field_hashers/mod.rs b/ff/src/fields/field_hashers/mod.rs index 76e17f6dd..723737a83 100644 --- a/ff/src/fields/field_hashers/mod.rs +++ b/ff/src/fields/field_hashers/mod.rs @@ -2,7 +2,6 @@ mod expander; use crate::{Field, PrimeField}; -use ark_std::vec::Vec; use digest::{FixedOutputReset, XofReader}; use expander::Expander; From 34a7211f990758eee7cf47e6e01b39e2b394d31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Tue, 19 Sep 2023 16:17:56 -0400 Subject: [PATCH 24/25] The hasher H could be PhantomData already. --- ff/src/fields/field_hashers/expander/mod.rs | 6 ++++-- ff/src/fields/field_hashers/mod.rs | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index af41974fe..aae7b26e6 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -1,6 +1,8 @@ // The below implementation is a rework of https://github.com/armfazh/h2c-rust-ref // With some optimisations +use core::marker::PhantomData; + use ark_std::vec::Vec; use arrayvec::ArrayVec; @@ -55,7 +57,7 @@ impl DST { } pub(super) struct ExpanderXof { - pub(super) xofer: H, + pub(super) xofer: PhantomData, pub(super) dst: Vec, pub(super) k: usize, } @@ -75,7 +77,7 @@ impl Expander for ExpanderXof { } pub(super) struct ExpanderXmd { - pub(super) hasher: H, + pub(super) hasher: PhantomData, pub(super) dst: Vec, pub(super) block_size: usize, } diff --git a/ff/src/fields/field_hashers/mod.rs b/ff/src/fields/field_hashers/mod.rs index 723737a83..f8bd0b26b 100644 --- a/ff/src/fields/field_hashers/mod.rs +++ b/ff/src/fields/field_hashers/mod.rs @@ -1,5 +1,7 @@ mod expander; +use core::marker::PhantomData; + use crate::{Field, PrimeField}; use digest::{FixedOutputReset, XofReader}; @@ -50,7 +52,7 @@ impl Ha let len_per_base_elem = get_len_per_elem::(); let expander = ExpanderXmd { - hasher: H::default(), + hasher: PhantomData, dst: dst.to_vec(), block_size: len_per_base_elem, }; From 93bd53c9584af6ddd4d23e2f8de6948a110f7165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Jeff?= <¨burdges@gnunet.org¨> Date: Tue, 19 Sep 2023 16:25:38 -0400 Subject: [PATCH 25/25] Oops not sure why these never ran locally. --- ff/src/fields/field_hashers/expander/mod.rs | 2 +- ff/src/fields/field_hashers/expander/tests.rs | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/ff/src/fields/field_hashers/expander/mod.rs b/ff/src/fields/field_hashers/expander/mod.rs index aae7b26e6..16cc17df5 100644 --- a/ff/src/fields/field_hashers/expander/mod.rs +++ b/ff/src/fields/field_hashers/expander/mod.rs @@ -29,7 +29,7 @@ impl DST { ArrayVec::try_from(long.finalize_fixed().as_ref()).unwrap() } else { ArrayVec::try_from(dst).unwrap() - }; + }; DST(array) } diff --git a/ff/src/fields/field_hashers/expander/tests.rs b/ff/src/fields/field_hashers/expander/tests.rs index 36b4190f9..eeebc64a7 100644 --- a/ff/src/fields/field_hashers/expander/tests.rs +++ b/ff/src/fields/field_hashers/expander/tests.rs @@ -5,6 +5,7 @@ use sha3::{Shake128, Shake256}; use std::{ fs::{read_dir, File}, io::BufReader, + marker::PhantomData, }; use super::{Expander, ExpanderXmd, ExpanderXof}; @@ -99,29 +100,29 @@ fn get_expander(id: ExpID, _dst: &[u8], k: usize) -> Box { match id { ExpID::XMD(h) => match h { HashID::SHA256 => Box::new(ExpanderXmd { - hasher: Sha256::default(), + hasher: PhantomData::, block_size: 64, dst, }), HashID::SHA384 => Box::new(ExpanderXmd { - hasher: Sha384::default(), + hasher: PhantomData::, block_size: 128, dst, }), HashID::SHA512 => Box::new(ExpanderXmd { - hasher: Sha512::default(), + hasher: PhantomData::, block_size: 128, dst, }), }, ExpID::XOF(x) => match x { XofID::SHAKE128 => Box::new(ExpanderXof { - xofer: Shake128::default(), + xofer: PhantomData::, k, dst, }), XofID::SHAKE256 => Box::new(ExpanderXof { - xofer: Shake256::default(), + xofer: PhantomData::, k, dst, }),