crypt_io/hash/
sha2_impl.rs1use sha2::Digest;
12use sha2::{Sha256, Sha512};
13
14use super::{SHA256_OUTPUT_LEN, SHA512_OUTPUT_LEN};
15
16#[must_use]
28pub fn sha256(data: &[u8]) -> [u8; SHA256_OUTPUT_LEN] {
29 let mut hasher = Sha256::new();
30 hasher.update(data);
31 hasher.finalize().into()
32}
33
34#[must_use]
46pub fn sha512(data: &[u8]) -> [u8; SHA512_OUTPUT_LEN] {
47 let mut hasher = Sha512::new();
48 hasher.update(data);
49 hasher.finalize().into()
50}
51
52#[derive(Debug, Clone, Default)]
68pub struct Sha256Hasher {
69 inner: Sha256,
70}
71
72impl Sha256Hasher {
73 #[must_use]
75 pub fn new() -> Self {
76 Self {
77 inner: Sha256::new(),
78 }
79 }
80
81 pub fn update(&mut self, data: &[u8]) -> &mut Self {
84 self.inner.update(data);
85 self
86 }
87
88 #[must_use]
90 pub fn finalize(self) -> [u8; SHA256_OUTPUT_LEN] {
91 self.inner.finalize().into()
92 }
93}
94
95#[derive(Debug, Clone, Default)]
111pub struct Sha512Hasher {
112 inner: Sha512,
113}
114
115impl Sha512Hasher {
116 #[must_use]
118 pub fn new() -> Self {
119 Self {
120 inner: Sha512::new(),
121 }
122 }
123
124 pub fn update(&mut self, data: &[u8]) -> &mut Self {
127 self.inner.update(data);
128 self
129 }
130
131 #[must_use]
133 pub fn finalize(self) -> [u8; SHA512_OUTPUT_LEN] {
134 self.inner.finalize().into()
135 }
136}
137
138#[cfg(test)]
139#[allow(clippy::unwrap_used, clippy::expect_used, unused_results)]
140mod tests {
141 use super::*;
142
143 fn hex_to_bytes(s: &str) -> alloc::vec::Vec<u8> {
144 hex::decode(s).expect("valid hex")
145 }
146
147 #[test]
151 fn sha256_kat_abc() {
152 let expected =
153 hex_to_bytes("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
154 assert_eq!(&sha256(b"abc")[..], &expected[..]);
155 }
156
157 #[test]
160 fn sha256_kat_two_block() {
161 let input = b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
162 let expected =
163 hex_to_bytes("248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
164 assert_eq!(&sha256(input)[..], &expected[..]);
165 }
166
167 #[test]
169 fn sha256_kat_empty() {
170 let expected =
171 hex_to_bytes("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
172 assert_eq!(&sha256(b"")[..], &expected[..]);
173 }
174
175 #[test]
179 fn sha512_kat_abc() {
180 let expected = hex_to_bytes(
181 "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a\
182 2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
183 );
184 assert_eq!(&sha512(b"abc")[..], &expected[..]);
185 }
186
187 #[test]
190 fn sha512_kat_two_block() {
191 let input = b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
192 let expected = hex_to_bytes(
193 "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018\
194 501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909",
195 );
196 assert_eq!(&sha512(input)[..], &expected[..]);
197 }
198
199 #[test]
200 fn sha512_kat_empty() {
201 let expected = hex_to_bytes(
202 "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce\
203 47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
204 );
205 assert_eq!(&sha512(b"")[..], &expected[..]);
206 }
207
208 #[test]
211 fn sha256_streaming_equals_one_shot() {
212 let data = b"the quick brown fox jumps over the lazy dog";
213 let one_shot = sha256(data);
214 let mut h = Sha256Hasher::new();
215 h.update(&data[..10]);
216 h.update(&data[10..25]);
217 h.update(&data[25..]);
218 assert_eq!(h.finalize(), one_shot);
219 }
220
221 #[test]
222 fn sha512_streaming_equals_one_shot() {
223 let data = b"the quick brown fox jumps over the lazy dog";
224 let one_shot = sha512(data);
225 let mut h = Sha512Hasher::new();
226 h.update(&data[..10]);
227 h.update(&data[10..25]);
228 h.update(&data[25..]);
229 assert_eq!(h.finalize(), one_shot);
230 }
231
232 #[test]
233 fn sha256_streaming_chain_returns_self() {
234 let mut h = Sha256Hasher::new();
235 h.update(b"chain").update(b"-friendly");
236 assert_eq!(h.finalize(), sha256(b"chain-friendly"));
237 }
238
239 #[test]
240 fn sha512_streaming_chain_returns_self() {
241 let mut h = Sha512Hasher::new();
242 h.update(b"chain").update(b"-friendly");
243 assert_eq!(h.finalize(), sha512(b"chain-friendly"));
244 }
245
246 #[test]
247 fn sha256_empty_input_through_streaming() {
248 let h = Sha256Hasher::new();
249 assert_eq!(h.finalize(), sha256(b""));
250 }
251
252 #[test]
253 fn sha512_empty_input_through_streaming() {
254 let h = Sha512Hasher::new();
255 assert_eq!(h.finalize(), sha512(b""));
256 }
257}