dryoc/
sha512.rs

1//! # SHA-512 hash algorithm
2//!
3//! Provides an implementation of the SHA-512 hash algorithm.
4//!
5//! ## Example
6//!
7//! ```
8//! use dryoc::sha512::Sha512;
9//!
10//! let mut state = Sha512::new();
11//! state.update(b"bytes");
12//! let hash = state.finalize_to_vec();
13//! ```
14use generic_array::GenericArray;
15use generic_array::typenum::U64;
16use sha2::{Digest as DigestImpl, Sha512 as Sha512Impl};
17
18use crate::constants::CRYPTO_HASH_SHA512_BYTES;
19use crate::types::*;
20
21/// Type alias for SHA512 digest, provided for convience.
22pub type Digest = StackByteArray<CRYPTO_HASH_SHA512_BYTES>;
23
24/// SHA-512 wrapper, provided for convience.
25pub struct Sha512 {
26    hasher: Sha512Impl,
27}
28
29impl Sha512 {
30    /// Returns a new SHA-512 hasher instance.
31    pub fn new() -> Self {
32        Self {
33            hasher: Sha512Impl::new(),
34        }
35    }
36
37    /// One-time interface to compute SHA-512 digest for `input`, copying result
38    /// into `output`.
39    pub fn compute_into_bytes<
40        Input: Bytes + ?Sized,
41        Output: MutByteArray<CRYPTO_HASH_SHA512_BYTES>,
42    >(
43        output: &mut Output,
44        input: &Input,
45    ) {
46        let mut hasher = Self::new();
47        hasher.update(input);
48        hasher.finalize_into_bytes(output)
49    }
50
51    /// One-time interface to compute SHA-512 digest for `input`.
52    pub fn compute<Input: Bytes + ?Sized, Output: NewByteArray<CRYPTO_HASH_SHA512_BYTES>>(
53        input: &Input,
54    ) -> Output {
55        let mut hasher = Self::new();
56        hasher.update(input);
57        hasher.finalize()
58    }
59
60    /// Wrapper around [`Sha512::compute`], returning a [`Vec`]. Provided for
61    /// convenience.
62    pub fn compute_to_vec<Input: Bytes + ?Sized>(input: &Input) -> Vec<u8> {
63        Self::compute(input)
64    }
65
66    /// Updates SHA-512 hash state with `input`.
67    pub fn update<Input: Bytes + ?Sized>(&mut self, input: &Input) {
68        self.hasher.update(input.as_slice())
69    }
70
71    /// Consumes hasher and return final computed hash.
72    pub fn finalize<Output: NewByteArray<CRYPTO_HASH_SHA512_BYTES>>(self) -> Output {
73        let mut hash = Output::new_byte_array();
74        self.finalize_into_bytes(&mut hash);
75        hash
76    }
77
78    /// Consumes hasher and writes final computed hash into `output`.
79    pub fn finalize_into_bytes<Output: MutByteArray<CRYPTO_HASH_SHA512_BYTES>>(
80        mut self,
81        output: &mut Output,
82    ) {
83        let arr = GenericArray::<_, U64>::from_mut_slice(output.as_mut_slice());
84        self.hasher.finalize_into_reset(arr);
85    }
86
87    /// Consumes hasher and returns final computed hash as a [`Vec`].
88    pub fn finalize_to_vec(self) -> Vec<u8> {
89        self.finalize()
90    }
91}
92
93impl Default for Sha512 {
94    fn default() -> Self {
95        Self::new()
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use super::*;
102
103    #[test]
104    fn test_sha512() {
105        use sodiumoxide::crypto::hash;
106
107        use crate::rng::randombytes_buf;
108
109        let mut their_state = hash::State::new();
110        let mut our_state = Sha512::new();
111
112        for _ in 0..10 {
113            let r = randombytes_buf(64);
114            their_state.update(&r);
115            our_state.update(&r);
116        }
117
118        let their_digest = their_state.finalize();
119        let our_digest = our_state.finalize_to_vec();
120
121        assert_eq!(their_digest.as_ref(), our_digest);
122    }
123}