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