1use core::ops::Index;
11use core::slice::SliceIndex;
12use core::str;
13
14use crate::{sha512, FromSliceError};
15
16crate::internal_macros::hash_type! {
17 256,
18 false,
19 "Output of the SHA512/256 hash function.\n\nSHA512/256 is a hash function that uses the sha512 algorithm but it truncates the output to 256 bits. It has different initial constants than sha512 so it produces an entirely different hash compared to sha512. More information at <https://eprint.iacr.org/2010/548.pdf>."
20}
21
22fn from_engine(e: HashEngine) -> Hash {
23 let mut ret = [0; 32];
24 ret.copy_from_slice(&sha512::from_engine(e.0)[..32]);
25 Hash(ret)
26}
27
28#[derive(Clone)]
35pub struct HashEngine(sha512::HashEngine);
36
37impl Default for HashEngine {
38 #[rustfmt::skip]
39 fn default() -> Self {
40 HashEngine(sha512::HashEngine::sha512_256())
41 }
42}
43
44impl crate::HashEngine for HashEngine {
45 type MidState = [u8; 64];
46
47 fn midstate(&self) -> [u8; 64] { self.0.midstate() }
48
49 const BLOCK_SIZE: usize = sha512::BLOCK_SIZE;
50
51 fn n_bytes_hashed(&self) -> usize { self.0.n_bytes_hashed() }
52
53 fn input(&mut self, inp: &[u8]) { self.0.input(inp); }
54}
55
56#[cfg(test)]
57mod tests {
58 #[test]
59 #[cfg(feature = "alloc")]
60 fn test() {
61 use crate::{sha512_256, Hash, HashEngine};
62
63 #[derive(Clone)]
64 struct Test {
65 input: &'static str,
66 output: Vec<u8>,
67 output_str: &'static str,
68 }
69
70 #[rustfmt::skip]
71 let tests = vec![
72 Test {
74 input: "",
75 output: vec![
76 0xc6, 0x72, 0xb8, 0xd1, 0xef, 0x56, 0xed, 0x28,
77 0xab, 0x87, 0xc3, 0x62, 0x2c, 0x51, 0x14, 0x06,
78 0x9b, 0xdd, 0x3a, 0xd7, 0xb8, 0xf9, 0x73, 0x74,
79 0x98, 0xd0, 0xc0, 0x1e, 0xce, 0xf0, 0x96, 0x7a,
80 ],
81 output_str: "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a"
82 },
83 Test {
84 input: "abcdef",
85 output: vec![
86 0xe4, 0xfd, 0xcb, 0x11, 0xd1, 0xac, 0x14, 0xe6,
87 0x98, 0x74, 0x3a, 0xcd, 0x88, 0x05, 0x17, 0x4c,
88 0xea, 0x5d, 0xdc, 0x0d, 0x31, 0x2e, 0x3e, 0x47,
89 0xf6, 0x37, 0x20, 0x32, 0x57, 0x1b, 0xad, 0x84,
90 ],
91 output_str: "e4fdcb11d1ac14e698743acd8805174cea5ddc0d312e3e47f6372032571bad84",
92 },
93 Test {
94 input: "Discard medicine more than two years old.",
95 output: vec![
96 0x69, 0x0c, 0x8a, 0xd3, 0x91, 0x6c, 0xef, 0xd3,
97 0xad, 0x29, 0x22, 0x6d, 0x98, 0x75, 0x96, 0x5e,
98 0x3e, 0xe9, 0xec, 0x0d, 0x44, 0x82, 0xea, 0xcc,
99 0x24, 0x8f, 0x2f, 0xf4, 0xaa, 0x0d, 0x8e, 0x5b,
100 ],
101 output_str: "690c8ad3916cefd3ad29226d9875965e3ee9ec0d4482eacc248f2ff4aa0d8e5b",
102 },
103 Test {
104 input: "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977",
105 output: vec![
106 0xb5, 0xba, 0xf7, 0x47, 0xc3, 0x07, 0xf9, 0x88,
107 0x49, 0xec, 0x88, 0x1c, 0xf0, 0xd4, 0x86, 0x05,
108 0xae, 0x4e, 0xdd, 0x38, 0x63, 0x72, 0xae, 0xa9,
109 0xb2, 0x6e, 0x71, 0xdb, 0x51, 0x7e, 0x65, 0x0b,
110 ],
111 output_str: "b5baf747c307f98849ec881cf0d48605ae4edd386372aea9b26e71db517e650b",
112 },
113 Test {
114 input: "The major problem is with sendmail. -Mark Horton",
115 output: vec![
116 0x53, 0xed, 0x5f, 0x9b, 0x5c, 0x0b, 0x67, 0x4a,
117 0xc0, 0xf3, 0x42, 0x5d, 0x9f, 0x9a, 0x5d, 0x46,
118 0x26, 0x55, 0xb0, 0x7c, 0xc9, 0x0f, 0x5d, 0x0f,
119 0x69, 0x2e, 0xec, 0x09, 0x38, 0x84, 0xa6, 0x07,
120 ],
121 output_str: "53ed5f9b5c0b674ac0f3425d9f9a5d462655b07cc90f5d0f692eec093884a607",
122 },
123 ];
124
125 for test in tests {
126 let hash = sha512_256::Hash::hash(test.input.as_bytes());
128 assert_eq!(hash, test.output_str.parse::<sha512_256::Hash>().expect("parse hex"));
129 assert_eq!(&hash[..], &test.output[..]);
130 assert_eq!(&hash.to_string(), &test.output_str);
131
132 let mut engine = sha512_256::Hash::engine();
134 for ch in test.input.as_bytes() {
135 engine.0.input(&[*ch]);
136 }
137 let manual_hash = sha512_256::Hash::from_engine(engine);
138 assert_eq!(hash, manual_hash);
139 assert_eq!(hash.to_byte_array()[..].as_ref(), test.output.as_slice());
140 }
141 }
142}
143
144#[cfg(bench)]
145mod benches {
146 use test::Bencher;
147
148 use crate::{sha512_256, Hash, HashEngine};
149
150 #[bench]
151 pub fn sha512_256_10(bh: &mut Bencher) {
152 let mut engine = sha512_256::Hash::engine();
153 let bytes = [1u8; 10];
154 bh.iter(|| {
155 engine.input(&bytes);
156 });
157 bh.bytes = bytes.len() as u64;
158 }
159
160 #[bench]
161 pub fn sha512_256_1k(bh: &mut Bencher) {
162 let mut engine = sha512_256::Hash::engine();
163 let bytes = [1u8; 1024];
164 bh.iter(|| {
165 engine.input(&bytes);
166 });
167 bh.bytes = bytes.len() as u64;
168 }
169
170 #[bench]
171 pub fn sha512_256_64k(bh: &mut Bencher) {
172 let mut engine = sha512_256::Hash::engine();
173 let bytes = [1u8; 65536];
174 bh.iter(|| {
175 engine.input(&bytes);
176 });
177 bh.bytes = bytes.len() as u64;
178 }
179}