Skip to main content

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