From 4b4e7f81b6a1da0f08797d2d7a112eb398fadb27 Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Thu, 30 Jun 2022 16:23:24 -0700 Subject: [PATCH 1/6] update expand_message API Signed-off-by: Andrew Whitehead --- Cargo.lock | 8 +- Cargo.toml | 4 +- README.md | 2 +- src/hash_to_curve/expand_msg.rs | 318 +++--- src/hash_to_curve/map_g1.rs | 12 +- src/hash_to_curve/map_g2.rs | 5 +- src/hash_to_curve/map_scalar.rs | 8 +- src/hash_to_curve/mod.rs | 45 +- tests/expand_msg.rs | 1736 +++++++++++++++---------------- tests/hash_to_curve_g1.rs | 178 ++-- tests/hash_to_curve_g2.rs | 221 ++-- 11 files changed, 1302 insertions(+), 1235 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bc32847..9932b17b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -62,7 +62,7 @@ dependencies = [ "digest", "ff", "group", - "hex", + "hex-literal", "pairing", "rand_core", "rand_xorshift", @@ -301,10 +301,10 @@ dependencies = [ ] [[package]] -name = "hex" -version = "0.4.3" +name = "hex-literal" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" [[package]] name = "itertools" diff --git a/Cargo.toml b/Cargo.toml index 4ce37dbb..31ca30f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ rustdoc-args = [ "--html-in-header", "katex-header.html" ] [dev-dependencies] csv = ">= 1.0, < 1.2" # csv 1.2 has MSRV 1.60 criterion = "0.3" -hex = "0.4" +hex-literal = "0.3" rand_xorshift = "0.3" sha2 = "0.9" sha3 = "0.9" @@ -69,7 +69,7 @@ bits = ["ff/bits"] groups = ["group"] pairings = ["groups", "pairing"] alloc = ["group/alloc"] -experimental = ["digest"] +experimental = ["digest", "groups"] nightly = ["subtle/nightly"] [[test]] diff --git a/README.md b/README.md index 9a099e23..daa916cb 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ If you want to propose "substantial" changes to this crate, please * `alloc` (on by default): Enables APIs that require an allocator; these include pairing optimizations. * `nightly`: Enables `subtle/nightly` which tries to prevent compiler optimizations that could jeopardize constant time operations. Requires the nightly Rust compiler. * `experimental`: Enables experimental features. These features have no backwards-compatibility guarantees and may change at any time; users that depend on specific behaviour should pin an exact version of this crate. The current list of experimental features: - * Hashing to curves ([Internet Draft v12](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-12)) + * Hashing to curves ([Internet Draft v16](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16)) ## [Documentation](https://docs.rs/bls12_381) diff --git a/src/hash_to_curve/expand_msg.rs b/src/hash_to_curve/expand_msg.rs index 6c49d38e..4e816fd5 100644 --- a/src/hash_to_curve/expand_msg.rs +++ b/src/hash_to_curve/expand_msg.rs @@ -1,104 +1,180 @@ //! This module implements message expansion consistent with the -//! hash-to-curve RFC drafts 7 through 10 +//! hash-to-curve RFC drafts 7 through 16 -use core::{ - fmt::{self, Debug, Formatter}, - marker::PhantomData, -}; +use core::fmt::{self, Debug, Formatter}; -use digest::{BlockInput, Digest, ExtendableOutputDirty, Update, XofReader}; +use digest::{ + generic_array::typenum::IsLess, BlockInput, ExtendableOutput, FixedOutput, Update, XofReader, +}; use crate::generic_array::{ - typenum::{Unsigned, U32}, + typenum::{Unsigned, U256}, ArrayLength, GenericArray, }; #[cfg(feature = "alloc")] use alloc::vec::Vec; +const MAX_DST_LENGTH: usize = 255; const OVERSIZE_DST_SALT: &[u8] = b"H2C-OVERSIZE-DST-"; /// The domain separation tag for a message expansion. /// -/// Implements [section 5.4.3 of `draft-irtf-cfrg-hash-to-curve-12`][dst]. +/// Implements [section 5.3.3 of `draft-irtf-cfrg-hash-to-curve-16`][dst]. /// -/// [dst]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-12#section-5.4.3 +/// [dst]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3 #[derive(Debug)] -enum ExpandMsgDst<'x, L: ArrayLength> { - /// DST produced by hashing a very long (> 255 chars) input DST. - Hashed(GenericArray), - /// A raw input DST (<= 255 chars). - Raw(&'x [u8]), +struct ExpandMsgDst { + dst: [u8; MAX_DST_LENGTH], + len: usize, } -impl<'x, L: ArrayLength> ExpandMsgDst<'x, L> { +impl ExpandMsgDst { + #[inline] + fn new(init: impl FnOnce(&mut [u8; MAX_DST_LENGTH]) -> usize) -> Self { + let mut slf = ExpandMsgDst { + dst: [0u8; MAX_DST_LENGTH], + len: 0, + }; + slf.len = init(&mut slf.dst); + assert!(slf.len <= MAX_DST_LENGTH); + slf + } + /// Produces a DST for use with `expand_message_xof`. - pub fn process_xof(dst: &'x [u8]) -> Self + pub fn for_xof(dst: &[u8]) -> Self where - H: Default + Update + ExtendableOutputDirty, + H: Default + Update + ExtendableOutput, + L: ArrayLength + IsLess, { - if dst.len() > 255 { - let mut data = GenericArray::::default(); - H::default() - .chain(OVERSIZE_DST_SALT) - .chain(&dst) - .finalize_xof_dirty() - .read(&mut data); - Self::Hashed(data) - } else { - Self::Raw(dst) - } + let input_len = dst.len(); + ExpandMsgDst::new(|buf| { + if input_len > MAX_DST_LENGTH { + H::default() + .chain(OVERSIZE_DST_SALT) + .chain(&dst) + .finalize_xof() + .read(&mut buf[..L::USIZE]); + L::USIZE + } else { + buf[..input_len].copy_from_slice(dst); + input_len + } + }) } /// Produces a DST for use with `expand_message_xmd`. - pub fn process_xmd(dst: &'x [u8]) -> Self + pub fn for_xmd(dst: &[u8]) -> Self where - H: Digest, + H: Default + FixedOutput + Update, { - if dst.len() > 255 { - Self::Hashed(H::new().chain(OVERSIZE_DST_SALT).chain(&dst).finalize()) - } else { - Self::Raw(dst) - } + let input_len = dst.len(); + ExpandMsgDst::new(|buf| { + if input_len > MAX_DST_LENGTH { + let hashed = H::default() + .chain(OVERSIZE_DST_SALT) + .chain(&dst) + .finalize_fixed(); + let len = hashed.len().min(MAX_DST_LENGTH); + buf[..len].copy_from_slice(&hashed); + len + } else { + buf[..input_len].copy_from_slice(dst); + input_len + } + }) } /// Returns the raw bytes of the DST. - pub fn data(&'x self) -> &'x [u8] { - match self { - Self::Hashed(arr) => &arr[..], - Self::Raw(buf) => buf, - } + pub fn data(&self) -> &[u8] { + &self.dst[..self.len] } /// Returns the length of the DST. - pub fn len(&'x self) -> usize { - match self { - Self::Hashed(_) => L::to_usize(), - Self::Raw(buf) => buf.len(), + pub fn len(&self) -> usize { + self.len + } +} + +/// A trait allowing flexible support for message input types. +pub trait Message { + /// Consume the message input. + /// + /// The parameters to successive calls to `f` are treated as a + /// single concatenated octet string. + fn consume(self, f: impl FnMut(&[u8])); +} + +impl Message for &[u8] { + #[inline] + fn consume(self, mut f: impl FnMut(&[u8])) { + f(self) + } +} + +impl Message for &[u8; N] { + #[inline] + fn consume(self, mut f: impl FnMut(&[u8])) { + f(self) + } +} + +impl Message for &str { + #[inline] + fn consume(self, mut f: impl FnMut(&[u8])) { + f(self.as_bytes()) + } +} + +impl Message for &[&[u8]] { + #[inline] + fn consume(self, mut f: impl FnMut(&[u8])) { + for msg in self { + f(msg); } } } -/// A trait for message expansion methods supported by hash-to-curve. -pub trait ExpandMessage: for<'x> InitExpandMessage<'x> { - // This intermediate is likely only necessary until GATs allow - // associated types with lifetimes. +#[cfg(feature = "alloc")] +impl Message for Vec { + #[inline] + fn consume(self, mut f: impl FnMut(&[u8])) { + f(self.as_slice()) + } } -/// Trait for constructing a new message expander. -pub trait InitExpandMessage<'x> { - /// The state object used during message expansion. - type Expander: ExpandMessageState<'x>; +#[cfg(feature = "alloc")] +impl Message for &Vec { + #[inline] + fn consume(self, mut f: impl FnMut(&[u8])) { + f(self.as_slice()) + } +} - /// Initializes a message expander. - fn init_expand(message: &[u8], dst: &'x [u8], len_in_bytes: usize) -> Self::Expander; +#[cfg(feature = "alloc")] +impl Message for alloc::string::String { + #[inline] + fn consume(self, mut f: impl FnMut(&[u8])) { + f(self.as_bytes()) + } +} + +#[cfg(feature = "alloc")] +impl Message for &alloc::string::String { + #[inline] + fn consume(self, mut f: impl FnMut(&[u8])) { + f(self.as_bytes()) + } } -// Automatically derive trait -impl InitExpandMessage<'x>> ExpandMessage for X {} +/// A trait for message expansion methods supported by hash-to-curve. +pub trait ExpandMessage { + /// Initializes a message expander. + fn init_expand(message: M, dst: &[u8], len_in_bytes: usize) -> Self + where + M: Message, + L: ArrayLength + IsLess; -/// Trait for types implementing the `expand_message` interface for `hash_to_field`. -pub trait ExpandMessageState<'x> { /// Reads bytes from the generated output. fn read_into(&mut self, output: &mut [u8]) -> usize; @@ -120,16 +196,18 @@ pub trait ExpandMessageState<'x> { /// A generator for the output of `expand_message_xof` for a given /// extendable hash function, message, DST, and output length. /// -/// Implements [section 5.4.2 of `draft-irtf-cfrg-hash-to-curve-12`][expand_message_xof] -/// with `k = 128`. +/// Implements [section 5.3.2 of `draft-irtf-cfrg-hash-to-curve-16`][expand_message_xof]. /// -/// [expand_message_xof]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-12#section-5.4.2 -pub struct ExpandMsgXof { - hash: ::Reader, +/// The length parameter L defaults to U32, corresponding to the target security level of +/// k = 128 for both defined BLS12-381 ciphersuites. +/// +/// [expand_message_xof]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.2 +pub struct ExpandMsgXof { + reader: ::Reader, remain: usize, } -impl Debug for ExpandMsgXof { +impl Debug for ExpandMsgXof { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("ExpandMsgXof") .field("remain", &self.remain) @@ -137,13 +215,36 @@ impl Debug for ExpandMsgXof { } } -impl<'x, H> ExpandMessageState<'x> for ExpandMsgXof +impl ExpandMessage for ExpandMsgXof where - H: ExtendableOutputDirty, + H: Default + ExtendableOutput + Update, { + fn init_expand(message: M, dst: &[u8], len_in_bytes: usize) -> Self + where + M: Message, + L: ArrayLength + IsLess, + { + if len_in_bytes > u16::MAX as usize { + panic!("Invalid ExpandMsgXof usage: len_in_bytes > u16::MAX"); + } + + let dst = ExpandMsgDst::for_xof::(dst); + let mut hash = H::default(); + message.consume(|m| hash.update(m)); + let reader = hash + .chain((len_in_bytes as u16).to_be_bytes()) + .chain(dst.data()) + .chain([dst.len() as u8]) + .finalize_xof(); + Self { + reader, + remain: len_in_bytes, + } + } + fn read_into(&mut self, output: &mut [u8]) -> usize { let len = self.remain.min(output.len()); - self.hash.read(&mut output[..len]); + self.reader.read(&mut output[..len]); self.remain -= len; len } @@ -153,45 +254,14 @@ where } } -impl<'x, H> InitExpandMessage<'x> for ExpandMsgXof -where - H: Default + Update + ExtendableOutputDirty, -{ - type Expander = Self; - - fn init_expand(message: &[u8], dst: &[u8], len_in_bytes: usize) -> Self { - // Use U32 here for k = 128. - let dst = ExpandMsgDst::::process_xof::(dst); - let hash = H::default() - .chain(message) - .chain((len_in_bytes as u16).to_be_bytes()) - .chain(dst.data()) - .chain([dst.len() as u8]) - .finalize_xof_dirty(); - Self { - hash, - remain: len_in_bytes, - } - } -} - -/// Constructor for `expand_message_xmd` for a given digest hash function, message, DST, -/// and output length. -/// -/// Implements [section 5.4.1 of `draft-irtf-cfrg-hash-to-curve-12`][expand_message_xmd]. -/// -/// [expand_message_xmd]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-12#section-5.4.1 -#[derive(Debug)] -pub struct ExpandMsgXmd(PhantomData); - /// A generator for the output of `expand_message_xmd` for a given /// digest hash function, message, DST, and output length. /// -/// Implements [section 5.4.1 of `draft-irtf-cfrg-hash-to-curve-12`][expand_message_xmd]. +/// Implements [section 5.3.1 of `draft-irtf-cfrg-hash-to-curve-16`][expand_message_xmd]. /// -/// [expand_message_xmd]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-12#section-5.4.1 -pub struct ExpandMsgXmdState<'x, H: Digest> { - dst: ExpandMsgDst<'x, H::OutputSize>, +/// [expand_message_xmd]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.1 +pub struct ExpandMsgXmd { + dst: ExpandMsgDst, b_0: GenericArray, b_i: GenericArray, i: usize, @@ -199,43 +269,46 @@ pub struct ExpandMsgXmdState<'x, H: Digest> { remain: usize, } -impl Debug for ExpandMsgXmdState<'_, H> { +impl Debug for ExpandMsgXmd { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("ExpandMsgXmdState") + f.debug_struct("ExpandMsgXmd") .field("remain", &self.remain) .finish() } } -impl<'x, H> InitExpandMessage<'x> for ExpandMsgXmd +impl ExpandMessage for ExpandMsgXmd where - H: Digest + BlockInput, + H: Default + BlockInput + FixedOutput + Update, { - type Expander = ExpandMsgXmdState<'x, H>; - - fn init_expand(message: &[u8], dst: &'x [u8], len_in_bytes: usize) -> Self::Expander { - let hash_size = ::OutputSize::to_usize(); + fn init_expand(message: M, dst: &[u8], len_in_bytes: usize) -> Self + where + M: Message, + L: ArrayLength + IsLess, + { + let hash_size = ::OutputSize::to_usize(); let ell = (len_in_bytes + hash_size - 1) / hash_size; if ell > 255 { panic!("Invalid ExpandMsgXmd usage: ell > 255"); } - let dst = ExpandMsgDst::process_xmd::(dst); - let b_0 = H::new() - .chain(GenericArray::::BlockSize>::default()) - .chain(message) + let dst = ExpandMsgDst::for_xmd::(dst); + let mut hash_b_0 = + H::default().chain(GenericArray::::BlockSize>::default()); + message.consume(|m| hash_b_0.update(m)); + let b_0 = hash_b_0 .chain((len_in_bytes as u16).to_be_bytes()) .chain([0u8]) .chain(dst.data()) .chain([dst.len() as u8]) - .finalize(); + .finalize_fixed(); // init with b_1 - let b_i = H::new() + let b_i = H::default() .chain(&b_0) .chain([1u8]) .chain(dst.data()) .chain([dst.len() as u8]) - .finalize(); - ExpandMsgXmdState { + .finalize_fixed(); + ExpandMsgXmd { dst, b_0, b_i, @@ -244,12 +317,7 @@ where remain: len_in_bytes, } } -} -impl<'x, H> ExpandMessageState<'x> for ExpandMsgXmdState<'x, H> -where - H: Digest + BlockInput, -{ fn read_into(&mut self, output: &mut [u8]) -> usize { let read_len = self.remain.min(output.len()); let mut offs = 0; @@ -268,12 +336,12 @@ where for j in 0..hash_size { b_prev_xor[j] ^= self.b_i[j]; } - self.b_i = H::new() + self.b_i = H::default() .chain(b_prev_xor) .chain([self.i as u8]) .chain(self.dst.data()) .chain([self.dst.len() as u8]) - .finalize(); + .finalize_fixed(); self.b_offs = 0; self.i += 1; } diff --git a/src/hash_to_curve/map_g1.rs b/src/hash_to_curve/map_g1.rs index 1f86a55d..e2165709 100644 --- a/src/hash_to_curve/map_g1.rs +++ b/src/hash_to_curve/map_g1.rs @@ -6,7 +6,10 @@ use super::chain::chain_pm3div4; use super::{HashToField, MapToCurve, Sgn0}; use crate::fp::Fp; use crate::g1::G1Projective; -use crate::generic_array::{typenum::U64, GenericArray}; +use crate::generic_array::{ + typenum::{U32, U64}, + GenericArray, +}; /// Coefficients of the 11-isogeny x map's numerator const ISO11_XNUM: [Fp; 12] = [ @@ -504,6 +507,9 @@ impl HashToField for Fp { // ceil(log2(p)) = 381, m = 1, k = 128. type InputLength = U64; + // k = 128 + type XofOutputLength = U32; + fn from_okm(okm: &GenericArray) -> Fp { const F_2_256: Fp = Fp::from_raw_unchecked([ 0x075b_3cd7_c5ce_820f, @@ -538,9 +544,9 @@ impl Sgn0 for Fp { /// Maps an element of [`Fp`] to a point on iso-G1. /// -/// Implements [section 6.6.2 of `draft-irtf-cfrg-hash-to-curve-12`][sswu]. +/// Implements [section 6.6.2 of `draft-irtf-cfrg-hash-to-curve-16`][sswu]. /// -/// [sswu]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-12#section-6.6.2 +/// [sswu]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-6.6.2 fn map_to_curve_simple_swu(u: &Fp) -> G1Projective { let usq = u.square(); let xi_usq = SSWU_XI * usq; diff --git a/src/hash_to_curve/map_g2.rs b/src/hash_to_curve/map_g2.rs index 72ff3235..5737b29d 100644 --- a/src/hash_to_curve/map_g2.rs +++ b/src/hash_to_curve/map_g2.rs @@ -5,7 +5,7 @@ use subtle::{Choice, ConditionallyNegatable, ConditionallySelectable, ConstantTi use super::chain::chain_p2m9div16; use super::{HashToField, MapToCurve, Sgn0}; use crate::generic_array::{ - typenum::{U128, U64}, + typenum::{U128, U32, U64}, GenericArray, }; use crate::{fp::Fp, fp2::Fp2, g2::G2Projective}; @@ -368,6 +368,9 @@ impl HashToField for Fp2 { // ceil(log2(p)) = 381, m = 2, k = 128. type InputLength = U128; + // k = 128 + type XofOutputLength = U32; + fn from_okm(okm: &GenericArray) -> Fp2 { let c0 = ::from_okm(GenericArray::::from_slice(&okm[..64])); let c1 = ::from_okm(GenericArray::::from_slice(&okm[64..])); diff --git a/src/hash_to_curve/map_scalar.rs b/src/hash_to_curve/map_scalar.rs index ec4bb9e0..539c129c 100644 --- a/src/hash_to_curve/map_scalar.rs +++ b/src/hash_to_curve/map_scalar.rs @@ -1,13 +1,19 @@ //! Implementation of hash-to-field for Scalar values use super::HashToField; -use crate::generic_array::{typenum::U48, GenericArray}; +use crate::generic_array::{ + typenum::{U32, U48}, + GenericArray, +}; use crate::scalar::Scalar; impl HashToField for Scalar { // ceil(log2(p)) = 255, m = 1, k = 128. type InputLength = U48; + // k = 128 + type XofOutputLength = U32; + fn from_okm(okm: &GenericArray) -> Scalar { let mut bs = [0u8; 64]; bs[16..].copy_from_slice(okm); diff --git a/src/hash_to_curve/mod.rs b/src/hash_to_curve/mod.rs index 4c15a498..2f688a54 100644 --- a/src/hash_to_curve/mod.rs +++ b/src/hash_to_curve/mod.rs @@ -8,21 +8,22 @@ use subtle::Choice; pub(crate) mod chain; mod expand_msg; -pub use self::expand_msg::{ - ExpandMessage, ExpandMessageState, ExpandMsgXmd, ExpandMsgXof, InitExpandMessage, -}; +pub use self::expand_msg::{ExpandMessage, ExpandMsgXmd, ExpandMsgXof, Message}; mod map_g1; mod map_g2; mod map_scalar; -use crate::generic_array::{typenum::Unsigned, ArrayLength, GenericArray}; +use crate::generic_array::{ + typenum::{IsLess, Unsigned, U256}, + ArrayLength, GenericArray, +}; /// Enables a byte string to be hashed into one or more field elements for a given curve. /// -/// Implements [section 5 of `draft-irtf-cfrg-hash-to-curve-12`][hash_to_field]. +/// Implements [section 5 of `draft-irtf-cfrg-hash-to-curve-16`][hash_to_field]. /// -/// [hash_to_field]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-12#section-5 +/// [hash_to_field]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5 pub trait HashToField: Sized { /// The length of the data used to produce an individual field element. /// @@ -31,6 +32,12 @@ pub trait HashToField: Sized { /// security parameter. type InputLength: ArrayLength; + /// The number of bytes to read from the extensible output hash function. + /// + /// This must be set to `ceil(2 * k / 8)`, where `k` is the security parameter. This + /// is used when handling DST values longer than 255 bytes. + type XofOutputLength: ArrayLength + IsLess; + /// Interprets the given output keying material as a big endian integer, and reduces /// it into a field element. fn from_okm(okm: &GenericArray) -> Self; @@ -38,13 +45,17 @@ pub trait HashToField: Sized { /// Hashes a byte string of arbitrary length into one or more elements of `Self`, /// using [`ExpandMessage`] variant `X`. /// - /// Implements [section 5.3 of `draft-irtf-cfrg-hash-to-curve-12`][hash_to_field]. + /// Implements [section 5.2 of `draft-irtf-cfrg-hash-to-curve-16`][hash_to_field]. /// - /// [hash_to_field]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-12#section-5.3 - fn hash_to_field(message: &[u8], dst: &[u8], output: &mut [Self]) { + /// [hash_to_field]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.2 + fn hash_to_field(message: M, dst: &[u8], output: &mut [Self]) + where + X: ExpandMessage, + M: Message, + { let len_per_elm = Self::InputLength::to_usize(); let len_in_bytes = output.len() * len_per_elm; - let mut expander = X::init_expand(message, dst, len_in_bytes); + let mut expander = X::init_expand::(message, dst, len_in_bytes); let mut buf = GenericArray::::default(); output.iter_mut().for_each(|item| { @@ -72,9 +83,9 @@ pub trait HashToCurve: MapToCurve + for<'a> Add<&'a Self, Outp /// /// This function is suitable for most applications requiring a random /// oracle returning points in `Self`. - fn hash_to_curve(message: impl AsRef<[u8]>, dst: &[u8]) -> Self { + fn hash_to_curve(message: M, dst: &[u8]) -> Self { let mut u = [Self::Field::default(); 2]; - Self::Field::hash_to_field::(message.as_ref(), dst, &mut u); + Self::Field::hash_to_field::(message, dst, &mut u); let p1 = Self::map_to_curve(&u[0]); let p2 = Self::map_to_curve(&u[1]); (p1 + &p2).clear_h() @@ -85,13 +96,13 @@ pub trait HashToCurve: MapToCurve + for<'a> Add<&'a Self, Outp /// The distribution of its output is not uniformly random in `Self`: the set of /// possible outputs of this function is only a fraction of the points in `Self`, and /// some elements of this set are more likely to be output than others. See - /// [section 10.1 of `draft-irtf-cfrg-hash-to-curve-12`][encode_to_curve-distribution] + /// [section 10.4 of `draft-irtf-cfrg-hash-to-curve-16`][encode_to_curve-distribution] /// for a more precise definition of `encode_to_curve`'s output distribution. /// - /// [encode_to_curve-distribution]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-12#section-10.1 - fn encode_to_curve(message: impl AsRef<[u8]>, dst: &[u8]) -> Self { + /// [encode_to_curve-distribution]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-10.4 + fn encode_to_curve(message: M, dst: &[u8]) -> Self { let mut u = [Self::Field::default(); 1]; - Self::Field::hash_to_field::(message.as_ref(), dst, &mut u); + Self::Field::hash_to_field::(message, dst, &mut u); let p = Self::map_to_curve(&u[0]); p.clear_h() } @@ -107,7 +118,7 @@ where pub(crate) trait Sgn0 { /// Returns either 0 or 1 indicating the "sign" of x, where sgn0(x) == 1 /// just when x is "negative". (In other words, this function always considers 0 to be positive.) - /// + /// /// The equivalent for draft 6 would be `lexicographically_largest`. fn sgn0(&self) -> Choice; } diff --git a/tests/expand_msg.rs b/tests/expand_msg.rs index 234ad6b3..ff8a5528 100644 --- a/tests/expand_msg.rs +++ b/tests/expand_msg.rs @@ -1,146 +1,166 @@ -use bls12_381::hash_to_curve::{ExpandMessageState, ExpandMsgXmd, ExpandMsgXof, InitExpandMessage}; +use bls12_381::hash_to_curve::*; +use digest::generic_array::typenum::U32; +use hex_literal::hex; use sha2::{Sha256, Sha512}; use sha3::{Shake128, Shake256}; -/// From +struct TestCase { + msg: &'static [u8], + dst: &'static [u8], + len_in_bytes: usize, + uniform_bytes: &'static [u8], +} + +impl TestCase { + #[track_caller] + pub fn run(self) { + let mut buf = [0u8; 128]; + let output = &mut buf[..self.len_in_bytes]; + E::init_expand::<_, U32>(self.msg, self.dst, self.len_in_bytes).read_into(output); + if output != self.uniform_bytes { + panic!( + "Failed: expand_message.\n\ + Message: {:x?}\n\ + DST: {:x?}\n\ + Expected: {:x?}\n\ + Found: {:x?}", + self.msg, self.dst, self.uniform_bytes, output + ) + } + } +} + +/// From #[test] -fn expand_message_xmd_works_for_draft12_testvectors_sha256() { +fn expand_msg_xmd_works_for_draft16_testvectors_sha256() { let dst = b"QUUX-V01-CS02-with-expander-SHA256-128"; - let msg = b""; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "68a985b87eb6b46952128911f2a4412bbc302a9d759667f8\ - 7f7a21d803f07235", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abc"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "d8ccab23b5985ccea865c6c97b6e5b8350e794e603b4b979\ - 02f53a8a0d605615", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abcdef0123456789"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "eff31487c770a893cfb36f912fbfcbff40d5661771ca4b2c\ - b4eafe524333f5c1", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ - qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ - qqqqqqqqqqqqqqqqqqqqqqqqq"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "b23a1d2b4d97b2ef7785562a7e8bac7eed54ed6e97e29aa5\ - 1bfe3f12ddad1ff9", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "4623227bcc01293b8c130bf771da8c298dede7383243dc09\ - 93d2d94823958c4c", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b""; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "af84c27ccfd45d41914fdff5df25293e221afc53d8ad2ac0\ - 6d5e3e29485dadbee0d121587713a3e0dd4d5e69e93eb7cd4f5df4\ - cd103e188cf60cb02edc3edf18eda8576c412b18ffb658e3dd6ec8\ - 49469b979d444cf7b26911a08e63cf31f9dcc541708d3491184472\ - c2c29bb749d4286b004ceb5ee6b9a7fa5b646c993f0ced", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abc"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "abba86a6129e366fc877aab32fc4ffc70120d8996c88aee2\ - fe4b32d6c7b6437a647e6c3163d40b76a73cf6a5674ef1d890f95b\ - 664ee0afa5359a5c4e07985635bbecbac65d747d3d2da7ec2b8221\ - b17b0ca9dc8a1ac1c07ea6a1e60583e2cb00058e77b7b72a298425\ - cd1b941ad4ec65e8afc50303a22c0f99b0509b4c895f40", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abcdef0123456789"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "ef904a29bffc4cf9ee82832451c946ac3c8f8058ae97d8d6\ - 29831a74c6572bd9ebd0df635cd1f208e2038e760c4994984ce73f\ - 0d55ea9f22af83ba4734569d4bc95e18350f740c07eef653cbb9f8\ - 7910d833751825f0ebefa1abe5420bb52be14cf489b37fe1a72f7d\ - e2d10be453b2c9d9eb20c7e3f6edc5a60629178d9478df", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ + TestCase { + msg: b"", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "68a985b87eb6b46952128911f2a4412bbc302a9d759667f8 + 7f7a21d803f07235" + ), + } + .run::>(); + + TestCase { + msg: b"abc", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "d8ccab23b5985ccea865c6c97b6e5b8350e794e603b4b979 + 02f53a8a0d605615" + ), + } + .run::>(); + + TestCase { + msg: b"abcdef0123456789", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "eff31487c770a893cfb36f912fbfcbff40d5661771ca4b2c + b4eafe524333f5c1" + ), + } + .run::>(); + + TestCase { + msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ + qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ + qqqqqqqqqqqqqqqqqqqqqqqqq", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "b23a1d2b4d97b2ef7785562a7e8bac7eed54ed6e97e29aa5 + 1bfe3f12ddad1ff9" + ), + } + .run::>(); + + TestCase { + msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "4623227bcc01293b8c130bf771da8c298dede7383243dc09 + 93d2d94823958c4c" + ), + } + .run::>(); + + TestCase { + msg: b"", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "af84c27ccfd45d41914fdff5df25293e221afc53d8ad2ac0 + 6d5e3e29485dadbee0d121587713a3e0dd4d5e69e93eb7cd4f5df4 + cd103e188cf60cb02edc3edf18eda8576c412b18ffb658e3dd6ec8 + 49469b979d444cf7b26911a08e63cf31f9dcc541708d3491184472 + c2c29bb749d4286b004ceb5ee6b9a7fa5b646c993f0ced" + ), + } + .run::>(); + + TestCase { + msg: b"abc", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "abba86a6129e366fc877aab32fc4ffc70120d8996c88aee2 + fe4b32d6c7b6437a647e6c3163d40b76a73cf6a5674ef1d890f95b + 664ee0afa5359a5c4e07985635bbecbac65d747d3d2da7ec2b8221 + b17b0ca9dc8a1ac1c07ea6a1e60583e2cb00058e77b7b72a298425 + cd1b941ad4ec65e8afc50303a22c0f99b0509b4c895f40" + ), + } + .run::>(); + + TestCase { + msg: b"abcdef0123456789", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "ef904a29bffc4cf9ee82832451c946ac3c8f8058ae97d8d6 + 29831a74c6572bd9ebd0df635cd1f208e2038e760c4994984ce73f + 0d55ea9f22af83ba4734569d4bc95e18350f740c07eef653cbb9f8 + 7910d833751825f0ebefa1abe5420bb52be14cf489b37fe1a72f7d + e2d10be453b2c9d9eb20c7e3f6edc5a60629178d9478df" + ), + } + .run::>(); + + TestCase { + msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ - qqqqqqqqqqqqqqqqqqqqqqqqq"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "80be107d0884f0d881bb460322f0443d38bd222db8bd0b0a\ - 5312a6fedb49c1bbd88fd75d8b9a09486c60123dfa1d73c1cc3169\ - 761b17476d3c6b7cbbd727acd0e2c942f4dd96ae3da5de368d26b3\ - 2286e32de7e5a8cb2949f866a0b80c58116b29fa7fabb3ea7d520e\ - e603e0c25bcaf0b9a5e92ec6a1fe4e0391d1cdbce8c68a", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); + qqqqqqqqqqqqqqqqqqqqqqqqq", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "80be107d0884f0d881bb460322f0443d38bd222db8bd0b0a + 5312a6fedb49c1bbd88fd75d8b9a09486c60123dfa1d73c1cc3169 + 761b17476d3c6b7cbbd727acd0e2c942f4dd96ae3da5de368d26b3 + 2286e32de7e5a8cb2949f866a0b80c58116b29fa7fabb3ea7d520e + e603e0c25bcaf0b9a5e92ec6a1fe4e0391d1cdbce8c68a" + ), + } + .run::>(); - let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + TestCase { + msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ @@ -149,165 +169,155 @@ fn expand_message_xmd_works_for_draft12_testvectors_sha256() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "546aff5444b5b79aa6148bd81728704c32decb73a3ba76e9\ - e75885cad9def1d06d6792f8a7d12794e90efed817d96920d72889\ - 6a4510864370c207f99bd4a608ea121700ef01ed879745ee3e4cee\ - f777eda6d9e5e38b90c86ea6fb0b36504ba4a45d22e86f6db5dd43\ - d98a294bebb9125d5b794e9d2a81181066eb954966a487", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "546aff5444b5b79aa6148bd81728704c32decb73a3ba76e9 + e75885cad9def1d06d6792f8a7d12794e90efed817d96920d72889 + 6a4510864370c207f99bd4a608ea121700ef01ed879745ee3e4cee + f777eda6d9e5e38b90c86ea6fb0b36504ba4a45d22e86f6db5dd43 + d98a294bebb9125d5b794e9d2a81181066eb954966a487" + ), + } + .run::>(); } -/// From +/// From #[test] -fn expand_message_xmd_works_for_draft12_testvectors_sha256_long_dst() { +fn expand_msg_xmd_works_for_draft16_testvectors_sha256_long_dst() { let dst = b"QUUX-V01-CS02-with-expander-SHA256-128-long-DST-111111\ 111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111111111111111111\ 1111111111111111111111111111111111111111"; - let msg = b""; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "e8dc0c8b686b7ef2074086fbdd2f30e3f8bfbd3bdf177f73\ - f04b97ce618a3ed3", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abc"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "52dbf4f36cf560fca57dedec2ad924ee9c266341d8f3d6af\ - e5171733b16bbb12", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abcdef0123456789"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "35387dcf22618f3728e6c686490f8b431f76550b0b2c61cb\ - c1ce7001536f4521", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ + TestCase { + msg: b"", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "e8dc0c8b686b7ef2074086fbdd2f30e3f8bfbd3bdf177f73 + f04b97ce618a3ed3" + ), + } + .run::>(); + + TestCase { + msg: b"abc", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "52dbf4f36cf560fca57dedec2ad924ee9c266341d8f3d6af + e5171733b16bbb12" + ), + } + .run::>(); + + TestCase { + msg: b"abcdef0123456789", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "35387dcf22618f3728e6c686490f8b431f76550b0b2c61cb + c1ce7001536f4521" + ), + } + .run::>(); + + TestCase { + msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ - qqqqqqqqqqqqqqqqqqqqqqqqq"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "01b637612bb18e840028be900a833a74414140dde0c4754c\ - 198532c3a0ba42bc", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "20cce7033cabc5460743180be6fa8aac5a103f56d481cf36\ - 9a8accc0c374431b", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b""; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "14604d85432c68b757e485c8894db3117992fc57e0e136f7\ - 1ad987f789a0abc287c47876978e2388a02af86b1e8d1342e5ce4f\ - 7aaa07a87321e691f6fba7e0072eecc1218aebb89fb14a0662322d\ - 5edbd873f0eb35260145cd4e64f748c5dfe60567e126604bcab1a3\ - ee2dc0778102ae8a5cfd1429ebc0fa6bf1a53c36f55dfc", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abc"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "1a30a5e36fbdb87077552b9d18b9f0aee16e80181d5b951d\ - 0471d55b66684914aef87dbb3626eaabf5ded8cd0686567e503853\ - e5c84c259ba0efc37f71c839da2129fe81afdaec7fbdc0ccd4c794\ - 727a17c0d20ff0ea55e1389d6982d1241cb8d165762dbc39fb0cee\ - 4474d2cbbd468a835ae5b2f20e4f959f56ab24cd6fe267", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abcdef0123456789"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "d2ecef3635d2397f34a9f86438d772db19ffe9924e28a1ca\ - f6f1c8f15603d4028f40891044e5c7e39ebb9b31339979ff33a424\ - 9206f67d4a1e7c765410bcd249ad78d407e303675918f20f26ce6d\ - 7027ed3774512ef5b00d816e51bfcc96c3539601fa48ef1c07e494\ - bdc37054ba96ecb9dbd666417e3de289d4f424f502a982", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ + qqqqqqqqqqqqqqqqqqqqqqqqq", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "01b637612bb18e840028be900a833a74414140dde0c4754c + 198532c3a0ba42bc" + ), + } + .run::>(); + + TestCase { + msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "20cce7033cabc5460743180be6fa8aac5a103f56d481cf36 + 9a8accc0c374431b" + ), + } + .run::>(); + + TestCase { + msg: b"", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "14604d85432c68b757e485c8894db3117992fc57e0e136f7 + 1ad987f789a0abc287c47876978e2388a02af86b1e8d1342e5ce4f + 7aaa07a87321e691f6fba7e0072eecc1218aebb89fb14a0662322d + 5edbd873f0eb35260145cd4e64f748c5dfe60567e126604bcab1a3 + ee2dc0778102ae8a5cfd1429ebc0fa6bf1a53c36f55dfc" + ), + } + .run::>(); + + TestCase { + msg: b"abc", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "1a30a5e36fbdb87077552b9d18b9f0aee16e80181d5b951d + 0471d55b66684914aef87dbb3626eaabf5ded8cd0686567e503853 + e5c84c259ba0efc37f71c839da2129fe81afdaec7fbdc0ccd4c794 + 727a17c0d20ff0ea55e1389d6982d1241cb8d165762dbc39fb0cee + 4474d2cbbd468a835ae5b2f20e4f959f56ab24cd6fe267" + ), + } + .run::>(); + + TestCase { + msg: b"abcdef0123456789", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "d2ecef3635d2397f34a9f86438d772db19ffe9924e28a1ca + f6f1c8f15603d4028f40891044e5c7e39ebb9b31339979ff33a424 + 9206f67d4a1e7c765410bcd249ad78d407e303675918f20f26ce6d + 7027ed3774512ef5b00d816e51bfcc96c3539601fa48ef1c07e494 + bdc37054ba96ecb9dbd666417e3de289d4f424f502a982" + ), + } + .run::>(); + + TestCase { + msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ - qqqqqqqqqqqqqqqqqqqqqqqqq"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "ed6e8c036df90111410431431a232d41a32c86e296c05d42\ - 6e5f44e75b9a50d335b2412bc6c91e0a6dc131de09c43110d9180d\ - 0a70f0d6289cb4e43b05f7ee5e9b3f42a1fad0f31bac6a625b3b5c\ - 50e3a83316783b649e5ecc9d3b1d9471cb5024b7ccf40d41d1751a\ - 04ca0356548bc6e703fca02ab521b505e8e45600508d32", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); + qqqqqqqqqqqqqqqqqqqqqqqqq", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "ed6e8c036df90111410431431a232d41a32c86e296c05d42 + 6e5f44e75b9a50d335b2412bc6c91e0a6dc131de09c43110d9180d + 0a70f0d6289cb4e43b05f7ee5e9b3f42a1fad0f31bac6a625b3b5c + 50e3a83316783b649e5ecc9d3b1d9471cb5024b7ccf40d41d1751a + 04ca0356548bc6e703fca02ab521b505e8e45600508d32" + ), + } + .run::>(); - let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + TestCase { + msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ @@ -316,161 +326,151 @@ fn expand_message_xmd_works_for_draft12_testvectors_sha256_long_dst() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "78b53f2413f3c688f07732c10e5ced29a17c6a16f717179f\ - fbe38d92d6c9ec296502eb9889af83a1928cd162e845b0d3c5424e\ - 83280fed3d10cffb2f8431f14e7a23f4c68819d40617589e4c4116\ - 9d0b56e0e3535be1fd71fbb08bb70c5b5ffed953d6c14bf7618b35\ - fc1f4c4b30538236b4b08c9fbf90462447a8ada60be495", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "78b53f2413f3c688f07732c10e5ced29a17c6a16f717179f + fbe38d92d6c9ec296502eb9889af83a1928cd162e845b0d3c5424e + 83280fed3d10cffb2f8431f14e7a23f4c68819d40617589e4c4116 + 9d0b56e0e3535be1fd71fbb08bb70c5b5ffed953d6c14bf7618b35 + fc1f4c4b30538236b4b08c9fbf90462447a8ada60be495" + ), + } + .run::>(); } -/// From +/// From #[test] -fn expand_message_xmd_works_for_draft12_testvectors_sha512() { +fn expand_msg_xmd_works_for_draft16_testvectors_sha512() { let dst = b"QUUX-V01-CS02-with-expander-SHA512-256"; - let msg = b""; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "6b9a7312411d92f921c6f68ca0b6380730a1a4d982c50721\ - 1a90964c394179ba", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abc"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "0da749f12fbe5483eb066a5f595055679b976e93abe9be6f\ - 0f6318bce7aca8dc", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abcdef0123456789"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "087e45a86e2939ee8b91100af1583c4938e0f5fc6c9db4b1\ - 07b83346bc967f58", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ + TestCase { + msg: b"", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "6b9a7312411d92f921c6f68ca0b6380730a1a4d982c50721 + 1a90964c394179ba" + ), + } + .run::>(); + + TestCase { + msg: b"abc", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "0da749f12fbe5483eb066a5f595055679b976e93abe9be6f + 0f6318bce7aca8dc" + ), + } + .run::>(); + + TestCase { + msg: b"abcdef0123456789", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "087e45a86e2939ee8b91100af1583c4938e0f5fc6c9db4b1 + 07b83346bc967f58" + ), + } + .run::>(); + + TestCase { + msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ - qqqqqqqqqqqqqqqqqqqqqqqqq"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "7336234ee9983902440f6bc35b348352013becd88938d2af\ - ec44311caf8356b3", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "57b5f7e766d5be68a6bfe1768e3c2b7f1228b3e4b3134956\ - dd73a59b954c66f4", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b""; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "41b037d1734a5f8df225dd8c7de38f851efdb45c372887be\ - 655212d07251b921b052b62eaed99b46f72f2ef4cc96bfaf254ebb\ - bec091e1a3b9e4fb5e5b619d2e0c5414800a1d882b62bb5cd1778f\ - 098b8eb6cb399d5d9d18f5d5842cf5d13d7eb00a7cff859b605da6\ - 78b318bd0e65ebff70bec88c753b159a805d2c89c55961", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abc"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "7f1dddd13c08b543f2e2037b14cefb255b44c83cc397c178\ - 6d975653e36a6b11bdd7732d8b38adb4a0edc26a0cef4bb4521713\ - 5456e58fbca1703cd6032cb1347ee720b87972d63fbf232587043e\ - d2901bce7f22610c0419751c065922b488431851041310ad659e4b\ - 23520e1772ab29dcdeb2002222a363f0c2b1c972b3efe1", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abcdef0123456789"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "3f721f208e6199fe903545abc26c837ce59ac6fa45733f1b\ - aaf0222f8b7acb0424814fcb5eecf6c1d38f06e9d0a6ccfbf85ae6\ - 12ab8735dfdf9ce84c372a77c8f9e1c1e952c3a61b7567dd069301\ - 6af51d2745822663d0c2367e3f4f0bed827feecc2aaf98c949b5ed\ - 0d35c3f1023d64ad1407924288d366ea159f46287e61ac", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ + qqqqqqqqqqqqqqqqqqqqqqqqq", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "7336234ee9983902440f6bc35b348352013becd88938d2af + ec44311caf8356b3" + ), + } + .run::>(); + + TestCase { + msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "57b5f7e766d5be68a6bfe1768e3c2b7f1228b3e4b3134956 + dd73a59b954c66f4" + ), + } + .run::>(); + + TestCase { + msg: b"", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "41b037d1734a5f8df225dd8c7de38f851efdb45c372887be + 655212d07251b921b052b62eaed99b46f72f2ef4cc96bfaf254ebb + bec091e1a3b9e4fb5e5b619d2e0c5414800a1d882b62bb5cd1778f + 098b8eb6cb399d5d9d18f5d5842cf5d13d7eb00a7cff859b605da6 + 78b318bd0e65ebff70bec88c753b159a805d2c89c55961" + ), + } + .run::>(); + + TestCase { + msg: b"abc", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "7f1dddd13c08b543f2e2037b14cefb255b44c83cc397c178 + 6d975653e36a6b11bdd7732d8b38adb4a0edc26a0cef4bb4521713 + 5456e58fbca1703cd6032cb1347ee720b87972d63fbf232587043e + d2901bce7f22610c0419751c065922b488431851041310ad659e4b + 23520e1772ab29dcdeb2002222a363f0c2b1c972b3efe1" + ), + } + .run::>(); + + TestCase { + msg: b"abcdef0123456789", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "3f721f208e6199fe903545abc26c837ce59ac6fa45733f1b + aaf0222f8b7acb0424814fcb5eecf6c1d38f06e9d0a6ccfbf85ae6 + 12ab8735dfdf9ce84c372a77c8f9e1c1e952c3a61b7567dd069301 + 6af51d2745822663d0c2367e3f4f0bed827feecc2aaf98c949b5ed + 0d35c3f1023d64ad1407924288d366ea159f46287e61ac" + ), + } + .run::>(); + + TestCase { + msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ - qqqqqqqqqqqqqqqqqqqqqqqqq"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "b799b045a58c8d2b4334cf54b78260b45eec544f9f2fb5bd\ - 12fb603eaee70db7317bf807c406e26373922b7b8920fa29142703\ - dd52bdf280084fb7ef69da78afdf80b3586395b433dc66cde048a2\ - 58e476a561e9deba7060af40adf30c64249ca7ddea79806ee5beb9\ - a1422949471d267b21bc88e688e4014087a0b592b695ed", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); + qqqqqqqqqqqqqqqqqqqqqqqqq", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "b799b045a58c8d2b4334cf54b78260b45eec544f9f2fb5bd + 12fb603eaee70db7317bf807c406e26373922b7b8920fa29142703 + dd52bdf280084fb7ef69da78afdf80b3586395b433dc66cde048a2 + 58e476a561e9deba7060af40adf30c64249ca7ddea79806ee5beb9 + a1422949471d267b21bc88e688e4014087a0b592b695ed" + ), + } + .run::>(); - let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + TestCase { + msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ @@ -479,161 +479,151 @@ fn expand_message_xmd_works_for_draft12_testvectors_sha512() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "05b0bfef265dcee87654372777b7c44177e2ae4c13a27f10\ - 3340d9cd11c86cb2426ffcad5bd964080c2aee97f03be1ca18e30a\ - 1f14e27bc11ebbd650f305269cc9fb1db08bf90bfc79b42a952b46\ - daf810359e7bc36452684784a64952c343c52e5124cd1f71d474d5\ - 197fefc571a92929c9084ffe1112cf5eea5192ebff330b", - ) - .unwrap(); - assert_eq!( - ExpandMsgXmd::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "05b0bfef265dcee87654372777b7c44177e2ae4c13a27f10 + 3340d9cd11c86cb2426ffcad5bd964080c2aee97f03be1ca18e30a + 1f14e27bc11ebbd650f305269cc9fb1db08bf90bfc79b42a952b46 + daf810359e7bc36452684784a64952c343c52e5124cd1f71d474d5 + 197fefc571a92929c9084ffe1112cf5eea5192ebff330b" + ), + } + .run::>(); } -/// From +/// From #[test] -fn expand_message_xof_works_for_draft12_testvectors_shake128() { +fn expand_msg_xof_works_for_draft16_testvectors_shake128() { let dst = b"QUUX-V01-CS02-with-expander-SHAKE128"; - let msg = b""; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "86518c9cd86581486e9485aa74ab35ba150d1c75c88e26b7\ - 043e44e2acd735a2", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abc"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "8696af52a4d862417c0763556073f47bc9b9ba43c99b5053\ - 05cb1ec04a9ab468", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abcdef0123456789"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "912c58deac4821c3509dbefa094df54b34b8f5d01a191d1d\ - 3108a2c89077acca", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ + TestCase { + msg: b"", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "86518c9cd86581486e9485aa74ab35ba150d1c75c88e26b7 + 043e44e2acd735a2" + ), + } + .run::>(); + + TestCase { + msg: b"abc", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "8696af52a4d862417c0763556073f47bc9b9ba43c99b5053 + 05cb1ec04a9ab468" + ), + } + .run::>(); + + TestCase { + msg: b"abcdef0123456789", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "912c58deac4821c3509dbefa094df54b34b8f5d01a191d1d + 3108a2c89077acca" + ), + } + .run::>(); + + TestCase { + msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ - qqqqqqqqqqqqqqqqqqqqqqqqq"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "1adbcc448aef2a0cebc71dac9f756b22e51839d348e031e6\ - 3b33ebb50faeaf3f", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "df3447cc5f3e9a77da10f819218ddf31342c310778e0e4ef\ - 72bbaecee786a4fe", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b""; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "7314ff1a155a2fb99a0171dc71b89ab6e3b2b7d59e38e644\ - 19b8b6294d03ffee42491f11370261f436220ef787f8f76f5b26bd\ - cd850071920ce023f3ac46847744f4612b8714db8f5db83205b2e6\ - 25d95afd7d7b4d3094d3bdde815f52850bb41ead9822e08f22cf41\ - d615a303b0d9dde73263c049a7b9898208003a739a2e57", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abc"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "c952f0c8e529ca8824acc6a4cab0e782fc3648c563ddb00d\ - a7399f2ae35654f4860ec671db2356ba7baa55a34a9d7f79197b60\ - ddae6e64768a37d699a78323496db3878c8d64d909d0f8a7de4927\ - dcab0d3dbbc26cb20a49eceb0530b431cdf47bc8c0fa3e0d88f53b\ - 318b6739fbed7d7634974f1b5c386d6230c76260d5337a", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abcdef0123456789"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "19b65ee7afec6ac06a144f2d6134f08eeec185f1a890fe34\ - e68f0e377b7d0312883c048d9b8a1d6ecc3b541cb4987c26f45e0c\ - 82691ea299b5e6889bbfe589153016d8131717ba26f07c3c14ffbe\ - f1f3eff9752e5b6183f43871a78219a75e7000fbac6a7072e2b83c\ - 790a3a5aecd9d14be79f9fd4fb180960a3772e08680495", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ + qqqqqqqqqqqqqqqqqqqqqqqqq", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "1adbcc448aef2a0cebc71dac9f756b22e51839d348e031e6 + 3b33ebb50faeaf3f" + ), + } + .run::>(); + + TestCase { + msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "df3447cc5f3e9a77da10f819218ddf31342c310778e0e4ef + 72bbaecee786a4fe" + ), + } + .run::>(); + + TestCase { + msg: b"", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "7314ff1a155a2fb99a0171dc71b89ab6e3b2b7d59e38e644 + 19b8b6294d03ffee42491f11370261f436220ef787f8f76f5b26bd + cd850071920ce023f3ac46847744f4612b8714db8f5db83205b2e6 + 25d95afd7d7b4d3094d3bdde815f52850bb41ead9822e08f22cf41 + d615a303b0d9dde73263c049a7b9898208003a739a2e57" + ), + } + .run::>(); + + TestCase { + msg: b"abc", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "c952f0c8e529ca8824acc6a4cab0e782fc3648c563ddb00d + a7399f2ae35654f4860ec671db2356ba7baa55a34a9d7f79197b60 + ddae6e64768a37d699a78323496db3878c8d64d909d0f8a7de4927 + dcab0d3dbbc26cb20a49eceb0530b431cdf47bc8c0fa3e0d88f53b + 318b6739fbed7d7634974f1b5c386d6230c76260d5337a" + ), + } + .run::>(); + + TestCase { + msg: b"abcdef0123456789", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "19b65ee7afec6ac06a144f2d6134f08eeec185f1a890fe34 + e68f0e377b7d0312883c048d9b8a1d6ecc3b541cb4987c26f45e0c + 82691ea299b5e6889bbfe589153016d8131717ba26f07c3c14ffbe + f1f3eff9752e5b6183f43871a78219a75e7000fbac6a7072e2b83c + 790a3a5aecd9d14be79f9fd4fb180960a3772e08680495" + ), + } + .run::>(); + + TestCase { + msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ - qqqqqqqqqqqqqqqqqqqqqqqqq"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "ca1b56861482b16eae0f4a26212112362fcc2d76dcc80c93\ - c4182ed66c5113fe41733ed68be2942a3487394317f3379856f482\ - 2a611735e50528a60e7ade8ec8c71670fec6661e2c59a09ed36386\ - 513221688b35dc47e3c3111ee8c67ff49579089d661caa29db1ef1\ - 0eb6eace575bf3dc9806e7c4016bd50f3c0e2a6481ee6d", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); + qqqqqqqqqqqqqqqqqqqqqqqqq", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "ca1b56861482b16eae0f4a26212112362fcc2d76dcc80c93 + c4182ed66c5113fe41733ed68be2942a3487394317f3379856f482 + 2a611735e50528a60e7ade8ec8c71670fec6661e2c59a09ed36386 + 513221688b35dc47e3c3111ee8c67ff49579089d661caa29db1ef1 + 0eb6eace575bf3dc9806e7c4016bd50f3c0e2a6481ee6d" + ), + } + .run::>(); - let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + TestCase { + msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ @@ -642,165 +632,155 @@ fn expand_message_xof_works_for_draft12_testvectors_shake128() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "9d763a5ce58f65c91531b4100c7266d479a5d9777ba76169\ - 3d052acd37d149e7ac91c796a10b919cd74a591a1e38719fb91b72\ - 03e2af31eac3bff7ead2c195af7d88b8bc0a8adf3d1e90ab9bed6d\ - dc2b7f655dd86c730bdeaea884e73741097142c92f0e3fc1811b69\ - 9ba593c7fbd81da288a29d423df831652e3a01a9374999", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "9d763a5ce58f65c91531b4100c7266d479a5d9777ba76169 + 3d052acd37d149e7ac91c796a10b919cd74a591a1e38719fb91b72 + 03e2af31eac3bff7ead2c195af7d88b8bc0a8adf3d1e90ab9bed6d + dc2b7f655dd86c730bdeaea884e73741097142c92f0e3fc1811b69 + 9ba593c7fbd81da288a29d423df831652e3a01a9374999" + ), + } + .run::>(); } -/// From +/// From #[test] -fn expand_message_xof_works_for_draft12_testvectors_shake128_long_dst() { +fn expand_msg_xof_works_for_draft16_testvectors_shake128_long_dst() { let dst = b"QUUX-V01-CS02-with-expander-SHAKE128-long-DST-11111111\ 111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111111111111111111\ 111111111111111111111111111111111111111111111111111111\ 1111111111111111111111111111111111111111"; - let msg = b""; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "827c6216330a122352312bccc0c8d6e7a146c5257a776dbd\ - 9ad9d75cd880fc53", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abc"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "690c8d82c7213b4282c6cb41c00e31ea1d3e2005f93ad19b\ - bf6da40f15790c5c", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abcdef0123456789"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "979e3a15064afbbcf99f62cc09fa9c85028afcf3f825eb07\ - 11894dcfc2f57057", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ + TestCase { + msg: b"", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "827c6216330a122352312bccc0c8d6e7a146c5257a776dbd + 9ad9d75cd880fc53" + ), + } + .run::>(); + + TestCase { + msg: b"abc", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "690c8d82c7213b4282c6cb41c00e31ea1d3e2005f93ad19b + bf6da40f15790c5c" + ), + } + .run::>(); + + TestCase { + msg: b"abcdef0123456789", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "979e3a15064afbbcf99f62cc09fa9c85028afcf3f825eb07 + 11894dcfc2f57057" + ), + } + .run::>(); + + TestCase { + msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ - qqqqqqqqqqqqqqqqqqqqqqqqq"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "c5a9220962d9edc212c063f4f65b609755a1ed96e62f9db5\ - d1fd6adb5a8dc52b", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "f7b96a5901af5d78ce1d071d9c383cac66a1dfadb508300e\ - c6aeaea0d62d5d62", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b""; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "3890dbab00a2830be398524b71c2713bbef5f4884ac2e6f0\ - 70b092effdb19208c7df943dc5dcbaee3094a78c267ef276632ee2\ - c8ea0c05363c94b6348500fae4208345dd3475fe0c834c2beac7fa\ - 7bc181692fb728c0a53d809fc8111495222ce0f38468b11becb15b\ - 32060218e285c57a60162c2c8bb5b6bded13973cd41819", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abc"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "41b7ffa7a301b5c1441495ebb9774e2a53dbbf4e54b9a1af\ - 6a20fd41eafd69ef7b9418599c5545b1ee422f363642b01d4a5344\ - 9313f68da3e49dddb9cd25b97465170537d45dcbdf92391b5bdff3\ - 44db4bd06311a05bca7dcd360b6caec849c299133e5c9194f4e15e\ - 3e23cfaab4003fab776f6ac0bfae9144c6e2e1c62e7d57", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abcdef0123456789"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "55317e4a21318472cd2290c3082957e1242241d9e0d04f47\ - 026f03401643131401071f01aa03038b2783e795bdfa8a3541c194\ - ad5de7cb9c225133e24af6c86e748deb52e560569bd54ef4dac034\ - 65111a3a44b0ea490fb36777ff8ea9f1a8a3e8e0de3cf0880b4b2f\ - 8dd37d3a85a8b82375aee4fa0e909f9763319b55778e71", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ + qqqqqqqqqqqqqqqqqqqqqqqqq", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "c5a9220962d9edc212c063f4f65b609755a1ed96e62f9db5 + d1fd6adb5a8dc52b" + ), + } + .run::>(); + + TestCase { + msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "f7b96a5901af5d78ce1d071d9c383cac66a1dfadb508300e + c6aeaea0d62d5d62" + ), + } + .run::>(); + + TestCase { + msg: b"", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "3890dbab00a2830be398524b71c2713bbef5f4884ac2e6f0 + 70b092effdb19208c7df943dc5dcbaee3094a78c267ef276632ee2 + c8ea0c05363c94b6348500fae4208345dd3475fe0c834c2beac7fa + 7bc181692fb728c0a53d809fc8111495222ce0f38468b11becb15b + 32060218e285c57a60162c2c8bb5b6bded13973cd41819" + ), + } + .run::>(); + + TestCase { + msg: b"abc", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "41b7ffa7a301b5c1441495ebb9774e2a53dbbf4e54b9a1af + 6a20fd41eafd69ef7b9418599c5545b1ee422f363642b01d4a5344 + 9313f68da3e49dddb9cd25b97465170537d45dcbdf92391b5bdff3 + 44db4bd06311a05bca7dcd360b6caec849c299133e5c9194f4e15e + 3e23cfaab4003fab776f6ac0bfae9144c6e2e1c62e7d57" + ), + } + .run::>(); + + TestCase { + msg: b"abcdef0123456789", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "55317e4a21318472cd2290c3082957e1242241d9e0d04f47 + 026f03401643131401071f01aa03038b2783e795bdfa8a3541c194 + ad5de7cb9c225133e24af6c86e748deb52e560569bd54ef4dac034 + 65111a3a44b0ea490fb36777ff8ea9f1a8a3e8e0de3cf0880b4b2f + 8dd37d3a85a8b82375aee4fa0e909f9763319b55778e71" + ), + } + .run::>(); + + TestCase { + msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ - qqqqqqqqqqqqqqqqqqqqqqqqq"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "19fdd2639f082e31c77717ac9bb032a22ff0958382b2dbb3\ - 9020cdc78f0da43305414806abf9a561cb2d0067eb2f7bc544482f\ - 75623438ed4b4e39dd9e6e2909dd858bd8f1d57cd0fce2d3150d90\ - aa67b4498bdf2df98c0100dd1a173436ba5d0df6be1defb0b2ce55\ - ccd2f4fc05eb7cb2c019c35d5398b85adc676da4238bc7", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); + qqqqqqqqqqqqqqqqqqqqqqqqq", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "19fdd2639f082e31c77717ac9bb032a22ff0958382b2dbb3 + 9020cdc78f0da43305414806abf9a561cb2d0067eb2f7bc544482f + 75623438ed4b4e39dd9e6e2909dd858bd8f1d57cd0fce2d3150d90 + aa67b4498bdf2df98c0100dd1a173436ba5d0df6be1defb0b2ce55 + ccd2f4fc05eb7cb2c019c35d5398b85adc676da4238bc7" + ), + } + .run::>(); - let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + TestCase { + msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ @@ -809,161 +789,151 @@ fn expand_message_xof_works_for_draft12_testvectors_shake128_long_dst() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "945373f0b3431a103333ba6a0a34f1efab2702efde41754c\ - 4cb1d5216d5b0a92a67458d968562bde7fa6310a83f53dda138368\ - 0a276a283438d58ceebfa7ab7ba72499d4a3eddc860595f63c93b1\ - c5e823ea41fc490d938398a26db28f61857698553e93f0574eb8c5\ - 017bfed6249491f9976aaa8d23d9485339cc85ca329308", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "945373f0b3431a103333ba6a0a34f1efab2702efde41754c + 4cb1d5216d5b0a92a67458d968562bde7fa6310a83f53dda138368 + 0a276a283438d58ceebfa7ab7ba72499d4a3eddc860595f63c93b1 + c5e823ea41fc490d938398a26db28f61857698553e93f0574eb8c5 + 017bfed6249491f9976aaa8d23d9485339cc85ca329308" + ), + } + .run::>(); } -/// From +/// From #[test] -fn expand_message_xof_works_for_draft12_testvectors_shake256() { +fn expand_msg_xof_works_for_draft16_testvectors_shake256() { let dst = b"QUUX-V01-CS02-with-expander-SHAKE256"; - let msg = b""; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "2ffc05c48ed32b95d72e807f6eab9f7530dd1c2f013914c8\ - fed38c5ccc15ad76", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abc"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "b39e493867e2767216792abce1f2676c197c0692aed06156\ - 0ead251821808e07", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abcdef0123456789"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "245389cf44a13f0e70af8665fe5337ec2dcd138890bb7901\ - c4ad9cfceb054b65", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ + TestCase { + msg: b"", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "2ffc05c48ed32b95d72e807f6eab9f7530dd1c2f013914c8 + fed38c5ccc15ad76" + ), + } + .run::>(); + + TestCase { + msg: b"abc", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "b39e493867e2767216792abce1f2676c197c0692aed06156 + 0ead251821808e07" + ), + } + .run::>(); + + TestCase { + msg: b"abcdef0123456789", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "245389cf44a13f0e70af8665fe5337ec2dcd138890bb7901 + c4ad9cfceb054b65" + ), + } + .run::>(); + + TestCase { + msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ - qqqqqqqqqqqqqqqqqqqqqqqqq"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "719b3911821e6428a5ed9b8e600f2866bcf23c8f0515e52d\ - 6c6c019a03f16f0e", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let len_in_bytes = 0x20; - let uniform_bytes = hex::decode( - "9181ead5220b1963f1b5951f35547a5ea86a820562287d6c\ - a4723633d17ccbbc", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b""; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "7a1361d2d7d82d79e035b8880c5a3c86c5afa719478c007d\ - 96e6c88737a3f631dd74a2c88df79a4cb5e5d9f7504957c70d669e\ - c6bfedc31e01e2bacc4ff3fdf9b6a00b17cc18d9d72ace7d6b81c2\ - e481b4f73f34f9a7505dccbe8f5485f3d20c5409b0310093d5d649\ - 2dea4e18aa6979c23c8ea5de01582e9689612afbb353df", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abc"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "a54303e6b172909783353ab05ef08dd435a558c3197db0c1\ - 32134649708e0b9b4e34fb99b92a9e9e28fc1f1d8860d85897a8e0\ - 21e6382f3eea10577f968ff6df6c45fe624ce65ca25932f679a42a\ - 404bc3681efe03fcd45ef73bb3a8f79ba784f80f55ea8a3c367408\ - f30381299617f50c8cf8fbb21d0f1e1d70b0131a7b6fbe", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"abcdef0123456789"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "e42e4d9538a189316e3154b821c1bafb390f78b2f010ea40\ - 4e6ac063deb8c0852fcd412e098e231e43427bd2be1330bb47b403\ - 9ad57b30ae1fc94e34993b162ff4d695e42d59d9777ea18d3848d9\ - d336c25d2acb93adcad009bcfb9cde12286df267ada283063de0bb\ - 1505565b2eb6c90e31c48798ecdc71a71756a9110ff373", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); - - let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ + qqqqqqqqqqqqqqqqqqqqqqqqq", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "719b3911821e6428a5ed9b8e600f2866bcf23c8f0515e52d + 6c6c019a03f16f0e" + ), + } + .run::>(); + + TestCase { + msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + dst, + len_in_bytes: 0x20, + uniform_bytes: &hex!( + "9181ead5220b1963f1b5951f35547a5ea86a820562287d6c + a4723633d17ccbbc" + ), + } + .run::>(); + + TestCase { + msg: b"", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "7a1361d2d7d82d79e035b8880c5a3c86c5afa719478c007d + 96e6c88737a3f631dd74a2c88df79a4cb5e5d9f7504957c70d669e + c6bfedc31e01e2bacc4ff3fdf9b6a00b17cc18d9d72ace7d6b81c2 + e481b4f73f34f9a7505dccbe8f5485f3d20c5409b0310093d5d649 + 2dea4e18aa6979c23c8ea5de01582e9689612afbb353df" + ), + } + .run::>(); + + TestCase { + msg: b"abc", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "a54303e6b172909783353ab05ef08dd435a558c3197db0c1 + 32134649708e0b9b4e34fb99b92a9e9e28fc1f1d8860d85897a8e0 + 21e6382f3eea10577f968ff6df6c45fe624ce65ca25932f679a42a + 404bc3681efe03fcd45ef73bb3a8f79ba784f80f55ea8a3c367408 + f30381299617f50c8cf8fbb21d0f1e1d70b0131a7b6fbe" + ), + } + .run::>(); + + TestCase { + msg: b"abcdef0123456789", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "e42e4d9538a189316e3154b821c1bafb390f78b2f010ea40 + 4e6ac063deb8c0852fcd412e098e231e43427bd2be1330bb47b403 + 9ad57b30ae1fc94e34993b162ff4d695e42d59d9777ea18d3848d9 + d336c25d2acb93adcad009bcfb9cde12286df267ada283063de0bb + 1505565b2eb6c90e31c48798ecdc71a71756a9110ff373" + ), + } + .run::>(); + + TestCase { + msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ - qqqqqqqqqqqqqqqqqqqqqqqqq"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "4ac054dda0a38a65d0ecf7afd3c2812300027c8789655e47\ - aecf1ecc1a2426b17444c7482c99e5907afd9c25b991990490bb9c\ - 686f43e79b4471a23a703d4b02f23c669737a886a7ec28bddb92c3\ - a98de63ebf878aa363a501a60055c048bea11840c4717beae7eee2\ - 8c3cfa42857b3d130188571943a7bd747de831bd6444e0", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); + qqqqqqqqqqqqqqqqqqqqqqqqq", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "4ac054dda0a38a65d0ecf7afd3c2812300027c8789655e47 + aecf1ecc1a2426b17444c7482c99e5907afd9c25b991990490bb9c + 686f43e79b4471a23a703d4b02f23c669737a886a7ec28bddb92c3 + a98de63ebf878aa363a501a60055c048bea11840c4717beae7eee2 + 8c3cfa42857b3d130188571943a7bd747de831bd6444e0" + ), + } + .run::>(); - let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ + TestCase { + msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ @@ -972,18 +942,16 @@ fn expand_message_xof_works_for_draft12_testvectors_shake256() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let len_in_bytes = 0x80; - let uniform_bytes = hex::decode( - "09afc76d51c2cccbc129c2315df66c2be7295a231203b8ab\ - 2dd7f95c2772c68e500bc72e20c602abc9964663b7a03a389be128\ - c56971ce81001a0b875e7fd17822db9d69792ddf6a23a151bf4700\ - 79c518279aef3e75611f8f828994a9988f4a8a256ddb8bae161e65\ - 8d5a2a09bcfe839c6396dc06ee5c8ff3c22d3b1f9deb7e", - ) - .unwrap(); - assert_eq!( - ExpandMsgXof::::init_expand(msg, dst, len_in_bytes).into_vec(), - uniform_bytes - ); + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + dst, + len_in_bytes: 0x80, + uniform_bytes: &hex!( + "09afc76d51c2cccbc129c2315df66c2be7295a231203b8ab + 2dd7f95c2772c68e500bc72e20c602abc9964663b7a03a389be128 + c56971ce81001a0b875e7fd17822db9d69792ddf6a23a151bf4700 + 79c518279aef3e75611f8f828994a9988f4a8a256ddb8bae161e65 + 8d5a2a09bcfe839c6396dc06ee5c8ff3c22d3b1f9deb7e" + ), + } + .run::>(); } diff --git a/tests/hash_to_curve_g1.rs b/tests/hash_to_curve_g1.rs index 6c770e40..6f8857a3 100644 --- a/tests/hash_to_curve_g1.rs +++ b/tests/hash_to_curve_g1.rs @@ -1,56 +1,70 @@ -use bls12_381::G1Projective; +use bls12_381::{ + hash_to_curve::{ExpandMsgXmd, HashToCurve}, + G1Affine, G1Projective, +}; +use hex_literal::hex; +use sha2::Sha256; -// test vectors from the draft 10 RFC -#[test] -fn test_encode_to_curve_10() { - use bls12_381::{ - hash_to_curve::{ExpandMsgXmd, HashToCurve}, - G1Affine, - }; - use std::string::{String, ToString}; +struct TestCase { + msg: &'static [u8], + dst: &'static [u8], + expected: &'static [u8], +} - struct TestCase { - msg: &'static [u8], - expected: [&'static str; 2], - } - impl TestCase { - fn expected(&self) -> String { - self.expected[0].to_string() + self.expected[1] +impl TestCase { + pub fn check_output(&self, output: &[u8]) { + if output != self.expected { + panic!( + "Test vector result mismatch.\n\ + Message: {:x?}\n\ + DST: {:x?}\n\ + Expected: {:x?}\n\ + Found: {:x?}", + self.msg, self.dst, self.expected, output + ) } } +} - const DOMAIN: &[u8] = b"QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_NU_"; +// From +#[test] +fn encode_to_curve_works_for_draft16_testvectors_g1_sha256_nu() { + let dst = b"QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_NU_"; let cases = vec![ TestCase { msg: b"", - expected: [ - "184bb665c37ff561a89ec2122dd343f20e0f4cbcaec84e3c3052ea81d1834e192c426074b02ed3dca4e7676ce4ce48ba", - "04407b8d35af4dacc809927071fc0405218f1401a6d15af775810e4e460064bcc9468beeba82fdc751be70476c888bf3", - ], + dst, + expected: &hex!( + "184bb665c37ff561a89ec2122dd343f20e0f4cbcaec84e3c3052ea81d1834e192c426074b02ed3dca4e7676ce4ce48ba + 04407b8d35af4dacc809927071fc0405218f1401a6d15af775810e4e460064bcc9468beeba82fdc751be70476c888bf3" + ), }, TestCase { msg: b"abc", - expected: [ - "009769f3ab59bfd551d53a5f846b9984c59b97d6842b20a2c565baa167945e3d026a3755b6345df8ec7e6acb6868ae6d", - "1532c00cf61aa3d0ce3e5aa20c3b531a2abd2c770a790a2613818303c6b830ffc0ecf6c357af3317b9575c567f11cd2c", - ], + dst, + expected: &hex!( + "009769f3ab59bfd551d53a5f846b9984c59b97d6842b20a2c565baa167945e3d026a3755b6345df8ec7e6acb6868ae6d + 1532c00cf61aa3d0ce3e5aa20c3b531a2abd2c770a790a2613818303c6b830ffc0ecf6c357af3317b9575c567f11cd2c" + ), }, TestCase { msg: b"abcdef0123456789", - expected: [ - "1974dbb8e6b5d20b84df7e625e2fbfecb2cdb5f77d5eae5fb2955e5ce7313cae8364bc2fff520a6c25619739c6bdcb6a", - "15f9897e11c6441eaa676de141c8d83c37aab8667173cbe1dfd6de74d11861b961dccebcd9d289ac633455dfcc7013a3", - ] + dst, + expected: &hex!( + "1974dbb8e6b5d20b84df7e625e2fbfecb2cdb5f77d5eae5fb2955e5ce7313cae8364bc2fff520a6c25619739c6bdcb6a + 15f9897e11c6441eaa676de141c8d83c37aab8667173cbe1dfd6de74d11861b961dccebcd9d289ac633455dfcc7013a3" + ), }, TestCase { msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqq", - expected: [ - "0a7a047c4a8397b3446450642c2ac64d7239b61872c9ae7a59707a8f4f950f101e766afe58223b3bff3a19a7f754027c", - "1383aebba1e4327ccff7cf9912bda0dbc77de048b71ef8c8a81111d71dc33c5e3aa6edee9cf6f5fe525d50cc50b77cc9", - ] + dst, + expected: &hex!( + "0a7a047c4a8397b3446450642c2ac64d7239b61872c9ae7a59707a8f4f950f101e766afe58223b3bff3a19a7f754027c + 1383aebba1e4327ccff7cf9912bda0dbc77de048b71ef8c8a81111d71dc33c5e3aa6edee9cf6f5fe525d50cc50b77cc9" + ), }, TestCase { msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ @@ -63,75 +77,63 @@ fn test_encode_to_curve_10() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - expected: [ - "0e7a16a975904f131682edbb03d9560d3e48214c9986bd50417a77108d13dc957500edf96462a3d01e62dc6cd468ef11", - "0ae89e677711d05c30a48d6d75e76ca9fb70fe06c6dd6ff988683d89ccde29ac7d46c53bb97a59b1901abf1db66052db", - ] - } + dst, + expected: &hex!( + "0e7a16a975904f131682edbb03d9560d3e48214c9986bd50417a77108d13dc957500edf96462a3d01e62dc6cd468ef11 + 0ae89e677711d05c30a48d6d75e76ca9fb70fe06c6dd6ff988683d89ccde29ac7d46c53bb97a59b1901abf1db66052db" + ), + }, ]; for case in cases { - let g = >>::encode_to_curve( - &case.msg, DOMAIN, + let g = >>::encode_to_curve( + case.msg, case.dst, ); let aff = G1Affine::from(g); let g_uncompressed = aff.to_uncompressed(); - - assert_eq!(case.expected(), hex::encode(&g_uncompressed[..])); + case.check_output(&g_uncompressed); } } -// test vectors from the draft 10 RFC +// From #[test] -fn test_hash_to_curve_10() { - use bls12_381::{ - hash_to_curve::{ExpandMsgXmd, HashToCurve}, - G1Affine, - }; - use std::string::{String, ToString}; - - struct TestCase { - msg: &'static [u8], - expected: [&'static str; 2], - } - impl TestCase { - fn expected(&self) -> String { - self.expected[0].to_string() + self.expected[1] - } - } - - const DOMAIN: &[u8] = b"QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_"; +fn hash_to_curve_works_for_draft16_testvectors_g1_sha256_ro() { + let dst = b"QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_"; let cases = vec![ TestCase { msg: b"", - expected: [ - "052926add2207b76ca4fa57a8734416c8dc95e24501772c814278700eed6d1e4e8cf62d9c09db0fac349612b759e79a1", - "08ba738453bfed09cb546dbb0783dbb3a5f1f566ed67bb6be0e8c67e2e81a4cc68ee29813bb7994998f3eae0c9c6a265", - ], + dst, + expected: &hex!( + "052926add2207b76ca4fa57a8734416c8dc95e24501772c814278700eed6d1e4e8cf62d9c09db0fac349612b759e79a1 + 08ba738453bfed09cb546dbb0783dbb3a5f1f566ed67bb6be0e8c67e2e81a4cc68ee29813bb7994998f3eae0c9c6a265" + ), }, TestCase { msg: b"abc", - expected: [ - "03567bc5ef9c690c2ab2ecdf6a96ef1c139cc0b2f284dca0a9a7943388a49a3aee664ba5379a7655d3c68900be2f6903", - "0b9c15f3fe6e5cf4211f346271d7b01c8f3b28be689c8429c85b67af215533311f0b8dfaaa154fa6b88176c229f2885d" - ], + dst, + expected: &hex!( + "03567bc5ef9c690c2ab2ecdf6a96ef1c139cc0b2f284dca0a9a7943388a49a3aee664ba5379a7655d3c68900be2f6903 + 0b9c15f3fe6e5cf4211f346271d7b01c8f3b28be689c8429c85b67af215533311f0b8dfaaa154fa6b88176c229f2885d" + ), }, TestCase { msg: b"abcdef0123456789", - expected: [ - "11e0b079dea29a68f0383ee94fed1b940995272407e3bb916bbf268c263ddd57a6a27200a784cbc248e84f357ce82d98", - "03a87ae2caf14e8ee52e51fa2ed8eefe80f02457004ba4d486d6aa1f517c0889501dc7413753f9599b099ebcbbd2d709" - ] + dst, + expected: &hex!( + "11e0b079dea29a68f0383ee94fed1b940995272407e3bb916bbf268c263ddd57a6a27200a784cbc248e84f357ce82d98 + 03a87ae2caf14e8ee52e51fa2ed8eefe80f02457004ba4d486d6aa1f517c0889501dc7413753f9599b099ebcbbd2d709" + ), }, TestCase { msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqq", - expected: [ - "15f68eaa693b95ccb85215dc65fa81038d69629f70aeee0d0f677cf22285e7bf58d7cb86eefe8f2e9bc3f8cb84fac488", - "1807a1d50c29f430b8cafc4f8638dfeeadf51211e1602a5f184443076715f91bb90a48ba1e370edce6ae1062f5e6dd38" - ] + dst, + expected: &hex!( + "15f68eaa693b95ccb85215dc65fa81038d69629f70aeee0d0f677cf22285e7bf58d7cb86eefe8f2e9bc3f8cb84fac488 + 1807a1d50c29f430b8cafc4f8638dfeeadf51211e1602a5f184443076715f91bb90a48ba1e370edce6ae1062f5e6dd38" + ), }, TestCase { msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ @@ -144,19 +146,19 @@ fn test_hash_to_curve_10() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - expected: [ - "082aabae8b7dedb0e78aeb619ad3bfd9277a2f77ba7fad20ef6aabdc6c31d19ba5a6d12283553294c1825c4b3ca2dcfe", - "05b84ae5a942248eea39e1d91030458c40153f3b654ab7872d779ad1e942856a20c438e8d99bc8abfbf74729ce1f7ac8" - ] - } + dst, + expected: &hex!( + "082aabae8b7dedb0e78aeb619ad3bfd9277a2f77ba7fad20ef6aabdc6c31d19ba5a6d12283553294c1825c4b3ca2dcfe + 05b84ae5a942248eea39e1d91030458c40153f3b654ab7872d779ad1e942856a20c438e8d99bc8abfbf74729ce1f7ac8" + ), + }, ]; for case in cases { - let g = >>::hash_to_curve( - &case.msg, DOMAIN, - ); - let g_uncompressed = G1Affine::from(g).to_uncompressed(); - - assert_eq!(case.expected(), hex::encode(&g_uncompressed[..])); + let g = + >>::hash_to_curve(case.msg, case.dst); + let aff = G1Affine::from(g); + let g_uncompressed = aff.to_uncompressed(); + case.check_output(&g_uncompressed); } } diff --git a/tests/hash_to_curve_g2.rs b/tests/hash_to_curve_g2.rs index dfb03e51..da8b80cf 100644 --- a/tests/hash_to_curve_g2.rs +++ b/tests/hash_to_curve_g2.rs @@ -1,64 +1,78 @@ -use bls12_381::G2Projective; +use bls12_381::{ + hash_to_curve::{ExpandMsgXmd, HashToCurve}, + G2Affine, G2Projective, +}; +use hex_literal::hex; +use sha2::Sha256; -// test vectors from the draft 10 RFC -#[test] -fn test_encode_to_curve_10() { - use bls12_381::{ - hash_to_curve::{ExpandMsgXmd, HashToCurve}, - G2Affine, - }; - use std::string::{String, ToString}; +struct TestCase { + msg: &'static [u8], + dst: &'static [u8], + expected: &'static [u8], +} - struct TestCase { - msg: &'static [u8], - expected: [&'static str; 4], - } - impl TestCase { - fn expected(&self) -> String { - self.expected[0].to_string() + self.expected[1] + self.expected[2] + self.expected[3] +impl TestCase { + pub fn check_output(&self, output: &[u8]) { + if output != self.expected { + panic!( + "Test vector result mismatch.\n\ + Message: {:x?}\n\ + DST: {:x?}\n\ + Expected: {:x?}\n\ + Found: {:x?}", + self.msg, self.dst, self.expected, output + ) } } +} - const DOMAIN: &[u8] = b"QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_NU_"; +// From +#[test] +fn encode_to_curve_works_for_draft16_testvectors_g2_sha256_nu() { + let dst = b"QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_NU_"; let cases = vec![ TestCase { msg: b"", - expected: [ - "126b855e9e69b1f691f816e48ac6977664d24d99f8724868a184186469ddfd4617367e94527d4b74fc86413483afb35b", - "00e7f4568a82b4b7dc1f14c6aaa055edf51502319c723c4dc2688c7fe5944c213f510328082396515734b6612c4e7bb7", - "1498aadcf7ae2b345243e281ae076df6de84455d766ab6fcdaad71fab60abb2e8b980a440043cd305db09d283c895e3d", - "0caead0fd7b6176c01436833c79d305c78be307da5f6af6c133c47311def6ff1e0babf57a0fb5539fce7ee12407b0a42", - ], + dst, + expected: &hex!( + "126b855e9e69b1f691f816e48ac6977664d24d99f8724868a184186469ddfd4617367e94527d4b74fc86413483afb35b + 00e7f4568a82b4b7dc1f14c6aaa055edf51502319c723c4dc2688c7fe5944c213f510328082396515734b6612c4e7bb7 + 1498aadcf7ae2b345243e281ae076df6de84455d766ab6fcdaad71fab60abb2e8b980a440043cd305db09d283c895e3d + 0caead0fd7b6176c01436833c79d305c78be307da5f6af6c133c47311def6ff1e0babf57a0fb5539fce7ee12407b0a42" + ), }, TestCase { msg: b"abc", - expected: [ - "0296238ea82c6d4adb3c838ee3cb2346049c90b96d602d7bb1b469b905c9228be25c627bffee872def773d5b2a2eb57d", - "108ed59fd9fae381abfd1d6bce2fd2fa220990f0f837fa30e0f27914ed6e1454db0d1ee957b219f61da6ff8be0d6441f", - "153606c417e59fb331b7ae6bce4fbf7c5190c33ce9402b5ebe2b70e44fca614f3f1382a3625ed5493843d0b0a652fc3f", - "033f90f6057aadacae7963b0a0b379dd46750c1c94a6357c99b65f63b79e321ff50fe3053330911c56b6ceea08fee656", - ], + dst, + expected: &hex!( + "0296238ea82c6d4adb3c838ee3cb2346049c90b96d602d7bb1b469b905c9228be25c627bffee872def773d5b2a2eb57d + 108ed59fd9fae381abfd1d6bce2fd2fa220990f0f837fa30e0f27914ed6e1454db0d1ee957b219f61da6ff8be0d6441f + 153606c417e59fb331b7ae6bce4fbf7c5190c33ce9402b5ebe2b70e44fca614f3f1382a3625ed5493843d0b0a652fc3f + 033f90f6057aadacae7963b0a0b379dd46750c1c94a6357c99b65f63b79e321ff50fe3053330911c56b6ceea08fee656" + ), }, TestCase { msg: b"abcdef0123456789", - expected: [ - "0da75be60fb6aa0e9e3143e40c42796edf15685cafe0279afd2a67c3dff1c82341f17effd402e4f1af240ea90f4b659b", - "038af300ef34c7759a6caaa4e69363cafeed218a1f207e93b2c70d91a1263d375d6730bd6b6509dcac3ba5b567e85bf3", - "0492f4fed741b073e5a82580f7c663f9b79e036b70ab3e51162359cec4e77c78086fe879b65ca7a47d34374c8315ac5e", - "19b148cbdf163cf0894f29660d2e7bfb2b68e37d54cc83fd4e6e62c020eaa48709302ef8e746736c0e19342cc1ce3df4", - ] + dst, + expected: &hex!( + "0da75be60fb6aa0e9e3143e40c42796edf15685cafe0279afd2a67c3dff1c82341f17effd402e4f1af240ea90f4b659b + 038af300ef34c7759a6caaa4e69363cafeed218a1f207e93b2c70d91a1263d375d6730bd6b6509dcac3ba5b567e85bf3 + 0492f4fed741b073e5a82580f7c663f9b79e036b70ab3e51162359cec4e77c78086fe879b65ca7a47d34374c8315ac5e + 19b148cbdf163cf0894f29660d2e7bfb2b68e37d54cc83fd4e6e62c020eaa48709302ef8e746736c0e19342cc1ce3df4" + ), }, TestCase { msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqq", - expected: [ - "12c8c05c1d5fc7bfa847f4d7d81e294e66b9a78bc9953990c358945e1f042eedafce608b67fdd3ab0cb2e6e263b9b1ad", - "0c5ae723be00e6c3f0efe184fdc0702b64588fe77dda152ab13099a3bacd3876767fa7bbad6d6fd90b3642e902b208f9", - "11c624c56dbe154d759d021eec60fab3d8b852395a89de497e48504366feedd4662d023af447d66926a28076813dd646", - "04e77ddb3ede41b5ec4396b7421dd916efc68a358a0d7425bddd253547f2fb4830522358491827265dfc5bcc1928a569", - ] + dst, + expected: &hex!( + "12c8c05c1d5fc7bfa847f4d7d81e294e66b9a78bc9953990c358945e1f042eedafce608b67fdd3ab0cb2e6e263b9b1ad + 0c5ae723be00e6c3f0efe184fdc0702b64588fe77dda152ab13099a3bacd3876767fa7bbad6d6fd90b3642e902b208f9 + 11c624c56dbe154d759d021eec60fab3d8b852395a89de497e48504366feedd4662d023af447d66926a28076813dd646 + 04e77ddb3ede41b5ec4396b7421dd916efc68a358a0d7425bddd253547f2fb4830522358491827265dfc5bcc1928a569" + ), }, TestCase { msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ @@ -71,84 +85,73 @@ fn test_encode_to_curve_10() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - expected: [ - "1565c2f625032d232f13121d3cfb476f45275c303a037faa255f9da62000c2c864ea881e2bcddd111edc4a3c0da3e88d", - "0ea4e7c33d43e17cc516a72f76437c4bf81d8f4eac69ac355d3bf9b71b8138d55dc10fd458be115afa798b55dac34be1", - "0f8991d2a1ad662e7b6f58ab787947f1fa607fce12dde171bc17903b012091b657e15333e11701edcf5b63ba2a561247", - "043b6f5fe4e52c839148dc66f2b3751e69a0f6ebb3d056d6465d50d4108543ecd956e10fa1640dfd9bc0030cc2558d28", - ] - } + dst, + expected: &hex!( + "1565c2f625032d232f13121d3cfb476f45275c303a037faa255f9da62000c2c864ea881e2bcddd111edc4a3c0da3e88d + 0ea4e7c33d43e17cc516a72f76437c4bf81d8f4eac69ac355d3bf9b71b8138d55dc10fd458be115afa798b55dac34be1 + 0f8991d2a1ad662e7b6f58ab787947f1fa607fce12dde171bc17903b012091b657e15333e11701edcf5b63ba2a561247 + 043b6f5fe4e52c839148dc66f2b3751e69a0f6ebb3d056d6465d50d4108543ecd956e10fa1640dfd9bc0030cc2558d28" + ), + }, ]; for case in cases { - let g = >>::encode_to_curve( - &case.msg, DOMAIN, + let g = >>::encode_to_curve( + case.msg, case.dst, ); - let g_uncompressed = G2Affine::from(g).to_uncompressed(); - - assert_eq!(case.expected(), hex::encode(&g_uncompressed[..])); + let aff = G2Affine::from(g); + let g_uncompressed = aff.to_uncompressed(); + case.check_output(&g_uncompressed); } } -// test vectors from the draft 10 RFC +// From #[test] -fn test_hash_to_curve_10() { - use bls12_381::{ - hash_to_curve::{ExpandMsgXmd, HashToCurve}, - G2Affine, - }; - use std::string::{String, ToString}; - - struct TestCase { - msg: &'static [u8], - expected: [&'static str; 4], - } - impl TestCase { - fn expected(&self) -> String { - self.expected[0].to_string() + self.expected[1] + self.expected[2] + self.expected[3] - } - } - - const DOMAIN: &[u8] = b"QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_RO_"; +fn hash_to_curve_works_for_draft16_testvectors_g2_sha256_ro() { + let dst = b"QUUX-V01-CS02-with-BLS12381G2_XMD:SHA-256_SSWU_RO_"; let cases = vec![ TestCase { msg: b"", - expected: [ - "05cb8437535e20ecffaef7752baddf98034139c38452458baeefab379ba13dff5bf5dd71b72418717047f5b0f37da03d", - "0141ebfbdca40eb85b87142e130ab689c673cf60f1a3e98d69335266f30d9b8d4ac44c1038e9dcdd5393faf5c41fb78a", - "12424ac32561493f3fe3c260708a12b7c620e7be00099a974e259ddc7d1f6395c3c811cdd19f1e8dbf3e9ecfdcbab8d6", - "0503921d7f6a12805e72940b963c0cf3471c7b2a524950ca195d11062ee75ec076daf2d4bc358c4b190c0c98064fdd92", - ], + dst, + expected: &hex!( + "05cb8437535e20ecffaef7752baddf98034139c38452458baeefab379ba13dff5bf5dd71b72418717047f5b0f37da03d + 0141ebfbdca40eb85b87142e130ab689c673cf60f1a3e98d69335266f30d9b8d4ac44c1038e9dcdd5393faf5c41fb78a + 12424ac32561493f3fe3c260708a12b7c620e7be00099a974e259ddc7d1f6395c3c811cdd19f1e8dbf3e9ecfdcbab8d6 + 0503921d7f6a12805e72940b963c0cf3471c7b2a524950ca195d11062ee75ec076daf2d4bc358c4b190c0c98064fdd92" + ), }, TestCase { msg: b"abc", - expected: [ - "139cddbccdc5e91b9623efd38c49f81a6f83f175e80b06fc374de9eb4b41dfe4ca3a230ed250fbe3a2acf73a41177fd8", - "02c2d18e033b960562aae3cab37a27ce00d80ccd5ba4b7fe0e7a210245129dbec7780ccc7954725f4168aff2787776e6", - "00aa65dae3c8d732d10ecd2c50f8a1baf3001578f71c694e03866e9f3d49ac1e1ce70dd94a733534f106d4cec0eddd16", - "1787327b68159716a37440985269cf584bcb1e621d3a7202be6ea05c4cfe244aeb197642555a0645fb87bf7466b2ba48", - ], + dst, + expected: &hex!( + "139cddbccdc5e91b9623efd38c49f81a6f83f175e80b06fc374de9eb4b41dfe4ca3a230ed250fbe3a2acf73a41177fd8 + 02c2d18e033b960562aae3cab37a27ce00d80ccd5ba4b7fe0e7a210245129dbec7780ccc7954725f4168aff2787776e6 + 00aa65dae3c8d732d10ecd2c50f8a1baf3001578f71c694e03866e9f3d49ac1e1ce70dd94a733534f106d4cec0eddd16 + 1787327b68159716a37440985269cf584bcb1e621d3a7202be6ea05c4cfe244aeb197642555a0645fb87bf7466b2ba48" + ), }, TestCase { msg: b"abcdef0123456789", - expected: [ - "190d119345b94fbd15497bcba94ecf7db2cbfd1e1fe7da034d26cbba169fb3968288b3fafb265f9ebd380512a71c3f2c", - "121982811d2491fde9ba7ed31ef9ca474f0e1501297f68c298e9f4c0028add35aea8bb83d53c08cfc007c1e005723cd0", - "0bb5e7572275c567462d91807de765611490205a941a5a6af3b1691bfe596c31225d3aabdf15faff860cb4ef17c7c3be", - "05571a0f8d3c08d094576981f4a3b8eda0a8e771fcdcc8ecceaf1356a6acf17574518acb506e435b639353c2e14827c8", - ] + dst, + expected: &hex!( + "190d119345b94fbd15497bcba94ecf7db2cbfd1e1fe7da034d26cbba169fb3968288b3fafb265f9ebd380512a71c3f2c + 121982811d2491fde9ba7ed31ef9ca474f0e1501297f68c298e9f4c0028add35aea8bb83d53c08cfc007c1e005723cd0 + 0bb5e7572275c567462d91807de765611490205a941a5a6af3b1691bfe596c31225d3aabdf15faff860cb4ef17c7c3be + 05571a0f8d3c08d094576981f4a3b8eda0a8e771fcdcc8ecceaf1356a6acf17574518acb506e435b639353c2e14827c8" + ), }, TestCase { msg: b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\ qqqqqqqqqqqqqqqqqqqqqqqqq", - expected: [ - "0934aba516a52d8ae479939a91998299c76d39cc0c035cd18813bec433f587e2d7a4fef038260eef0cef4d02aae3eb91", - "19a84dd7248a1066f737cc34502ee5555bd3c19f2ecdb3c7d9e24dc65d4e25e50d83f0f77105e955d78f4762d33c17da", - "09bcccfa036b4847c9950780733633f13619994394c23ff0b32fa6b795844f4a0673e20282d07bc69641cee04f5e5662", - "14f81cd421617428bc3b9fe25afbb751d934a00493524bc4e065635b0555084dd54679df1536101b2c979c0152d09192", - ] + dst, + expected: &hex!( + "0934aba516a52d8ae479939a91998299c76d39cc0c035cd18813bec433f587e2d7a4fef038260eef0cef4d02aae3eb91 + 19a84dd7248a1066f737cc34502ee5555bd3c19f2ecdb3c7d9e24dc65d4e25e50d83f0f77105e955d78f4762d33c17da + 09bcccfa036b4847c9950780733633f13619994394c23ff0b32fa6b795844f4a0673e20282d07bc69641cee04f5e5662 + 14f81cd421617428bc3b9fe25afbb751d934a00493524bc4e065635b0555084dd54679df1536101b2c979c0152d09192" + ), }, TestCase { msg: b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ @@ -161,21 +164,21 @@ fn test_hash_to_curve_10() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - expected: [ - "11fca2ff525572795a801eed17eb12785887c7b63fb77a42be46ce4a34131d71f7a73e95fee3f812aea3de78b4d01569", - "01a6ba2f9a11fa5598b2d8ace0fbe0a0eacb65deceb476fbbcb64fd24557c2f4b18ecfc5663e54ae16a84f5ab7f62534", - "03a47f8e6d1763ba0cad63d6114c0accbef65707825a511b251a660a9b3994249ae4e63fac38b23da0c398689ee2ab52", - "0b6798718c8aed24bc19cb27f866f1c9effcdbf92397ad6448b5c9db90d2b9da6cbabf48adc1adf59a1a28344e79d57e", - ] - } + dst, + expected: &hex!( + "11fca2ff525572795a801eed17eb12785887c7b63fb77a42be46ce4a34131d71f7a73e95fee3f812aea3de78b4d01569 + 01a6ba2f9a11fa5598b2d8ace0fbe0a0eacb65deceb476fbbcb64fd24557c2f4b18ecfc5663e54ae16a84f5ab7f62534 + 03a47f8e6d1763ba0cad63d6114c0accbef65707825a511b251a660a9b3994249ae4e63fac38b23da0c398689ee2ab52 + 0b6798718c8aed24bc19cb27f866f1c9effcdbf92397ad6448b5c9db90d2b9da6cbabf48adc1adf59a1a28344e79d57e" + ), + }, ]; for case in cases { - let g = >>::hash_to_curve( - &case.msg, DOMAIN, - ); - let g_uncompressed = G2Affine::from(g).to_uncompressed(); - - assert_eq!(case.expected(), hex::encode(&g_uncompressed[..])); + let g = + >>::hash_to_curve(case.msg, case.dst); + let aff = G2Affine::from(g); + let g_uncompressed = aff.to_uncompressed(); + case.check_output(&g_uncompressed); } } From db71a01d31e943e7dc6d72c1c6fa82e29696697c Mon Sep 17 00:00:00 2001 From: Andrew Whitehead Date: Mon, 8 Aug 2022 16:23:32 -0700 Subject: [PATCH 2/6] only implement Message for iterators Signed-off-by: Andrew Whitehead --- benches/hash_to_curve.rs | 8 ++-- src/hash_to_curve/expand_msg.rs | 70 +++++---------------------------- tests/expand_msg.rs | 18 ++++++++- tests/hash_to_curve_g1.rs | 9 +++-- tests/hash_to_curve_g2.rs | 9 +++-- 5 files changed, 43 insertions(+), 71 deletions(-) diff --git a/benches/hash_to_curve.rs b/benches/hash_to_curve.rs index 302b7c6b..94e22153 100644 --- a/benches/hash_to_curve.rs +++ b/benches/hash_to_curve.rs @@ -20,7 +20,7 @@ fn criterion_benchmark(c: &mut Criterion) { move |b| { b.iter(|| { >>::encode_to_curve( - black_box(message), + [black_box(message)], black_box(dst), ) }) @@ -29,7 +29,7 @@ fn criterion_benchmark(c: &mut Criterion) { c.bench_function(&format!("{} hash_to_curve SSWU SHA-256", name), move |b| { b.iter(|| { >>::hash_to_curve( - black_box(message), + [black_box(message)], black_box(dst), ) }) @@ -47,7 +47,7 @@ fn criterion_benchmark(c: &mut Criterion) { move |b| { b.iter(|| { >>::encode_to_curve( - black_box(message), + [black_box(message)], black_box(dst), ) }) @@ -56,7 +56,7 @@ fn criterion_benchmark(c: &mut Criterion) { c.bench_function(&format!("{} hash_to_curve SSWU SHA-256", name), move |b| { b.iter(|| { >>::hash_to_curve( - black_box(message), + [black_box(message)], black_box(dst), ) }) diff --git a/src/hash_to_curve/expand_msg.rs b/src/hash_to_curve/expand_msg.rs index 4e816fd5..33a3d9f9 100644 --- a/src/hash_to_curve/expand_msg.rs +++ b/src/hash_to_curve/expand_msg.rs @@ -102,71 +102,21 @@ pub trait Message { /// /// The parameters to successive calls to `f` are treated as a /// single concatenated octet string. - fn consume(self, f: impl FnMut(&[u8])); + fn input_message(self, f: impl FnMut(&[u8])); } -impl Message for &[u8] { - #[inline] - fn consume(self, mut f: impl FnMut(&[u8])) { - f(self) - } -} - -impl Message for &[u8; N] { - #[inline] - fn consume(self, mut f: impl FnMut(&[u8])) { - f(self) - } -} - -impl Message for &str { - #[inline] - fn consume(self, mut f: impl FnMut(&[u8])) { - f(self.as_bytes()) - } -} - -impl Message for &[&[u8]] { - #[inline] - fn consume(self, mut f: impl FnMut(&[u8])) { +impl Message for I +where + M: AsRef<[u8]>, + I: IntoIterator, +{ + fn input_message(self, mut f: impl FnMut(&[u8])) { for msg in self { - f(msg); + f(msg.as_ref()) } } } -#[cfg(feature = "alloc")] -impl Message for Vec { - #[inline] - fn consume(self, mut f: impl FnMut(&[u8])) { - f(self.as_slice()) - } -} - -#[cfg(feature = "alloc")] -impl Message for &Vec { - #[inline] - fn consume(self, mut f: impl FnMut(&[u8])) { - f(self.as_slice()) - } -} - -#[cfg(feature = "alloc")] -impl Message for alloc::string::String { - #[inline] - fn consume(self, mut f: impl FnMut(&[u8])) { - f(self.as_bytes()) - } -} - -#[cfg(feature = "alloc")] -impl Message for &alloc::string::String { - #[inline] - fn consume(self, mut f: impl FnMut(&[u8])) { - f(self.as_bytes()) - } -} - /// A trait for message expansion methods supported by hash-to-curve. pub trait ExpandMessage { /// Initializes a message expander. @@ -230,7 +180,7 @@ where let dst = ExpandMsgDst::for_xof::(dst); let mut hash = H::default(); - message.consume(|m| hash.update(m)); + message.input_message(|m| hash.update(m)); let reader = hash .chain((len_in_bytes as u16).to_be_bytes()) .chain(dst.data()) @@ -294,7 +244,7 @@ where let dst = ExpandMsgDst::for_xmd::(dst); let mut hash_b_0 = H::default().chain(GenericArray::::BlockSize>::default()); - message.consume(|m| hash_b_0.update(m)); + message.input_message(|m| hash_b_0.update(m)); let b_0 = hash_b_0 .chain((len_in_bytes as u16).to_be_bytes()) .chain([0u8]) diff --git a/tests/expand_msg.rs b/tests/expand_msg.rs index ff8a5528..dd1892d2 100644 --- a/tests/expand_msg.rs +++ b/tests/expand_msg.rs @@ -4,6 +4,22 @@ use hex_literal::hex; use sha2::{Sha256, Sha512}; use sha3::{Shake128, Shake256}; +#[test] +fn test_expand_message_parts() { + const EXPAND_LEN: usize = 16; + let mut b1 = [0u8; EXPAND_LEN]; + let mut b2 = [0u8; EXPAND_LEN]; + as ExpandMessage>::init_expand::<_, U32>( + [b"sig" as &[u8], b"nature"], + &[], + EXPAND_LEN, + ) + .read_into(&mut b1); + as ExpandMessage>::init_expand::<_, U32>([b"signature"], &[], EXPAND_LEN) + .read_into(&mut b2); + assert_eq!(b1, b2); +} + struct TestCase { msg: &'static [u8], dst: &'static [u8], @@ -16,7 +32,7 @@ impl TestCase { pub fn run(self) { let mut buf = [0u8; 128]; let output = &mut buf[..self.len_in_bytes]; - E::init_expand::<_, U32>(self.msg, self.dst, self.len_in_bytes).read_into(output); + E::init_expand::<_, U32>([self.msg], self.dst, self.len_in_bytes).read_into(output); if output != self.uniform_bytes { panic!( "Failed: expand_message.\n\ diff --git a/tests/hash_to_curve_g1.rs b/tests/hash_to_curve_g1.rs index 6f8857a3..42e57fb9 100644 --- a/tests/hash_to_curve_g1.rs +++ b/tests/hash_to_curve_g1.rs @@ -87,7 +87,8 @@ fn encode_to_curve_works_for_draft16_testvectors_g1_sha256_nu() { for case in cases { let g = >>::encode_to_curve( - case.msg, case.dst, + [case.msg], + case.dst, ); let aff = G1Affine::from(g); let g_uncompressed = aff.to_uncompressed(); @@ -155,8 +156,10 @@ fn hash_to_curve_works_for_draft16_testvectors_g1_sha256_ro() { ]; for case in cases { - let g = - >>::hash_to_curve(case.msg, case.dst); + let g = >>::hash_to_curve( + [case.msg], + case.dst, + ); let aff = G1Affine::from(g); let g_uncompressed = aff.to_uncompressed(); case.check_output(&g_uncompressed); diff --git a/tests/hash_to_curve_g2.rs b/tests/hash_to_curve_g2.rs index da8b80cf..08d7a97f 100644 --- a/tests/hash_to_curve_g2.rs +++ b/tests/hash_to_curve_g2.rs @@ -97,7 +97,8 @@ fn encode_to_curve_works_for_draft16_testvectors_g2_sha256_nu() { for case in cases { let g = >>::encode_to_curve( - case.msg, case.dst, + [case.msg], + case.dst, ); let aff = G2Affine::from(g); let g_uncompressed = aff.to_uncompressed(); @@ -175,8 +176,10 @@ fn hash_to_curve_works_for_draft16_testvectors_g2_sha256_ro() { ]; for case in cases { - let g = - >>::hash_to_curve(case.msg, case.dst); + let g = >>::hash_to_curve( + [case.msg], + case.dst, + ); let aff = G2Affine::from(g); let g_uncompressed = aff.to_uncompressed(); case.check_output(&g_uncompressed); From eb3f0a973a918532219d3f0850dd8b2ae57326f0 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 21 Jul 2024 21:26:23 +0000 Subject: [PATCH 3/6] Document `L` generic of `ExpandMessage::init_expand` --- src/hash_to_curve/expand_msg.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/hash_to_curve/expand_msg.rs b/src/hash_to_curve/expand_msg.rs index 33a3d9f9..9f6192d3 100644 --- a/src/hash_to_curve/expand_msg.rs +++ b/src/hash_to_curve/expand_msg.rs @@ -42,6 +42,9 @@ impl ExpandMsgDst { } /// Produces a DST for use with `expand_message_xof`. + /// + /// `L` **MUST** be set to `ceil(2 * k / 8)`, where `k` is the security parameter. It + /// is used when handling DST values longer than 255 bytes. pub fn for_xof(dst: &[u8]) -> Self where H: Default + Update + ExtendableOutput, @@ -120,6 +123,10 @@ where /// A trait for message expansion methods supported by hash-to-curve. pub trait ExpandMessage { /// Initializes a message expander. + /// + /// `L` **MUST** be set to `ceil(2 * k / 8)`, where `k` is the security parameter. + /// It is used by certain trait implementations (for example, [`ExpandMsgXof`]) when + /// handling DST values longer than 255 bytes. fn init_expand(message: M, dst: &[u8], len_in_bytes: usize) -> Self where M: Message, From cf264e6eb5a1b2420cb14333362909ab83238d59 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 21 Jul 2024 21:27:22 +0000 Subject: [PATCH 4/6] Add missing `len_in_bytes` check to `ExpandMsgXmd::init_expand` --- src/hash_to_curve/expand_msg.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hash_to_curve/expand_msg.rs b/src/hash_to_curve/expand_msg.rs index 9f6192d3..2b9beca6 100644 --- a/src/hash_to_curve/expand_msg.rs +++ b/src/hash_to_curve/expand_msg.rs @@ -248,6 +248,10 @@ where if ell > 255 { panic!("Invalid ExpandMsgXmd usage: ell > 255"); } + if len_in_bytes > u16::MAX as usize { + panic!("Invalid ExpandMsgXmd usage: len_in_bytes > u16::MAX"); + } + let dst = ExpandMsgDst::for_xmd::(dst); let mut hash_b_0 = H::default().chain(GenericArray::::BlockSize>::default()); From 9a812471c6c704406725020b370643b8ac273361 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 21 Jul 2024 21:28:28 +0000 Subject: [PATCH 5/6] Remove `pub` qualifiers from non-pub `ExpandMsgDst` --- src/hash_to_curve/expand_msg.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hash_to_curve/expand_msg.rs b/src/hash_to_curve/expand_msg.rs index 2b9beca6..e9993aab 100644 --- a/src/hash_to_curve/expand_msg.rs +++ b/src/hash_to_curve/expand_msg.rs @@ -45,7 +45,7 @@ impl ExpandMsgDst { /// /// `L` **MUST** be set to `ceil(2 * k / 8)`, where `k` is the security parameter. It /// is used when handling DST values longer than 255 bytes. - pub fn for_xof(dst: &[u8]) -> Self + fn for_xof(dst: &[u8]) -> Self where H: Default + Update + ExtendableOutput, L: ArrayLength + IsLess, @@ -67,7 +67,7 @@ impl ExpandMsgDst { } /// Produces a DST for use with `expand_message_xmd`. - pub fn for_xmd(dst: &[u8]) -> Self + fn for_xmd(dst: &[u8]) -> Self where H: Default + FixedOutput + Update, { @@ -89,12 +89,12 @@ impl ExpandMsgDst { } /// Returns the raw bytes of the DST. - pub fn data(&self) -> &[u8] { + fn data(&self) -> &[u8] { &self.dst[..self.len] } /// Returns the length of the DST. - pub fn len(&self) -> usize { + fn len(&self) -> usize { self.len } } From 09466e0ed76762ebed3cb12f5ae8446c19a1b614 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 21 Jul 2024 21:55:33 +0000 Subject: [PATCH 6/6] Require `ExpandMsgXmd` has `H::OutputSize < 256` instead of truncating The draft (and the final RFC) do not explicitly give an upper limit on the hash output size, but section 5.3.3 says that `expand_message_xmd` requires that DST is at most 255 bytes, and when given a longer domain separation tag, to use the output of `H` directly as the DST. To avoid any ambiguities, we bound the set of `H` we support. --- src/hash_to_curve/expand_msg.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/hash_to_curve/expand_msg.rs b/src/hash_to_curve/expand_msg.rs index e9993aab..129c7f3f 100644 --- a/src/hash_to_curve/expand_msg.rs +++ b/src/hash_to_curve/expand_msg.rs @@ -67,9 +67,13 @@ impl ExpandMsgDst { } /// Produces a DST for use with `expand_message_xmd`. + /// + /// The output size of `H` is required to be less than 256 bytes, so it can be used to + /// reduce domain separation tags that are longer than 255 bytes. fn for_xmd(dst: &[u8]) -> Self where H: Default + FixedOutput + Update, + H::OutputSize: IsLess, { let input_len = dst.len(); ExpandMsgDst::new(|buf| { @@ -78,7 +82,7 @@ impl ExpandMsgDst { .chain(OVERSIZE_DST_SALT) .chain(&dst) .finalize_fixed(); - let len = hashed.len().min(MAX_DST_LENGTH); + let len = hashed.len(); buf[..len].copy_from_slice(&hashed); len } else { @@ -216,7 +220,12 @@ where /// /// Implements [section 5.3.1 of `draft-irtf-cfrg-hash-to-curve-16`][expand_message_xmd]. /// +/// The output size of `H` is required to be less than 256 bytes, so it can be used to +/// reduce domain separation tags that are longer than 255 bytes (as specified in +/// [section 5.3.3 of `draft-irtf-cfrg-hash-to-curve-16`][dst]). +/// /// [expand_message_xmd]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.1 +/// [dst]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3 pub struct ExpandMsgXmd { dst: ExpandMsgDst, b_0: GenericArray, @@ -237,6 +246,7 @@ impl Debug for ExpandMsgXmd { impl ExpandMessage for ExpandMsgXmd where H: Default + BlockInput + FixedOutput + Update, + H::OutputSize: IsLess, { fn init_expand(message: M, dst: &[u8], len_in_bytes: usize) -> Self where