halo2curves_axiom/bls12_381/hash_to_curve/
expand_msg.rs

1//! This module implements message expansion consistent with the
2//! hash-to-curve RFC drafts 7 through 10
3//!
4//! Source: <https://github.com/privacy-scaling-explorations/bls12_381>
5
6use core::{
7    fmt::{self, Debug, Formatter},
8    marker::PhantomData,
9};
10
11use digest::{crypto_common::BlockSizeUser, Digest, ExtendableOutput, Update, XofReader};
12
13use crate::bls12_381::generic_array::{
14    typenum::{Unsigned, U32},
15    ArrayLength, GenericArray,
16};
17
18#[cfg(feature = "alloc")]
19use alloc::vec::Vec;
20
21const OVERSIZE_DST_SALT: &[u8] = b"H2C-OVERSIZE-DST-";
22
23/// The domain separation tag for a message expansion.
24///
25/// Implements [section 5.4.3 of `draft-irtf-cfrg-hash-to-curve-12`][dst].
26///
27/// [dst]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-12#section-5.4.3
28#[derive(Debug)]
29enum ExpandMsgDst<'x, L: ArrayLength<u8>> {
30    /// DST produced by hashing a very long (> 255 chars) input DST.
31    Hashed(GenericArray<u8, L>),
32    /// A raw input DST (<= 255 chars).
33    Raw(&'x [u8]),
34}
35
36impl<'x, L: ArrayLength<u8>> ExpandMsgDst<'x, L> {
37    /// Produces a DST for use with `expand_message_xof`.
38    pub fn process_xof<H>(dst: &'x [u8]) -> Self
39    where
40        H: Default + Update + ExtendableOutput,
41    {
42        if dst.len() > 255 {
43            let mut data = GenericArray::<u8, L>::default();
44            H::default()
45                .chain(OVERSIZE_DST_SALT)
46                .chain(dst)
47                .finalize_xof()
48                .read(&mut data);
49            Self::Hashed(data)
50        } else {
51            Self::Raw(dst)
52        }
53    }
54
55    /// Produces a DST for use with `expand_message_xmd`.
56    pub fn process_xmd<H>(dst: &'x [u8]) -> Self
57    where
58        H: Digest<OutputSize = L>,
59    {
60        if dst.len() > 255 {
61            Self::Hashed(
62                H::new()
63                    .chain_update(OVERSIZE_DST_SALT)
64                    .chain_update(dst)
65                    .finalize(),
66            )
67        } else {
68            Self::Raw(dst)
69        }
70    }
71
72    /// Returns the raw bytes of the DST.
73    pub fn data(&'x self) -> &'x [u8] {
74        match self {
75            Self::Hashed(arr) => &arr[..],
76            Self::Raw(buf) => buf,
77        }
78    }
79
80    /// Returns the length of the DST.
81    pub fn len(&'x self) -> usize {
82        match self {
83            Self::Hashed(_) => L::to_usize(),
84            Self::Raw(buf) => buf.len(),
85        }
86    }
87}
88
89/// A trait for message expansion methods supported by hash-to-curve.
90pub trait ExpandMessage: for<'x> InitExpandMessage<'x> {
91    // This intermediate is likely only necessary until GATs allow
92    // associated types with lifetimes.
93}
94
95/// Trait for constructing a new message expander.
96pub trait InitExpandMessage<'x> {
97    /// The state object used during message expansion.
98    type Expander: ExpandMessageState<'x>;
99
100    /// Initializes a message expander.
101    fn init_expand(message: &[u8], dst: &'x [u8], len_in_bytes: usize) -> Self::Expander;
102}
103
104// Automatically derive trait
105impl<X: for<'x> InitExpandMessage<'x>> ExpandMessage for X {}
106
107/// Trait for types implementing the `expand_message` interface for `hash_to_field`.
108pub trait ExpandMessageState<'x> {
109    /// Reads bytes from the generated output.
110    fn read_into(&mut self, output: &mut [u8]) -> usize;
111
112    /// Retrieves the number of bytes remaining in the generator.
113    fn remain(&self) -> usize;
114
115    #[cfg(feature = "alloc")]
116    /// Constructs a `Vec` containing the remaining bytes of the output.
117    fn into_vec(mut self) -> Vec<u8>
118    where
119        Self: Sized,
120    {
121        let mut result = alloc::vec![0u8; self.remain()];
122        self.read_into(&mut result[..]);
123        result
124    }
125}
126
127/// A generator for the output of `expand_message_xof` for a given
128/// extendable hash function, message, DST, and output length.
129///
130/// Implements [section 5.4.2 of `draft-irtf-cfrg-hash-to-curve-12`][expand_message_xof]
131/// with `k = 128`.
132///
133/// [expand_message_xof]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-12#section-5.4.2
134pub struct ExpandMsgXof<H: ExtendableOutput> {
135    hash: <H as ExtendableOutput>::Reader,
136    remain: usize,
137}
138
139impl<H: ExtendableOutput> Debug for ExpandMsgXof<H> {
140    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
141        f.debug_struct("ExpandMsgXof")
142            .field("remain", &self.remain)
143            .finish()
144    }
145}
146
147impl<'x, H> ExpandMessageState<'x> for ExpandMsgXof<H>
148where
149    H: ExtendableOutput,
150{
151    fn read_into(&mut self, output: &mut [u8]) -> usize {
152        let len = self.remain.min(output.len());
153        self.hash.read(&mut output[..len]);
154        self.remain -= len;
155        len
156    }
157
158    fn remain(&self) -> usize {
159        self.remain
160    }
161}
162
163impl<'x, H> InitExpandMessage<'x> for ExpandMsgXof<H>
164where
165    H: Default + Update + ExtendableOutput,
166{
167    type Expander = Self;
168
169    fn init_expand(message: &[u8], dst: &[u8], len_in_bytes: usize) -> Self {
170        // Use U32 here for k = 128.
171        let dst = ExpandMsgDst::<U32>::process_xof::<H>(dst);
172        let hash = H::default()
173            .chain(message)
174            .chain((len_in_bytes as u16).to_be_bytes())
175            .chain(dst.data())
176            .chain([dst.len() as u8])
177            .finalize_xof();
178        Self {
179            hash,
180            remain: len_in_bytes,
181        }
182    }
183}
184
185/// Constructor for `expand_message_xmd` for a given digest hash function, message, DST,
186/// and output length.
187///
188/// Implements [section 5.4.1 of `draft-irtf-cfrg-hash-to-curve-12`][expand_message_xmd].
189///
190/// [expand_message_xmd]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-12#section-5.4.1
191#[derive(Debug)]
192pub struct ExpandMsgXmd<H: Digest>(PhantomData<H>);
193
194/// A generator for the output of `expand_message_xmd` for a given
195/// digest hash function, message, DST, and output length.
196///
197/// Implements [section 5.4.1 of `draft-irtf-cfrg-hash-to-curve-12`][expand_message_xmd].
198///
199/// [expand_message_xmd]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-12#section-5.4.1
200pub struct ExpandMsgXmdState<'x, H: Digest> {
201    dst: ExpandMsgDst<'x, H::OutputSize>,
202    b_0: GenericArray<u8, H::OutputSize>,
203    b_i: GenericArray<u8, H::OutputSize>,
204    i: usize,
205    b_offs: usize,
206    remain: usize,
207}
208
209impl<H: Digest> Debug for ExpandMsgXmdState<'_, H> {
210    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
211        f.debug_struct("ExpandMsgXmdState")
212            .field("remain", &self.remain)
213            .finish()
214    }
215}
216
217impl<'x, H> InitExpandMessage<'x> for ExpandMsgXmd<H>
218where
219    H: Digest + BlockSizeUser,
220{
221    type Expander = ExpandMsgXmdState<'x, H>;
222
223    fn init_expand(message: &[u8], dst: &'x [u8], len_in_bytes: usize) -> Self::Expander {
224        let hash_size = <H as Digest>::output_size();
225        let ell = (len_in_bytes + hash_size - 1) / hash_size;
226        if ell > 255 {
227            panic!("Invalid ExpandMsgXmd usage: ell > 255");
228        }
229        let dst = ExpandMsgDst::process_xmd::<H>(dst);
230        let b_0 = H::new()
231            .chain_update(GenericArray::<u8, <H>::BlockSize>::default())
232            .chain_update(message)
233            .chain_update((len_in_bytes as u16).to_be_bytes())
234            .chain_update([0u8])
235            .chain_update(dst.data())
236            .chain_update([dst.len() as u8])
237            .finalize();
238        // init with b_1
239        let b_i = H::new()
240            .chain_update(&b_0)
241            .chain_update([1u8])
242            .chain_update(dst.data())
243            .chain_update([dst.len() as u8])
244            .finalize();
245        ExpandMsgXmdState {
246            dst,
247            b_0,
248            b_i,
249            i: 2,
250            b_offs: 0,
251            remain: len_in_bytes,
252        }
253    }
254}
255
256impl<'x, H> ExpandMessageState<'x> for ExpandMsgXmdState<'x, H>
257where
258    H: Digest,
259{
260    fn read_into(&mut self, output: &mut [u8]) -> usize {
261        let read_len = self.remain.min(output.len());
262        let mut offs = 0;
263        let hash_size = H::OutputSize::to_usize();
264        while offs < read_len {
265            let b_offs = self.b_offs;
266            let mut copy_len = hash_size - b_offs;
267            if copy_len > 0 {
268                copy_len = copy_len.min(read_len - offs);
269                output[offs..(offs + copy_len)]
270                    .copy_from_slice(&self.b_i[b_offs..(b_offs + copy_len)]);
271                offs += copy_len;
272                self.b_offs = b_offs + copy_len;
273            } else {
274                let mut b_prev_xor = self.b_0.clone();
275                for j in 0..hash_size {
276                    b_prev_xor[j] ^= self.b_i[j];
277                }
278                self.b_i = H::new()
279                    .chain_update(b_prev_xor)
280                    .chain_update([self.i as u8])
281                    .chain_update(self.dst.data())
282                    .chain_update([self.dst.len() as u8])
283                    .finalize();
284                self.b_offs = 0;
285                self.i += 1;
286            }
287        }
288        self.remain -= read_len;
289        read_len
290    }
291
292    fn remain(&self) -> usize {
293        self.remain
294    }
295}
296
297#[cfg(feature = "alloc")]
298#[cfg(test)]
299mod tests {
300    use super::*;
301    use sha2::{Sha256, Sha512};
302    use sha3::{Shake128, Shake256};
303
304    /// From <https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-12#appendix-K.1>
305    #[test]
306    fn expand_message_xmd_works_for_draft12_testvectors_sha256() {
307        let dst = b"QUUX-V01-CS02-with-expander-SHA256-128";
308
309        let msg = b"";
310        let len_in_bytes = 0x20;
311        let uniform_bytes = hex::decode(
312            "68a985b87eb6b46952128911f2a4412bbc302a9d759667f8\
313            7f7a21d803f07235",
314        )
315        .unwrap();
316        assert_eq!(
317            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
318            uniform_bytes
319        );
320
321        let msg = b"abc";
322        let len_in_bytes = 0x20;
323        let uniform_bytes = hex::decode(
324            "d8ccab23b5985ccea865c6c97b6e5b8350e794e603b4b979\
325            02f53a8a0d605615",
326        )
327        .unwrap();
328        assert_eq!(
329            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
330            uniform_bytes
331        );
332
333        let msg = b"abcdef0123456789";
334        let len_in_bytes = 0x20;
335        let uniform_bytes = hex::decode(
336            "eff31487c770a893cfb36f912fbfcbff40d5661771ca4b2c\
337            b4eafe524333f5c1",
338        )
339        .unwrap();
340        assert_eq!(
341            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
342            uniform_bytes
343        );
344
345        let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
346            qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
347            qqqqqqqqqqqqqqqqqqqqqqqqq";
348        let len_in_bytes = 0x20;
349        let uniform_bytes = hex::decode(
350            "b23a1d2b4d97b2ef7785562a7e8bac7eed54ed6e97e29aa5\
351            1bfe3f12ddad1ff9",
352        )
353        .unwrap();
354        assert_eq!(
355            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
356            uniform_bytes
357        );
358
359        let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
360            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
361            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
362            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
363            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
364            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
365            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
366            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
367            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
368            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
369        let len_in_bytes = 0x20;
370        let uniform_bytes = hex::decode(
371            "4623227bcc01293b8c130bf771da8c298dede7383243dc09\
372            93d2d94823958c4c",
373        )
374        .unwrap();
375        assert_eq!(
376            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
377            uniform_bytes
378        );
379
380        let msg = b"";
381        let len_in_bytes = 0x80;
382        let uniform_bytes = hex::decode(
383            "af84c27ccfd45d41914fdff5df25293e221afc53d8ad2ac0\
384            6d5e3e29485dadbee0d121587713a3e0dd4d5e69e93eb7cd4f5df4\
385            cd103e188cf60cb02edc3edf18eda8576c412b18ffb658e3dd6ec8\
386            49469b979d444cf7b26911a08e63cf31f9dcc541708d3491184472\
387            c2c29bb749d4286b004ceb5ee6b9a7fa5b646c993f0ced",
388        )
389        .unwrap();
390        assert_eq!(
391            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
392            uniform_bytes
393        );
394
395        let msg = b"abc";
396        let len_in_bytes = 0x80;
397        let uniform_bytes = hex::decode(
398            "abba86a6129e366fc877aab32fc4ffc70120d8996c88aee2\
399            fe4b32d6c7b6437a647e6c3163d40b76a73cf6a5674ef1d890f95b\
400            664ee0afa5359a5c4e07985635bbecbac65d747d3d2da7ec2b8221\
401            b17b0ca9dc8a1ac1c07ea6a1e60583e2cb00058e77b7b72a298425\
402            cd1b941ad4ec65e8afc50303a22c0f99b0509b4c895f40",
403        )
404        .unwrap();
405        assert_eq!(
406            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
407            uniform_bytes
408        );
409
410        let msg = b"abcdef0123456789";
411        let len_in_bytes = 0x80;
412        let uniform_bytes = hex::decode(
413            "ef904a29bffc4cf9ee82832451c946ac3c8f8058ae97d8d6\
414            29831a74c6572bd9ebd0df635cd1f208e2038e760c4994984ce73f\
415            0d55ea9f22af83ba4734569d4bc95e18350f740c07eef653cbb9f8\
416            7910d833751825f0ebefa1abe5420bb52be14cf489b37fe1a72f7d\
417            e2d10be453b2c9d9eb20c7e3f6edc5a60629178d9478df",
418        )
419        .unwrap();
420        assert_eq!(
421            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
422            uniform_bytes
423        );
424
425        let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
426            qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
427            qqqqqqqqqqqqqqqqqqqqqqqqq";
428        let len_in_bytes = 0x80;
429        let uniform_bytes = hex::decode(
430            "80be107d0884f0d881bb460322f0443d38bd222db8bd0b0a\
431            5312a6fedb49c1bbd88fd75d8b9a09486c60123dfa1d73c1cc3169\
432            761b17476d3c6b7cbbd727acd0e2c942f4dd96ae3da5de368d26b3\
433            2286e32de7e5a8cb2949f866a0b80c58116b29fa7fabb3ea7d520e\
434            e603e0c25bcaf0b9a5e92ec6a1fe4e0391d1cdbce8c68a",
435        )
436        .unwrap();
437        assert_eq!(
438            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
439            uniform_bytes
440        );
441
442        let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
443            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
444            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
445            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
446            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
447            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
448            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
449            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
450            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
451            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
452        let len_in_bytes = 0x80;
453        let uniform_bytes = hex::decode(
454            "546aff5444b5b79aa6148bd81728704c32decb73a3ba76e9\
455            e75885cad9def1d06d6792f8a7d12794e90efed817d96920d72889\
456            6a4510864370c207f99bd4a608ea121700ef01ed879745ee3e4cee\
457            f777eda6d9e5e38b90c86ea6fb0b36504ba4a45d22e86f6db5dd43\
458            d98a294bebb9125d5b794e9d2a81181066eb954966a487",
459        )
460        .unwrap();
461        assert_eq!(
462            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
463            uniform_bytes
464        );
465    }
466
467    /// From <https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-12#appendix-K.2>
468    #[test]
469    fn expand_message_xmd_works_for_draft12_testvectors_sha256_long_dst() {
470        let dst = b"QUUX-V01-CS02-with-expander-SHA256-128-long-DST-111111\
471            111111111111111111111111111111111111111111111111111111\
472            111111111111111111111111111111111111111111111111111111\
473            111111111111111111111111111111111111111111111111111111\
474            1111111111111111111111111111111111111111";
475
476        let msg = b"";
477        let len_in_bytes = 0x20;
478        let uniform_bytes = hex::decode(
479            "e8dc0c8b686b7ef2074086fbdd2f30e3f8bfbd3bdf177f73\
480            f04b97ce618a3ed3",
481        )
482        .unwrap();
483        assert_eq!(
484            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
485            uniform_bytes
486        );
487
488        let msg = b"abc";
489        let len_in_bytes = 0x20;
490        let uniform_bytes = hex::decode(
491            "52dbf4f36cf560fca57dedec2ad924ee9c266341d8f3d6af\
492            e5171733b16bbb12",
493        )
494        .unwrap();
495        assert_eq!(
496            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
497            uniform_bytes
498        );
499
500        let msg = b"abcdef0123456789";
501        let len_in_bytes = 0x20;
502        let uniform_bytes = hex::decode(
503            "35387dcf22618f3728e6c686490f8b431f76550b0b2c61cb\
504            c1ce7001536f4521",
505        )
506        .unwrap();
507        assert_eq!(
508            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
509            uniform_bytes
510        );
511
512        let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
513            qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
514            qqqqqqqqqqqqqqqqqqqqqqqqq";
515        let len_in_bytes = 0x20;
516        let uniform_bytes = hex::decode(
517            "01b637612bb18e840028be900a833a74414140dde0c4754c\
518            198532c3a0ba42bc",
519        )
520        .unwrap();
521        assert_eq!(
522            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
523            uniform_bytes
524        );
525
526        let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
527            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
528            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
529            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
530            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
531            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
532            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
533            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
534            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
535            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
536        let len_in_bytes = 0x20;
537        let uniform_bytes = hex::decode(
538            "20cce7033cabc5460743180be6fa8aac5a103f56d481cf36\
539            9a8accc0c374431b",
540        )
541        .unwrap();
542        assert_eq!(
543            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
544            uniform_bytes
545        );
546
547        let msg = b"";
548        let len_in_bytes = 0x80;
549        let uniform_bytes = hex::decode(
550            "14604d85432c68b757e485c8894db3117992fc57e0e136f7\
551            1ad987f789a0abc287c47876978e2388a02af86b1e8d1342e5ce4f\
552            7aaa07a87321e691f6fba7e0072eecc1218aebb89fb14a0662322d\
553            5edbd873f0eb35260145cd4e64f748c5dfe60567e126604bcab1a3\
554            ee2dc0778102ae8a5cfd1429ebc0fa6bf1a53c36f55dfc",
555        )
556        .unwrap();
557        assert_eq!(
558            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
559            uniform_bytes
560        );
561
562        let msg = b"abc";
563        let len_in_bytes = 0x80;
564        let uniform_bytes = hex::decode(
565            "1a30a5e36fbdb87077552b9d18b9f0aee16e80181d5b951d\
566            0471d55b66684914aef87dbb3626eaabf5ded8cd0686567e503853\
567            e5c84c259ba0efc37f71c839da2129fe81afdaec7fbdc0ccd4c794\
568            727a17c0d20ff0ea55e1389d6982d1241cb8d165762dbc39fb0cee\
569            4474d2cbbd468a835ae5b2f20e4f959f56ab24cd6fe267",
570        )
571        .unwrap();
572        assert_eq!(
573            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
574            uniform_bytes
575        );
576
577        let msg = b"abcdef0123456789";
578        let len_in_bytes = 0x80;
579        let uniform_bytes = hex::decode(
580            "d2ecef3635d2397f34a9f86438d772db19ffe9924e28a1ca\
581            f6f1c8f15603d4028f40891044e5c7e39ebb9b31339979ff33a424\
582            9206f67d4a1e7c765410bcd249ad78d407e303675918f20f26ce6d\
583            7027ed3774512ef5b00d816e51bfcc96c3539601fa48ef1c07e494\
584            bdc37054ba96ecb9dbd666417e3de289d4f424f502a982",
585        )
586        .unwrap();
587        assert_eq!(
588            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
589            uniform_bytes
590        );
591
592        let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
593            qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
594            qqqqqqqqqqqqqqqqqqqqqqqqq";
595        let len_in_bytes = 0x80;
596        let uniform_bytes = hex::decode(
597            "ed6e8c036df90111410431431a232d41a32c86e296c05d42\
598            6e5f44e75b9a50d335b2412bc6c91e0a6dc131de09c43110d9180d\
599            0a70f0d6289cb4e43b05f7ee5e9b3f42a1fad0f31bac6a625b3b5c\
600            50e3a83316783b649e5ecc9d3b1d9471cb5024b7ccf40d41d1751a\
601            04ca0356548bc6e703fca02ab521b505e8e45600508d32",
602        )
603        .unwrap();
604        assert_eq!(
605            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
606            uniform_bytes
607        );
608
609        let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
610            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
611            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
612            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
613            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
614            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
615            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
616            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
617            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
618            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
619        let len_in_bytes = 0x80;
620        let uniform_bytes = hex::decode(
621            "78b53f2413f3c688f07732c10e5ced29a17c6a16f717179f\
622            fbe38d92d6c9ec296502eb9889af83a1928cd162e845b0d3c5424e\
623            83280fed3d10cffb2f8431f14e7a23f4c68819d40617589e4c4116\
624            9d0b56e0e3535be1fd71fbb08bb70c5b5ffed953d6c14bf7618b35\
625            fc1f4c4b30538236b4b08c9fbf90462447a8ada60be495",
626        )
627        .unwrap();
628        assert_eq!(
629            ExpandMsgXmd::<Sha256>::init_expand(msg, dst, len_in_bytes).into_vec(),
630            uniform_bytes
631        );
632    }
633
634    /// From <https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-12#appendix-K.3>
635    #[test]
636    fn expand_message_xmd_works_for_draft12_testvectors_sha512() {
637        let dst = b"QUUX-V01-CS02-with-expander-SHA512-256";
638
639        let msg = b"";
640        let len_in_bytes = 0x20;
641        let uniform_bytes = hex::decode(
642            "6b9a7312411d92f921c6f68ca0b6380730a1a4d982c50721\
643            1a90964c394179ba",
644        )
645        .unwrap();
646        assert_eq!(
647            ExpandMsgXmd::<Sha512>::init_expand(msg, dst, len_in_bytes).into_vec(),
648            uniform_bytes
649        );
650
651        let msg = b"abc";
652        let len_in_bytes = 0x20;
653        let uniform_bytes = hex::decode(
654            "0da749f12fbe5483eb066a5f595055679b976e93abe9be6f\
655            0f6318bce7aca8dc",
656        )
657        .unwrap();
658        assert_eq!(
659            ExpandMsgXmd::<Sha512>::init_expand(msg, dst, len_in_bytes).into_vec(),
660            uniform_bytes
661        );
662
663        let msg = b"abcdef0123456789";
664        let len_in_bytes = 0x20;
665        let uniform_bytes = hex::decode(
666            "087e45a86e2939ee8b91100af1583c4938e0f5fc6c9db4b1\
667            07b83346bc967f58",
668        )
669        .unwrap();
670        assert_eq!(
671            ExpandMsgXmd::<Sha512>::init_expand(msg, dst, len_in_bytes).into_vec(),
672            uniform_bytes
673        );
674
675        let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
676            qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
677            qqqqqqqqqqqqqqqqqqqqqqqqq";
678        let len_in_bytes = 0x20;
679        let uniform_bytes = hex::decode(
680            "7336234ee9983902440f6bc35b348352013becd88938d2af\
681            ec44311caf8356b3",
682        )
683        .unwrap();
684        assert_eq!(
685            ExpandMsgXmd::<Sha512>::init_expand(msg, dst, len_in_bytes).into_vec(),
686            uniform_bytes
687        );
688
689        let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
690            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
691            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
692            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
693            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
694            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
695            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
696            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
697            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
698            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
699        let len_in_bytes = 0x20;
700        let uniform_bytes = hex::decode(
701            "57b5f7e766d5be68a6bfe1768e3c2b7f1228b3e4b3134956\
702            dd73a59b954c66f4",
703        )
704        .unwrap();
705        assert_eq!(
706            ExpandMsgXmd::<Sha512>::init_expand(msg, dst, len_in_bytes).into_vec(),
707            uniform_bytes
708        );
709
710        let msg = b"";
711        let len_in_bytes = 0x80;
712        let uniform_bytes = hex::decode(
713            "41b037d1734a5f8df225dd8c7de38f851efdb45c372887be\
714            655212d07251b921b052b62eaed99b46f72f2ef4cc96bfaf254ebb\
715            bec091e1a3b9e4fb5e5b619d2e0c5414800a1d882b62bb5cd1778f\
716            098b8eb6cb399d5d9d18f5d5842cf5d13d7eb00a7cff859b605da6\
717            78b318bd0e65ebff70bec88c753b159a805d2c89c55961",
718        )
719        .unwrap();
720        assert_eq!(
721            ExpandMsgXmd::<Sha512>::init_expand(msg, dst, len_in_bytes).into_vec(),
722            uniform_bytes
723        );
724
725        let msg = b"abc";
726        let len_in_bytes = 0x80;
727        let uniform_bytes = hex::decode(
728            "7f1dddd13c08b543f2e2037b14cefb255b44c83cc397c178\
729            6d975653e36a6b11bdd7732d8b38adb4a0edc26a0cef4bb4521713\
730            5456e58fbca1703cd6032cb1347ee720b87972d63fbf232587043e\
731            d2901bce7f22610c0419751c065922b488431851041310ad659e4b\
732            23520e1772ab29dcdeb2002222a363f0c2b1c972b3efe1",
733        )
734        .unwrap();
735        assert_eq!(
736            ExpandMsgXmd::<Sha512>::init_expand(msg, dst, len_in_bytes).into_vec(),
737            uniform_bytes
738        );
739
740        let msg = b"abcdef0123456789";
741        let len_in_bytes = 0x80;
742        let uniform_bytes = hex::decode(
743            "3f721f208e6199fe903545abc26c837ce59ac6fa45733f1b\
744            aaf0222f8b7acb0424814fcb5eecf6c1d38f06e9d0a6ccfbf85ae6\
745            12ab8735dfdf9ce84c372a77c8f9e1c1e952c3a61b7567dd069301\
746            6af51d2745822663d0c2367e3f4f0bed827feecc2aaf98c949b5ed\
747            0d35c3f1023d64ad1407924288d366ea159f46287e61ac",
748        )
749        .unwrap();
750        assert_eq!(
751            ExpandMsgXmd::<Sha512>::init_expand(msg, dst, len_in_bytes).into_vec(),
752            uniform_bytes
753        );
754
755        let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
756            qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
757            qqqqqqqqqqqqqqqqqqqqqqqqq";
758        let len_in_bytes = 0x80;
759        let uniform_bytes = hex::decode(
760            "b799b045a58c8d2b4334cf54b78260b45eec544f9f2fb5bd\
761            12fb603eaee70db7317bf807c406e26373922b7b8920fa29142703\
762            dd52bdf280084fb7ef69da78afdf80b3586395b433dc66cde048a2\
763            58e476a561e9deba7060af40adf30c64249ca7ddea79806ee5beb9\
764            a1422949471d267b21bc88e688e4014087a0b592b695ed",
765        )
766        .unwrap();
767        assert_eq!(
768            ExpandMsgXmd::<Sha512>::init_expand(msg, dst, len_in_bytes).into_vec(),
769            uniform_bytes
770        );
771
772        let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
773            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
774            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
775            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
776            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
777            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
778            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
779            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
780            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
781            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
782        let len_in_bytes = 0x80;
783        let uniform_bytes = hex::decode(
784            "05b0bfef265dcee87654372777b7c44177e2ae4c13a27f10\
785            3340d9cd11c86cb2426ffcad5bd964080c2aee97f03be1ca18e30a\
786            1f14e27bc11ebbd650f305269cc9fb1db08bf90bfc79b42a952b46\
787            daf810359e7bc36452684784a64952c343c52e5124cd1f71d474d5\
788            197fefc571a92929c9084ffe1112cf5eea5192ebff330b",
789        )
790        .unwrap();
791        assert_eq!(
792            ExpandMsgXmd::<Sha512>::init_expand(msg, dst, len_in_bytes).into_vec(),
793            uniform_bytes
794        );
795    }
796
797    /// From <https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-12#appendix-K.4>
798    #[test]
799    fn expand_message_xof_works_for_draft12_testvectors_shake128() {
800        let dst = b"QUUX-V01-CS02-with-expander-SHAKE128";
801
802        let msg = b"";
803        let len_in_bytes = 0x20;
804        let uniform_bytes = hex::decode(
805            "86518c9cd86581486e9485aa74ab35ba150d1c75c88e26b7\
806             043e44e2acd735a2",
807        )
808        .unwrap();
809        assert_eq!(
810            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
811            uniform_bytes
812        );
813
814        let msg = b"abc";
815        let len_in_bytes = 0x20;
816        let uniform_bytes = hex::decode(
817            "8696af52a4d862417c0763556073f47bc9b9ba43c99b5053\
818             05cb1ec04a9ab468",
819        )
820        .unwrap();
821        assert_eq!(
822            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
823            uniform_bytes
824        );
825
826        let msg = b"abcdef0123456789";
827        let len_in_bytes = 0x20;
828        let uniform_bytes = hex::decode(
829            "912c58deac4821c3509dbefa094df54b34b8f5d01a191d1d\
830             3108a2c89077acca",
831        )
832        .unwrap();
833        assert_eq!(
834            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
835            uniform_bytes
836        );
837
838        let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
839             qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
840             qqqqqqqqqqqqqqqqqqqqqqqqq";
841        let len_in_bytes = 0x20;
842        let uniform_bytes = hex::decode(
843            "1adbcc448aef2a0cebc71dac9f756b22e51839d348e031e6\
844             3b33ebb50faeaf3f",
845        )
846        .unwrap();
847        assert_eq!(
848            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
849            uniform_bytes
850        );
851
852        let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
853             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
854             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
855             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
856             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
857             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
858             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
859             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
860             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
861             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
862        let len_in_bytes = 0x20;
863        let uniform_bytes = hex::decode(
864            "df3447cc5f3e9a77da10f819218ddf31342c310778e0e4ef\
865             72bbaecee786a4fe",
866        )
867        .unwrap();
868        assert_eq!(
869            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
870            uniform_bytes
871        );
872
873        let msg = b"";
874        let len_in_bytes = 0x80;
875        let uniform_bytes = hex::decode(
876            "7314ff1a155a2fb99a0171dc71b89ab6e3b2b7d59e38e644\
877             19b8b6294d03ffee42491f11370261f436220ef787f8f76f5b26bd\
878             cd850071920ce023f3ac46847744f4612b8714db8f5db83205b2e6\
879             25d95afd7d7b4d3094d3bdde815f52850bb41ead9822e08f22cf41\
880             d615a303b0d9dde73263c049a7b9898208003a739a2e57",
881        )
882        .unwrap();
883        assert_eq!(
884            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
885            uniform_bytes
886        );
887
888        let msg = b"abc";
889        let len_in_bytes = 0x80;
890        let uniform_bytes = hex::decode(
891            "c952f0c8e529ca8824acc6a4cab0e782fc3648c563ddb00d\
892             a7399f2ae35654f4860ec671db2356ba7baa55a34a9d7f79197b60\
893             ddae6e64768a37d699a78323496db3878c8d64d909d0f8a7de4927\
894             dcab0d3dbbc26cb20a49eceb0530b431cdf47bc8c0fa3e0d88f53b\
895             318b6739fbed7d7634974f1b5c386d6230c76260d5337a",
896        )
897        .unwrap();
898        assert_eq!(
899            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
900            uniform_bytes
901        );
902
903        let msg = b"abcdef0123456789";
904        let len_in_bytes = 0x80;
905        let uniform_bytes = hex::decode(
906            "19b65ee7afec6ac06a144f2d6134f08eeec185f1a890fe34\
907             e68f0e377b7d0312883c048d9b8a1d6ecc3b541cb4987c26f45e0c\
908             82691ea299b5e6889bbfe589153016d8131717ba26f07c3c14ffbe\
909             f1f3eff9752e5b6183f43871a78219a75e7000fbac6a7072e2b83c\
910             790a3a5aecd9d14be79f9fd4fb180960a3772e08680495",
911        )
912        .unwrap();
913        assert_eq!(
914            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
915            uniform_bytes
916        );
917
918        let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
919             qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
920             qqqqqqqqqqqqqqqqqqqqqqqqq";
921        let len_in_bytes = 0x80;
922        let uniform_bytes = hex::decode(
923            "ca1b56861482b16eae0f4a26212112362fcc2d76dcc80c93\
924             c4182ed66c5113fe41733ed68be2942a3487394317f3379856f482\
925             2a611735e50528a60e7ade8ec8c71670fec6661e2c59a09ed36386\
926             513221688b35dc47e3c3111ee8c67ff49579089d661caa29db1ef1\
927             0eb6eace575bf3dc9806e7c4016bd50f3c0e2a6481ee6d",
928        )
929        .unwrap();
930        assert_eq!(
931            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
932            uniform_bytes
933        );
934
935        let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
936             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
937             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
938             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
939             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
940             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
941             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
942             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
943             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
944             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
945        let len_in_bytes = 0x80;
946        let uniform_bytes = hex::decode(
947            "9d763a5ce58f65c91531b4100c7266d479a5d9777ba76169\
948             3d052acd37d149e7ac91c796a10b919cd74a591a1e38719fb91b72\
949             03e2af31eac3bff7ead2c195af7d88b8bc0a8adf3d1e90ab9bed6d\
950             dc2b7f655dd86c730bdeaea884e73741097142c92f0e3fc1811b69\
951             9ba593c7fbd81da288a29d423df831652e3a01a9374999",
952        )
953        .unwrap();
954        assert_eq!(
955            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
956            uniform_bytes
957        );
958    }
959
960    /// From <https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-12#appendix-K.5>
961    #[test]
962    fn expand_message_xof_works_for_draft12_testvectors_shake128_long_dst() {
963        let dst = b"QUUX-V01-CS02-with-expander-SHAKE128-long-DST-11111111\
964             111111111111111111111111111111111111111111111111111111\
965             111111111111111111111111111111111111111111111111111111\
966             111111111111111111111111111111111111111111111111111111\
967             1111111111111111111111111111111111111111";
968
969        let msg = b"";
970        let len_in_bytes = 0x20;
971        let uniform_bytes = hex::decode(
972            "827c6216330a122352312bccc0c8d6e7a146c5257a776dbd\
973             9ad9d75cd880fc53",
974        )
975        .unwrap();
976        assert_eq!(
977            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
978            uniform_bytes
979        );
980
981        let msg = b"abc";
982        let len_in_bytes = 0x20;
983        let uniform_bytes = hex::decode(
984            "690c8d82c7213b4282c6cb41c00e31ea1d3e2005f93ad19b\
985             bf6da40f15790c5c",
986        )
987        .unwrap();
988        assert_eq!(
989            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
990            uniform_bytes
991        );
992
993        let msg = b"abcdef0123456789";
994        let len_in_bytes = 0x20;
995        let uniform_bytes = hex::decode(
996            "979e3a15064afbbcf99f62cc09fa9c85028afcf3f825eb07\
997             11894dcfc2f57057",
998        )
999        .unwrap();
1000        assert_eq!(
1001            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
1002            uniform_bytes
1003        );
1004
1005        let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
1006             qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
1007             qqqqqqqqqqqqqqqqqqqqqqqqq";
1008        let len_in_bytes = 0x20;
1009        let uniform_bytes = hex::decode(
1010            "c5a9220962d9edc212c063f4f65b609755a1ed96e62f9db5\
1011             d1fd6adb5a8dc52b",
1012        )
1013        .unwrap();
1014        assert_eq!(
1015            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
1016            uniform_bytes
1017        );
1018
1019        let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1020             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1021             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1022             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1023             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1024             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1025             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1026             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1027             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1028             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
1029        let len_in_bytes = 0x20;
1030        let uniform_bytes = hex::decode(
1031            "f7b96a5901af5d78ce1d071d9c383cac66a1dfadb508300e\
1032             c6aeaea0d62d5d62",
1033        )
1034        .unwrap();
1035        assert_eq!(
1036            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
1037            uniform_bytes
1038        );
1039
1040        let msg = b"";
1041        let len_in_bytes = 0x80;
1042        let uniform_bytes = hex::decode(
1043            "3890dbab00a2830be398524b71c2713bbef5f4884ac2e6f0\
1044             70b092effdb19208c7df943dc5dcbaee3094a78c267ef276632ee2\
1045             c8ea0c05363c94b6348500fae4208345dd3475fe0c834c2beac7fa\
1046             7bc181692fb728c0a53d809fc8111495222ce0f38468b11becb15b\
1047             32060218e285c57a60162c2c8bb5b6bded13973cd41819",
1048        )
1049        .unwrap();
1050        assert_eq!(
1051            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
1052            uniform_bytes
1053        );
1054
1055        let msg = b"abc";
1056        let len_in_bytes = 0x80;
1057        let uniform_bytes = hex::decode(
1058            "41b7ffa7a301b5c1441495ebb9774e2a53dbbf4e54b9a1af\
1059             6a20fd41eafd69ef7b9418599c5545b1ee422f363642b01d4a5344\
1060             9313f68da3e49dddb9cd25b97465170537d45dcbdf92391b5bdff3\
1061             44db4bd06311a05bca7dcd360b6caec849c299133e5c9194f4e15e\
1062             3e23cfaab4003fab776f6ac0bfae9144c6e2e1c62e7d57",
1063        )
1064        .unwrap();
1065        assert_eq!(
1066            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
1067            uniform_bytes
1068        );
1069
1070        let msg = b"abcdef0123456789";
1071        let len_in_bytes = 0x80;
1072        let uniform_bytes = hex::decode(
1073            "55317e4a21318472cd2290c3082957e1242241d9e0d04f47\
1074             026f03401643131401071f01aa03038b2783e795bdfa8a3541c194\
1075             ad5de7cb9c225133e24af6c86e748deb52e560569bd54ef4dac034\
1076             65111a3a44b0ea490fb36777ff8ea9f1a8a3e8e0de3cf0880b4b2f\
1077             8dd37d3a85a8b82375aee4fa0e909f9763319b55778e71",
1078        )
1079        .unwrap();
1080        assert_eq!(
1081            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
1082            uniform_bytes
1083        );
1084
1085        let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
1086             qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
1087             qqqqqqqqqqqqqqqqqqqqqqqqq";
1088        let len_in_bytes = 0x80;
1089        let uniform_bytes = hex::decode(
1090            "19fdd2639f082e31c77717ac9bb032a22ff0958382b2dbb3\
1091             9020cdc78f0da43305414806abf9a561cb2d0067eb2f7bc544482f\
1092             75623438ed4b4e39dd9e6e2909dd858bd8f1d57cd0fce2d3150d90\
1093             aa67b4498bdf2df98c0100dd1a173436ba5d0df6be1defb0b2ce55\
1094             ccd2f4fc05eb7cb2c019c35d5398b85adc676da4238bc7",
1095        )
1096        .unwrap();
1097        assert_eq!(
1098            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
1099            uniform_bytes
1100        );
1101
1102        let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1103             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1104             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1105             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1106             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1107             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1108             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1109             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1110             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1111             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
1112        let len_in_bytes = 0x80;
1113        let uniform_bytes = hex::decode(
1114            "945373f0b3431a103333ba6a0a34f1efab2702efde41754c\
1115             4cb1d5216d5b0a92a67458d968562bde7fa6310a83f53dda138368\
1116             0a276a283438d58ceebfa7ab7ba72499d4a3eddc860595f63c93b1\
1117             c5e823ea41fc490d938398a26db28f61857698553e93f0574eb8c5\
1118             017bfed6249491f9976aaa8d23d9485339cc85ca329308",
1119        )
1120        .unwrap();
1121        assert_eq!(
1122            ExpandMsgXof::<Shake128>::init_expand(msg, dst, len_in_bytes).into_vec(),
1123            uniform_bytes
1124        );
1125    }
1126
1127    /// From <https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-12#appendix-K.6>
1128    #[test]
1129    fn expand_message_xof_works_for_draft12_testvectors_shake256() {
1130        let dst = b"QUUX-V01-CS02-with-expander-SHAKE256";
1131
1132        let msg = b"";
1133        let len_in_bytes = 0x20;
1134        let uniform_bytes = hex::decode(
1135            "2ffc05c48ed32b95d72e807f6eab9f7530dd1c2f013914c8\
1136             fed38c5ccc15ad76",
1137        )
1138        .unwrap();
1139        assert_eq!(
1140            ExpandMsgXof::<Shake256>::init_expand(msg, dst, len_in_bytes).into_vec(),
1141            uniform_bytes
1142        );
1143
1144        let msg = b"abc";
1145        let len_in_bytes = 0x20;
1146        let uniform_bytes = hex::decode(
1147            "b39e493867e2767216792abce1f2676c197c0692aed06156\
1148             0ead251821808e07",
1149        )
1150        .unwrap();
1151        assert_eq!(
1152            ExpandMsgXof::<Shake256>::init_expand(msg, dst, len_in_bytes).into_vec(),
1153            uniform_bytes
1154        );
1155
1156        let msg = b"abcdef0123456789";
1157        let len_in_bytes = 0x20;
1158        let uniform_bytes = hex::decode(
1159            "245389cf44a13f0e70af8665fe5337ec2dcd138890bb7901\
1160             c4ad9cfceb054b65",
1161        )
1162        .unwrap();
1163        assert_eq!(
1164            ExpandMsgXof::<Shake256>::init_expand(msg, dst, len_in_bytes).into_vec(),
1165            uniform_bytes
1166        );
1167
1168        let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
1169             qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
1170             qqqqqqqqqqqqqqqqqqqqqqqqq";
1171        let len_in_bytes = 0x20;
1172        let uniform_bytes = hex::decode(
1173            "719b3911821e6428a5ed9b8e600f2866bcf23c8f0515e52d\
1174             6c6c019a03f16f0e",
1175        )
1176        .unwrap();
1177        assert_eq!(
1178            ExpandMsgXof::<Shake256>::init_expand(msg, dst, len_in_bytes).into_vec(),
1179            uniform_bytes
1180        );
1181
1182        let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1183             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1184             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1185             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1186             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1187             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1188             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1189             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1190             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1191             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
1192        let len_in_bytes = 0x20;
1193        let uniform_bytes = hex::decode(
1194            "9181ead5220b1963f1b5951f35547a5ea86a820562287d6c\
1195             a4723633d17ccbbc",
1196        )
1197        .unwrap();
1198        assert_eq!(
1199            ExpandMsgXof::<Shake256>::init_expand(msg, dst, len_in_bytes).into_vec(),
1200            uniform_bytes
1201        );
1202
1203        let msg = b"";
1204        let len_in_bytes = 0x80;
1205        let uniform_bytes = hex::decode(
1206            "7a1361d2d7d82d79e035b8880c5a3c86c5afa719478c007d\
1207             96e6c88737a3f631dd74a2c88df79a4cb5e5d9f7504957c70d669e\
1208             c6bfedc31e01e2bacc4ff3fdf9b6a00b17cc18d9d72ace7d6b81c2\
1209             e481b4f73f34f9a7505dccbe8f5485f3d20c5409b0310093d5d649\
1210             2dea4e18aa6979c23c8ea5de01582e9689612afbb353df",
1211        )
1212        .unwrap();
1213        assert_eq!(
1214            ExpandMsgXof::<Shake256>::init_expand(msg, dst, len_in_bytes).into_vec(),
1215            uniform_bytes
1216        );
1217
1218        let msg = b"abc";
1219        let len_in_bytes = 0x80;
1220        let uniform_bytes = hex::decode(
1221            "a54303e6b172909783353ab05ef08dd435a558c3197db0c1\
1222             32134649708e0b9b4e34fb99b92a9e9e28fc1f1d8860d85897a8e0\
1223             21e6382f3eea10577f968ff6df6c45fe624ce65ca25932f679a42a\
1224             404bc3681efe03fcd45ef73bb3a8f79ba784f80f55ea8a3c367408\
1225             f30381299617f50c8cf8fbb21d0f1e1d70b0131a7b6fbe",
1226        )
1227        .unwrap();
1228        assert_eq!(
1229            ExpandMsgXof::<Shake256>::init_expand(msg, dst, len_in_bytes).into_vec(),
1230            uniform_bytes
1231        );
1232
1233        let msg = b"abcdef0123456789";
1234        let len_in_bytes = 0x80;
1235        let uniform_bytes = hex::decode(
1236            "e42e4d9538a189316e3154b821c1bafb390f78b2f010ea40\
1237             4e6ac063deb8c0852fcd412e098e231e43427bd2be1330bb47b403\
1238             9ad57b30ae1fc94e34993b162ff4d695e42d59d9777ea18d3848d9\
1239             d336c25d2acb93adcad009bcfb9cde12286df267ada283063de0bb\
1240             1505565b2eb6c90e31c48798ecdc71a71756a9110ff373",
1241        )
1242        .unwrap();
1243        assert_eq!(
1244            ExpandMsgXof::<Shake256>::init_expand(msg, dst, len_in_bytes).into_vec(),
1245            uniform_bytes
1246        );
1247
1248        let msg = b"q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
1249             qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
1250             qqqqqqqqqqqqqqqqqqqqqqqqq";
1251        let len_in_bytes = 0x80;
1252        let uniform_bytes = hex::decode(
1253            "4ac054dda0a38a65d0ecf7afd3c2812300027c8789655e47\
1254             aecf1ecc1a2426b17444c7482c99e5907afd9c25b991990490bb9c\
1255             686f43e79b4471a23a703d4b02f23c669737a886a7ec28bddb92c3\
1256             a98de63ebf878aa363a501a60055c048bea11840c4717beae7eee2\
1257             8c3cfa42857b3d130188571943a7bd747de831bd6444e0",
1258        )
1259        .unwrap();
1260        assert_eq!(
1261            ExpandMsgXof::<Shake256>::init_expand(msg, dst, len_in_bytes).into_vec(),
1262            uniform_bytes
1263        );
1264
1265        let msg = b"a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1266             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1267             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1268             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1269             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1270             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1271             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1272             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1273             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
1274             aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
1275        let len_in_bytes = 0x80;
1276        let uniform_bytes = hex::decode(
1277            "09afc76d51c2cccbc129c2315df66c2be7295a231203b8ab\
1278             2dd7f95c2772c68e500bc72e20c602abc9964663b7a03a389be128\
1279             c56971ce81001a0b875e7fd17822db9d69792ddf6a23a151bf4700\
1280             79c518279aef3e75611f8f828994a9988f4a8a256ddb8bae161e65\
1281             8d5a2a09bcfe839c6396dc06ee5c8ff3c22d3b1f9deb7e",
1282        )
1283        .unwrap();
1284        assert_eq!(
1285            ExpandMsgXof::<Shake256>::init_expand(msg, dst, len_in_bytes).into_vec(),
1286            uniform_bytes
1287        );
1288    }
1289}