1use 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
21pub type Digest = StackByteArray<CRYPTO_HASH_SHA512_BYTES>;
23
24pub struct Sha512 {
26 hasher: Sha512Impl,
27}
28
29impl Sha512 {
30 pub fn new() -> Self {
32 Self {
33 hasher: Sha512Impl::new(),
34 }
35 }
36
37 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 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 pub fn compute_to_vec<Input: Bytes + ?Sized>(input: &Input) -> Vec<u8> {
63 Self::compute(input)
64 }
65
66 pub fn update<Input: Bytes + ?Sized>(&mut self, input: &Input) {
68 self.hasher.update(input.as_slice())
69 }
70
71 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 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 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}