1use sha2::{Digest as DigestImpl, Sha512 as Sha512Impl};
15
16use crate::constants::CRYPTO_HASH_SHA512_BYTES;
17use crate::types::*;
18
19pub type Digest = StackByteArray<CRYPTO_HASH_SHA512_BYTES>;
21
22pub struct Sha512 {
24 hasher: Sha512Impl,
25}
26
27impl Sha512 {
28 pub fn new() -> Self {
30 Self {
31 hasher: Sha512Impl::new(),
32 }
33 }
34
35 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 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 pub fn compute_to_vec<Input: Bytes + ?Sized>(input: &Input) -> Vec<u8> {
61 Self::compute(input)
62 }
63
64 pub fn update<Input: Bytes + ?Sized>(&mut self, input: &Input) {
66 self.hasher.update(input.as_slice())
67 }
68
69 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 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 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}