Skip to main content

blake2b_simd/
lib.rs

1//! [![GitHub](https://img.shields.io/github/tag/oconnor663/blake2_simd.svg?label=GitHub)](https://github.com/oconnor663/blake2_simd) [![crates.io](https://img.shields.io/crates/v/blake2b_simd.svg)](https://crates.io/crates/blake2b_simd) [![Actions Status](https://github.com/oconnor663/blake2_simd/workflows/tests/badge.svg)](https://github.com/oconnor663/blake2_simd/actions)
2//!
3//! An implementation of the BLAKE2b and BLAKE2bp hash functions. See also
4//! [`blake2s_simd`](https://docs.rs/blake2s_simd).
5//!
6//! This crate includes:
7//!
8//! - 100% stable Rust.
9//! - SIMD implementations based on Samuel Neves' [`blake2-avx2`](https://github.com/sneves/blake2-avx2).
10//!   These are very fast. For benchmarks, see [the Performance section of the
11//!   README](https://github.com/oconnor663/blake2_simd#performance).
12//! - Portable, safe implementations for other platforms.
13//! - Dynamic CPU feature detection. Binaries include multiple implementations by default and
14//!   choose the fastest one the processor supports at runtime.
15//! - All the features from the [the BLAKE2 spec](https://blake2.net/blake2.pdf), like adjustable
16//!   length, keying, and associated data for tree hashing.
17//! - `no_std` support. The `std` Cargo feature is on by default, for CPU feature detection and
18//!   for implementing `std::io::Write`.
19//! - Support for computing multiple BLAKE2b hashes in parallel, matching the efficiency of
20//!   BLAKE2bp. See the [`many`](many/index.html) module.
21//!
22//! # Example
23//!
24//! ```
25//! use blake2b_simd::{blake2b, Params};
26//!
27//! let expected = "ca002330e69d3e6b84a46a56a6533fd79d51d97a3bb7cad6c2ff43b354185d6d\
28//!                 c1e723fb3db4ae0737e120378424c714bb982d9dc5bbd7a0ab318240ddd18f8d";
29//! let hash = blake2b(b"foo");
30//! assert_eq!(expected, &hash.to_hex());
31//!
32//! let hash = Params::new()
33//!     .hash_length(16)
34//!     .key(b"The Magic Words are Squeamish Ossifrage")
35//!     .personal(b"L. P. Waterhouse")
36//!     .to_state()
37//!     .update(b"foo")
38//!     .update(b"bar")
39//!     .update(b"baz")
40//!     .finalize();
41//! assert_eq!("ee8ff4e9be887297cf79348dc35dab56", &hash.to_hex());
42//! ```
43
44#![cfg_attr(not(feature = "std"), no_std)]
45
46use core::cmp;
47use core::fmt;
48use core::mem::size_of;
49
50#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
51mod avx2;
52mod portable;
53#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
54mod sse41;
55
56pub mod blake2bp;
57mod guts;
58pub mod many;
59
60#[cfg(test)]
61mod test;
62
63type Word = u64;
64type Count = u128;
65
66/// The max hash length.
67pub const OUTBYTES: usize = 8 * size_of::<Word>();
68/// The max key length.
69pub const KEYBYTES: usize = 8 * size_of::<Word>();
70/// The max salt length.
71pub const SALTBYTES: usize = 2 * size_of::<Word>();
72/// The max personalization length.
73pub const PERSONALBYTES: usize = 2 * size_of::<Word>();
74/// The number input bytes passed to each call to the compression function. Small benchmarks need
75/// to use an even multiple of `BLOCKBYTES`, or else their apparent throughput will be low.
76pub const BLOCKBYTES: usize = 16 * size_of::<Word>();
77
78const IV: [Word; 8] = [
79    0x6A09E667F3BCC908,
80    0xBB67AE8584CAA73B,
81    0x3C6EF372FE94F82B,
82    0xA54FF53A5F1D36F1,
83    0x510E527FADE682D1,
84    0x9B05688C2B3E6C1F,
85    0x1F83D9ABFB41BD6B,
86    0x5BE0CD19137E2179,
87];
88
89const SIGMA: [[u8; 16]; 12] = [
90    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
91    [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
92    [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4],
93    [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8],
94    [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13],
95    [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9],
96    [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11],
97    [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10],
98    [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5],
99    [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0],
100    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
101    [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
102];
103
104/// Compute the BLAKE2b hash of a slice of bytes all at once, using default
105/// parameters.
106///
107/// # Example
108///
109/// ```
110/// # use blake2b_simd::{blake2b, Params};
111/// let expected = "ca002330e69d3e6b84a46a56a6533fd79d51d97a3bb7cad6c2ff43b354185d6d\
112///                 c1e723fb3db4ae0737e120378424c714bb982d9dc5bbd7a0ab318240ddd18f8d";
113/// let hash = blake2b(b"foo");
114/// assert_eq!(expected, &hash.to_hex());
115/// ```
116pub fn blake2b(input: &[u8]) -> Hash {
117    Params::new().hash(input)
118}
119
120/// A parameter builder that exposes all the non-default BLAKE2 features.
121///
122/// Apart from `hash_length`, which controls the length of the final `Hash`,
123/// all of these parameters are just associated data that gets mixed with the
124/// input. For more details, see [the BLAKE2 spec](https://blake2.net/blake2.pdf).
125///
126/// Several of the parameters have a valid range defined in the spec and
127/// documented below. Trying to set an invalid parameter will panic.
128///
129/// # Example
130///
131/// ```
132/// # use blake2b_simd::Params;
133/// // Create a Params object with a secret key and a non-default length.
134/// let mut params = Params::new();
135/// params.key(b"my secret key");
136/// params.hash_length(16);
137///
138/// // Use those params to hash an input all at once.
139/// let hash = params.hash(b"my input");
140///
141/// // Or use those params to build an incremental State.
142/// let mut state = params.to_state();
143/// ```
144#[derive(Clone)]
145pub struct Params {
146    hash_length: u8,
147    key_length: u8,
148    key_block: [u8; BLOCKBYTES],
149    salt: [u8; SALTBYTES],
150    personal: [u8; PERSONALBYTES],
151    fanout: u8,
152    max_depth: u8,
153    max_leaf_length: u32,
154    node_offset: u64,
155    node_depth: u8,
156    inner_hash_length: u8,
157    last_node: guts::LastNode,
158    implementation: guts::Implementation,
159}
160
161impl Params {
162    /// Equivalent to `Params::default()`.
163    #[inline]
164    pub fn new() -> Self {
165        Self {
166            hash_length: OUTBYTES as u8,
167            key_length: 0,
168            key_block: [0; BLOCKBYTES],
169            salt: [0; SALTBYTES],
170            personal: [0; PERSONALBYTES],
171            // NOTE: fanout and max_depth don't default to zero!
172            fanout: 1,
173            max_depth: 1,
174            max_leaf_length: 0,
175            node_offset: 0,
176            node_depth: 0,
177            inner_hash_length: 0,
178            last_node: guts::LastNode::No,
179            implementation: guts::Implementation::detect(),
180        }
181    }
182
183    #[inline(always)]
184    fn to_words(&self) -> [Word; 8] {
185        let salt_left: &[u8; SALTBYTES / 2] = (&self.salt[..SALTBYTES / 2]).try_into().unwrap();
186        let salt_right: &[u8; SALTBYTES / 2] = (&self.salt[SALTBYTES / 2..]).try_into().unwrap();
187        let personal_left: &[u8; PERSONALBYTES / 2] =
188            (&self.personal[..PERSONALBYTES / 2]).try_into().unwrap();
189        let personal_right: &[u8; PERSONALBYTES / 2] =
190            (&self.personal[PERSONALBYTES / 2..]).try_into().unwrap();
191        [
192            IV[0]
193                ^ self.hash_length as u64
194                ^ (self.key_length as u64) << 8
195                ^ (self.fanout as u64) << 16
196                ^ (self.max_depth as u64) << 24
197                ^ (self.max_leaf_length as u64) << 32,
198            IV[1] ^ self.node_offset,
199            IV[2] ^ self.node_depth as u64 ^ (self.inner_hash_length as u64) << 8,
200            IV[3],
201            IV[4] ^ Word::from_le_bytes(*salt_left),
202            IV[5] ^ Word::from_le_bytes(*salt_right),
203            IV[6] ^ Word::from_le_bytes(*personal_left),
204            IV[7] ^ Word::from_le_bytes(*personal_right),
205        ]
206    }
207
208    /// Hash an input all at once with these parameters.
209    #[inline]
210    pub fn hash(&self, input: &[u8]) -> Hash {
211        // If there's a key, just fall back to using the State.
212        if self.key_length > 0 {
213            return self.to_state().update(input).finalize();
214        }
215        let mut words = self.to_words();
216        self.implementation.compress1_loop(
217            input,
218            &mut words,
219            0,
220            self.last_node,
221            guts::Finalize::Yes,
222            guts::Stride::Serial,
223        );
224        Hash {
225            bytes: state_words_to_bytes(&words),
226            len: self.hash_length,
227        }
228    }
229
230    /// Construct a `State` object based on these parameters, for hashing input
231    /// incrementally.
232    pub fn to_state(&self) -> State {
233        State::with_params(self)
234    }
235
236    /// Set the length of the final hash in bytes, from 1 to `OUTBYTES` (64). Apart from
237    /// controlling the length of the final `Hash`, this is also associated data, and changing it
238    /// will result in a totally different hash.
239    #[inline]
240    pub fn hash_length(&mut self, length: usize) -> &mut Self {
241        assert!(
242            1 <= length && length <= OUTBYTES,
243            "Bad hash length: {}",
244            length
245        );
246        self.hash_length = length as u8;
247        self
248    }
249
250    /// Use a secret key, so that BLAKE2 acts as a MAC. The maximum key length is `KEYBYTES` (64).
251    /// An empty key is equivalent to having no key at all.
252    #[inline]
253    pub fn key(&mut self, key: &[u8]) -> &mut Self {
254        assert!(key.len() <= KEYBYTES, "Bad key length: {}", key.len());
255        self.key_length = key.len() as u8;
256        self.key_block = [0; BLOCKBYTES];
257        self.key_block[..key.len()].copy_from_slice(key);
258        self
259    }
260
261    /// At most `SALTBYTES` (16). Shorter salts are padded with null bytes. An empty salt is
262    /// equivalent to having no salt at all.
263    #[inline]
264    pub fn salt(&mut self, salt: &[u8]) -> &mut Self {
265        assert!(salt.len() <= SALTBYTES, "Bad salt length: {}", salt.len());
266        self.salt = [0; SALTBYTES];
267        self.salt[..salt.len()].copy_from_slice(salt);
268        self
269    }
270
271    /// At most `PERSONALBYTES` (16). Shorter personalizations are padded with null bytes. An empty
272    /// personalization is equivalent to having no personalization at all.
273    #[inline]
274    pub fn personal(&mut self, personalization: &[u8]) -> &mut Self {
275        assert!(
276            personalization.len() <= PERSONALBYTES,
277            "Bad personalization length: {}",
278            personalization.len()
279        );
280        self.personal = [0; PERSONALBYTES];
281        self.personal[..personalization.len()].copy_from_slice(personalization);
282        self
283    }
284
285    /// From 0 (meaning unlimited) to 255. The default is 1 (meaning sequential).
286    #[inline]
287    pub fn fanout(&mut self, fanout: u8) -> &mut Self {
288        self.fanout = fanout;
289        self
290    }
291
292    /// From 0 (meaning BLAKE2X B2 hashes), through 1 (the default, meaning sequential) to 255 (meaning unlimited).
293    #[inline]
294    pub fn max_depth(&mut self, depth: u8) -> &mut Self {
295        self.max_depth = depth;
296        self
297    }
298
299    /// From 0 (the default, meaning unlimited or sequential) to `2^32 - 1`.
300    #[inline]
301    pub fn max_leaf_length(&mut self, length: u32) -> &mut Self {
302        self.max_leaf_length = length;
303        self
304    }
305
306    /// From 0 (the default, meaning first, leftmost, leaf, or sequential) to `2^64 - 1`.
307    #[inline]
308    pub fn node_offset(&mut self, offset: u64) -> &mut Self {
309        self.node_offset = offset;
310        self
311    }
312
313    /// From 0 (the default, meaning leaf or sequential) to 255.
314    #[inline]
315    pub fn node_depth(&mut self, depth: u8) -> &mut Self {
316        self.node_depth = depth;
317        self
318    }
319
320    /// From 0 (the default, meaning sequential) to `OUTBYTES` (64).
321    #[inline]
322    pub fn inner_hash_length(&mut self, length: usize) -> &mut Self {
323        assert!(length <= OUTBYTES, "Bad inner hash length: {}", length);
324        self.inner_hash_length = length as u8;
325        self
326    }
327
328    /// Indicates the rightmost node in a row. This can also be changed on the
329    /// `State` object, potentially after hashing has begun. See
330    /// [`State::set_last_node`].
331    ///
332    /// [`State::set_last_node`]: struct.State.html#method.set_last_node
333    #[inline]
334    pub fn last_node(&mut self, last_node: bool) -> &mut Self {
335        self.last_node = if last_node {
336            guts::LastNode::Yes
337        } else {
338            guts::LastNode::No
339        };
340        self
341    }
342}
343
344impl Default for Params {
345    fn default() -> Self {
346        Self::new()
347    }
348}
349
350impl fmt::Debug for Params {
351    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
352        write!(
353            f,
354            "Params {{ hash_length: {}, key_length: {}, salt: {:?}, personal: {:?}, fanout: {}, \
355             max_depth: {}, max_leaf_length: {}, node_offset: {}, node_depth: {}, \
356             inner_hash_length: {}, last_node: {} }}",
357            self.hash_length,
358            // NB: Don't print the key itself. Debug shouldn't leak secrets.
359            self.key_length,
360            &self.salt,
361            &self.personal,
362            self.fanout,
363            self.max_depth,
364            self.max_leaf_length,
365            self.node_offset,
366            self.node_depth,
367            self.inner_hash_length,
368            self.last_node.yes(),
369        )
370    }
371}
372
373/// An incremental hasher for BLAKE2b.
374///
375/// To construct a `State` with non-default parameters, see `Params::to_state`.
376///
377/// # Example
378///
379/// ```
380/// use blake2b_simd::{State, blake2b};
381///
382/// let mut state = blake2b_simd::State::new();
383///
384/// state.update(b"foo");
385/// assert_eq!(blake2b(b"foo"), state.finalize());
386///
387/// state.update(b"bar");
388/// assert_eq!(blake2b(b"foobar"), state.finalize());
389/// ```
390#[derive(Clone)]
391pub struct State {
392    words: [Word; 8],
393    count: Count,
394    buf: [u8; BLOCKBYTES],
395    buflen: u8,
396    last_node: guts::LastNode,
397    hash_length: u8,
398    implementation: guts::Implementation,
399    is_keyed: bool,
400}
401
402impl State {
403    /// Equivalent to `State::default()` or `Params::default().to_state()`.
404    pub fn new() -> Self {
405        Self::with_params(&Params::default())
406    }
407
408    fn with_params(params: &Params) -> Self {
409        let mut state = Self {
410            words: params.to_words(),
411            count: 0,
412            buf: [0; BLOCKBYTES],
413            buflen: 0,
414            last_node: params.last_node,
415            hash_length: params.hash_length,
416            implementation: params.implementation,
417            is_keyed: params.key_length > 0,
418        };
419        if state.is_keyed {
420            state.buf = params.key_block;
421            state.buflen = state.buf.len() as u8;
422        }
423        state
424    }
425
426    fn fill_buf(&mut self, input: &mut &[u8]) {
427        let take = cmp::min(BLOCKBYTES - self.buflen as usize, input.len());
428        self.buf[self.buflen as usize..self.buflen as usize + take].copy_from_slice(&input[..take]);
429        self.buflen += take as u8;
430        *input = &input[take..];
431    }
432
433    // If the state already has some input in its buffer, try to fill the buffer and perform a
434    // compression. However, only do the compression if there's more input coming, otherwise it
435    // will give the wrong hash it the caller finalizes immediately after.
436    fn compress_buffer_if_possible(&mut self, input: &mut &[u8]) {
437        if self.buflen > 0 {
438            self.fill_buf(input);
439            if !input.is_empty() {
440                self.implementation.compress1_loop(
441                    &self.buf,
442                    &mut self.words,
443                    self.count,
444                    self.last_node,
445                    guts::Finalize::No,
446                    guts::Stride::Serial,
447                );
448                self.count = self.count.wrapping_add(BLOCKBYTES as Count);
449                self.buflen = 0;
450            }
451        }
452    }
453
454    /// Add input to the hash. You can call `update` any number of times.
455    pub fn update(&mut self, mut input: &[u8]) -> &mut Self {
456        // If we have a partial buffer, try to complete it.
457        self.compress_buffer_if_possible(&mut input);
458        // While there's more than a block of input left (which also means we cleared the buffer
459        // above), compress blocks directly without copying.
460        let mut end = input.len().saturating_sub(1);
461        end -= end % BLOCKBYTES;
462        if end > 0 {
463            self.implementation.compress1_loop(
464                &input[..end],
465                &mut self.words,
466                self.count,
467                self.last_node,
468                guts::Finalize::No,
469                guts::Stride::Serial,
470            );
471            self.count = self.count.wrapping_add(end as Count);
472            input = &input[end..];
473        }
474        // Buffer any remaining input, to be either compressed or finalized in a subsequent call.
475        // Note that this represents some copying overhead, which in theory we could avoid in
476        // all-at-once setting. A function hardcoded for exactly BLOCKSIZE input bytes is about 10%
477        // faster than using this implementation for the same input.
478        self.fill_buf(&mut input);
479        self
480    }
481
482    /// Finalize the state and return a `Hash`. This method is idempotent, and calling it multiple
483    /// times will give the same result. It's also possible to `update` with more input in between.
484    pub fn finalize(&self) -> Hash {
485        let mut words_copy = self.words;
486        self.implementation.compress1_loop(
487            &self.buf[..self.buflen as usize],
488            &mut words_copy,
489            self.count,
490            self.last_node,
491            guts::Finalize::Yes,
492            guts::Stride::Serial,
493        );
494        Hash {
495            bytes: state_words_to_bytes(&words_copy),
496            len: self.hash_length,
497        }
498    }
499
500    /// Set a flag indicating that this is the last node of its level in a tree hash. This is
501    /// equivalent to [`Params::last_node`], except that it can be set at any time before calling
502    /// `finalize`. That allows callers to begin hashing a node without knowing ahead of time
503    /// whether it's the last in its level. For more details about the intended use of this flag
504    /// [the BLAKE2 spec].
505    ///
506    /// [`Params::last_node`]: struct.Params.html#method.last_node
507    /// [the BLAKE2 spec]: https://blake2.net/blake2.pdf
508    pub fn set_last_node(&mut self, last_node: bool) -> &mut Self {
509        self.last_node = if last_node {
510            guts::LastNode::Yes
511        } else {
512            guts::LastNode::No
513        };
514        self
515    }
516
517    /// Return the total number of bytes input so far.
518    ///
519    /// Note that `count` doesn't include the bytes of the key block, if any.
520    /// It's exactly the total number of input bytes fed to `update`.
521    pub fn count(&self) -> Count {
522        let mut ret = self.count.wrapping_add(self.buflen as Count);
523        if self.is_keyed {
524            ret -= BLOCKBYTES as Count;
525        }
526        ret
527    }
528}
529
530#[inline(always)]
531fn state_words_to_bytes(state_words: &[Word; 8]) -> [u8; OUTBYTES] {
532    let mut bytes = [0; OUTBYTES];
533    {
534        const W: usize = size_of::<Word>();
535        *<&mut [u8; W]>::try_from(&mut bytes[0 * W..][..W]).unwrap() = state_words[0].to_le_bytes();
536        *<&mut [u8; W]>::try_from(&mut bytes[1 * W..][..W]).unwrap() = state_words[1].to_le_bytes();
537        *<&mut [u8; W]>::try_from(&mut bytes[2 * W..][..W]).unwrap() = state_words[2].to_le_bytes();
538        *<&mut [u8; W]>::try_from(&mut bytes[3 * W..][..W]).unwrap() = state_words[3].to_le_bytes();
539        *<&mut [u8; W]>::try_from(&mut bytes[4 * W..][..W]).unwrap() = state_words[4].to_le_bytes();
540        *<&mut [u8; W]>::try_from(&mut bytes[5 * W..][..W]).unwrap() = state_words[5].to_le_bytes();
541        *<&mut [u8; W]>::try_from(&mut bytes[6 * W..][..W]).unwrap() = state_words[6].to_le_bytes();
542        *<&mut [u8; W]>::try_from(&mut bytes[7 * W..][..W]).unwrap() = state_words[7].to_le_bytes();
543    }
544    bytes
545}
546
547#[cfg(feature = "std")]
548impl std::io::Write for State {
549    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
550        self.update(buf);
551        Ok(buf.len())
552    }
553
554    fn flush(&mut self) -> std::io::Result<()> {
555        Ok(())
556    }
557}
558
559impl fmt::Debug for State {
560    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
561        // NB: Don't print the words. Leaking them would allow length extension.
562        write!(
563            f,
564            "State {{ count: {}, hash_length: {}, last_node: {} }}",
565            self.count(),
566            self.hash_length,
567            self.last_node.yes(),
568        )
569    }
570}
571
572impl Default for State {
573    fn default() -> Self {
574        Self::with_params(&Params::default())
575    }
576}
577
578type HexString = arrayvec::ArrayString<{ 2 * OUTBYTES }>;
579
580/// A finalized BLAKE2 hash, with constant-time equality.
581#[derive(Clone, Copy)]
582pub struct Hash {
583    bytes: [u8; OUTBYTES],
584    len: u8,
585}
586
587impl Hash {
588    /// Convert the hash to a byte slice. Note that if you're using BLAKE2 as a MAC, you need
589    /// constant time equality, which `&[u8]` doesn't provide.
590    pub fn as_bytes(&self) -> &[u8] {
591        &self.bytes[..self.len as usize]
592    }
593
594    /// Convert the hash to a byte array. Note that if you're using BLAKE2 as a
595    /// MAC, you need constant time equality, which arrays don't provide. This
596    /// panics in debug mode if the length of the hash isn't `OUTBYTES`.
597    #[inline]
598    pub fn as_array(&self) -> &[u8; OUTBYTES] {
599        debug_assert_eq!(self.len as usize, OUTBYTES);
600        &self.bytes
601    }
602
603    /// Convert the hash to a lowercase hexadecimal
604    /// [`ArrayString`](https://docs.rs/arrayvec/0.7/arrayvec/struct.ArrayString.html).
605    pub fn to_hex(&self) -> HexString {
606        bytes_to_hex(self.as_bytes())
607    }
608}
609
610fn bytes_to_hex(bytes: &[u8]) -> HexString {
611    let mut s = arrayvec::ArrayString::new();
612    let table = b"0123456789abcdef";
613    for &b in bytes {
614        s.push(table[(b >> 4) as usize] as char);
615        s.push(table[(b & 0xf) as usize] as char);
616    }
617    s
618}
619
620impl From<[u8; OUTBYTES]> for Hash {
621    fn from(bytes: [u8; OUTBYTES]) -> Self {
622        Self {
623            bytes,
624            len: OUTBYTES as u8,
625        }
626    }
627}
628
629impl From<&[u8; OUTBYTES]> for Hash {
630    fn from(bytes: &[u8; OUTBYTES]) -> Self {
631        Self::from(*bytes)
632    }
633}
634
635/// This implementation is constant time, if the two hashes are the same length.
636impl PartialEq for Hash {
637    fn eq(&self, other: &Hash) -> bool {
638        constant_time_eq::constant_time_eq(&self.as_bytes(), &other.as_bytes())
639    }
640}
641
642/// This implementation is constant time, if the slice is the same length as the hash.
643impl PartialEq<[u8]> for Hash {
644    fn eq(&self, other: &[u8]) -> bool {
645        constant_time_eq::constant_time_eq(&self.as_bytes(), other)
646    }
647}
648
649impl Eq for Hash {}
650
651impl AsRef<[u8]> for Hash {
652    fn as_ref(&self) -> &[u8] {
653        self.as_bytes()
654    }
655}
656
657impl fmt::Debug for Hash {
658    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
659        write!(f, "Hash(0x{})", self.to_hex())
660    }
661}
662
663// Paint a byte pattern that won't repeat, so that we don't accidentally miss
664// buffer offset bugs. This is the same as what Bao uses in its tests.
665#[cfg(test)]
666fn paint_test_input(buf: &mut [u8]) {
667    let mut offset = 0;
668    let mut counter: u32 = 1;
669    while offset < buf.len() {
670        let bytes = counter.to_le_bytes();
671        let take = cmp::min(bytes.len(), buf.len() - offset);
672        buf[offset..][..take].copy_from_slice(&bytes[..take]);
673        counter += 1;
674        offset += take;
675    }
676}
677
678// This module is pub for internal benchmarks only. Please don't use it.
679#[doc(hidden)]
680pub mod benchmarks {
681    use super::*;
682
683    pub fn force_portable(params: &mut Params) {
684        params.implementation = guts::Implementation::portable();
685    }
686
687    pub fn force_portable_blake2bp(params: &mut blake2bp::Params) {
688        blake2bp::force_portable(params);
689    }
690}