1use super::{BlockHasher, Hasher};
4
5const K: [u32; 64] = [
9 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
10 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
11 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
12 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
13 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
14 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
15 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
16 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
17];
18
19#[inline]
22const fn ch(x: u32, y: u32, z: u32) -> u32 {
23 (x & y) ^ (!x & z)
24}
25
26#[inline]
29const fn maj(x: u32, y: u32, z: u32) -> u32 {
30 (x & y) ^ (x & z) ^ (y & z)
31}
32
33#[inline]
36const fn sigma_0(x: u32) -> u32 {
37 x.rotate_right(2) ^ x.rotate_right(13) ^ x.rotate_right(22)
38}
39
40#[inline]
43const fn sigma_1(x: u32) -> u32 {
44 x.rotate_right(6) ^ x.rotate_right(11) ^ x.rotate_right(25)
45}
46
47#[inline]
50const fn little_sigma_0(x: u32) -> u32 {
51 x.rotate_right(7) ^ x.rotate_right(18) ^ x >> 3
52}
53
54#[inline]
57const fn little_sigma_1(x: u32) -> u32 {
58 x.rotate_right(17) ^ x.rotate_right(19) ^ x >> 10
59}
60
61#[derive(Clone)]
62pub struct Sha256 {
63 state: [u32; Self::HASH_SIZE / size_of::<u32>()],
64 len: u64,
65}
66
67impl Sha256 {
68 pub const HASH_SIZE: usize = 32;
69 pub const BLOCK_SIZE: usize = 64;
70 fn update_countless(&mut self, block: &[u8; Self::BLOCK_SIZE]) {
71 let block = {
72 let mut as_u32 = [0u32; Sha256::BLOCK_SIZE / 4];
74 for (int, chunk) in as_u32.iter_mut().zip(block.chunks_exact(4)) {
76 *int = u32::from_be_bytes(chunk.try_into().unwrap());
77 }
78 as_u32
79 };
80
81 let mut message_schedule = [0; 64];
82 message_schedule[..block.len()].copy_from_slice(&block);
83
84 for i in 16..message_schedule.len() {
85 message_schedule[i] = little_sigma_1(message_schedule[i - 2])
86 .wrapping_add(message_schedule[i - 7])
87 .wrapping_add(little_sigma_0(message_schedule[i - 15]))
88 .wrapping_add(message_schedule[i - 16]);
89 }
90
91 let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut h] = self.state;
92
93 for i in 0..64 {
94 let temp1 = h
95 .wrapping_add(sigma_1(e))
96 .wrapping_add(ch(e, f, g))
97 .wrapping_add(K[i])
98 .wrapping_add(message_schedule[i]);
99 let temp2 = sigma_0(a).wrapping_add(maj(a, b, c));
100 h = g;
101 g = f;
102 f = e;
103 e = d.wrapping_add(temp1);
104 d = c;
105 c = b;
106 b = a;
107 a = temp1.wrapping_add(temp2);
108 }
109 self.state[0] = self.state[0].wrapping_add(a);
110 self.state[1] = self.state[1].wrapping_add(b);
111 self.state[2] = self.state[2].wrapping_add(c);
112 self.state[3] = self.state[3].wrapping_add(d);
113 self.state[4] = self.state[4].wrapping_add(e);
114 self.state[5] = self.state[5].wrapping_add(f);
115 self.state[6] = self.state[6].wrapping_add(g);
116 self.state[7] = self.state[7].wrapping_add(h);
117 }
118}
119
120impl Hasher<{ Sha256::HASH_SIZE }> for Sha256 {
121 fn new() -> Self {
122 Self {
123 state: [
124 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
125 0x5be0cd19,
126 ],
127 len: 0,
128 }
129 }
130 fn finish_with(mut self, msg: &[u8]) -> [u8; Self::HASH_SIZE] {
131 let blocks = msg.chunks_exact(Self::BLOCK_SIZE);
133 let remainder = blocks.remainder();
134
135 for block in blocks {
136 self.update_countless(block.try_into().unwrap());
137 }
138
139 let mut last_block = [0; Self::BLOCK_SIZE];
140 last_block[..remainder.len()].copy_from_slice(remainder);
142
143 last_block[remainder.len()] = 0x80;
144
145 if remainder.len() < Self::BLOCK_SIZE - size_of::<u64>() {
147 last_block[Self::BLOCK_SIZE - size_of::<u64>()..]
148 .copy_from_slice(&((msg.len() as u64 + self.len) * 8).to_be_bytes());
149 } else {
150 self.update_countless(&last_block);
151 last_block = [0; Self::BLOCK_SIZE];
152 last_block[Self::BLOCK_SIZE - size_of::<u64>()..]
153 .copy_from_slice(&((msg.len() as u64 + self.len) * 8).to_be_bytes());
154 }
155
156 self.update(&last_block);
157 u32_array_to_bytes(&self.state)
158 }
159
160 fn hash(msg: &[u8]) -> [u8; Sha256::HASH_SIZE] {
161 let hasher = Self::new();
162 hasher.finish_with(msg)
163 }
164
165 fn finish(mut self) -> [u8; Self::HASH_SIZE] {
166 let mut padding = [0; Self::BLOCK_SIZE];
167 padding[0] = 0x80;
168 padding[Sha256::BLOCK_SIZE - size_of::<u64>()..]
169 .copy_from_slice(&(self.len * 8).to_be_bytes());
170 self.update_countless(&padding);
171 u32_array_to_bytes(&self.state)
172 }
173}
174
175impl BlockHasher<{ Self::HASH_SIZE }, { Self::BLOCK_SIZE }> for Sha256 {
176 fn update(&mut self, block: &[u8; Self::BLOCK_SIZE]) {
177 self.update_countless(block);
178 self.len += Self::BLOCK_SIZE as u64;
179 }
180}
181
182fn u32_array_to_bytes(
183 array: &[u32; Sha256::HASH_SIZE / size_of::<u32>()],
184) -> [u8; Sha256::HASH_SIZE] {
185 let mut as_bytes = [0u8; Sha256::HASH_SIZE];
187 for (chunk, int) in as_bytes.chunks_exact_mut(size_of::<u32>()).zip(array) {
189 chunk.copy_from_slice(&int.to_be_bytes())
190 }
191 as_bytes
192}
193
194#[cfg(test)]
195mod tests {
196 use super::*;
197
198 #[test]
199 fn hash_1() {
200 let msg = b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
201 let digest: [u8; Sha256::HASH_SIZE] = [
202 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E,
203 0x60, 0x39, 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, 0xF6, 0xEC, 0xED, 0xD4,
204 0x19, 0xDB, 0x06, 0xC1,
205 ];
206 assert_eq!(Sha256::hash(msg), digest);
207 let msg = [
208 0x45, 0x11, 0x01, 0x25, 0x0e, 0xc6, 0xf2, 0x66, 0x52, 0x24, 0x9d, 0x59, 0xdc, 0x97,
209 0x4b, 0x73, 0x61, 0xd5, 0x71, 0xa8, 0x10, 0x1c, 0xdf, 0xd3, 0x6a, 0xba, 0x3b, 0x58,
210 0x54, 0xd3, 0xae, 0x08, 0x6b, 0x5f, 0xdd, 0x45, 0x97, 0x72, 0x1b, 0x66, 0xe3, 0xc0,
211 0xdc, 0x5d, 0x8c, 0x60, 0x6d, 0x96, 0x57, 0xd0, 0xe3, 0x23, 0x28, 0x3a, 0x52, 0x17,
212 0xd1, 0xf5, 0x3f, 0x2f, 0x28, 0x4f, 0x57, 0xb8, 0x5c, 0x8a, 0x61, 0xac, 0x89, 0x24,
213 0x71, 0x1f, 0x89, 0x5c, 0x5e, 0xd9, 0x0e, 0xf1, 0x77, 0x45, 0xed, 0x2d, 0x72, 0x8a,
214 0xbd, 0x22, 0xa5, 0xf7, 0xa1, 0x34, 0x79, 0xa4, 0x62, 0xd7, 0x1b, 0x56, 0xc1, 0x9a,
215 0x74, 0xa4, 0x0b, 0x65, 0x5c, 0x58, 0xed, 0xfe, 0x0a, 0x18, 0x8a, 0xd2, 0xcf, 0x46,
216 0xcb, 0xf3, 0x05, 0x24, 0xf6, 0x5d, 0x42, 0x3c, 0x83, 0x7d, 0xd1, 0xff, 0x2b, 0xf4,
217 0x62, 0xac, 0x41, 0x98, 0x00, 0x73, 0x45, 0xbb, 0x44, 0xdb, 0xb7, 0xb1, 0xc8, 0x61,
218 0x29, 0x8c, 0xdf, 0x61, 0x98, 0x2a, 0x83, 0x3a, 0xfc, 0x72, 0x8f, 0xae, 0x1e, 0xda,
219 0x2f, 0x87, 0xaa, 0x2c, 0x94, 0x80, 0x85, 0x8b, 0xec,
220 ];
221 let digest = [
222 0x3c, 0x59, 0x3a, 0xa5, 0x39, 0xfd, 0xcd, 0xae, 0x51, 0x6c, 0xdf, 0x2f, 0x15, 0x00,
223 0x0f, 0x66, 0x34, 0x18, 0x5c, 0x88, 0xf5, 0x05, 0xb3, 0x97, 0x75, 0xfb, 0x9a, 0xb1,
224 0x37, 0xa1, 0x0a, 0xa2,
225 ];
226 assert_eq!(Sha256::hash(&msg), digest);
227 }
228
229 #[test]
230 fn hash_2() {
231 let msg = [
232 0x6b, 0x91, 0x8f, 0xb1, 0xa5, 0xad, 0x1f, 0x9c, 0x5e, 0x5d, 0xbd, 0xf1, 0x0a, 0x93,
233 0xa9, 0xc8, 0xf6, 0xbc, 0xa8, 0x9f, 0x37, 0xe7, 0x9c, 0x9f, 0xe1, 0x2a, 0x57, 0x22,
234 0x79, 0x41, 0xb1, 0x73, 0xac, 0x79, 0xd8, 0xd4, 0x40, 0xcd, 0xe8, 0xc6, 0x4c, 0x4e,
235 0xbc, 0x84, 0xa4, 0xc8, 0x03, 0xd1, 0x98, 0xa2, 0x96, 0xf3, 0xde, 0x06, 0x09, 0x00,
236 0xcc, 0x42, 0x7f, 0x58, 0xca, 0x6e, 0xc3, 0x73, 0x08, 0x4f, 0x95, 0xdd, 0x6c, 0x7c,
237 0x42, 0x7e, 0xcf, 0xbf, 0x78, 0x1f, 0x68, 0xbe, 0x57, 0x2a, 0x88, 0xdb, 0xcb, 0xb1,
238 0x88, 0x58, 0x1a, 0xb2, 0x00, 0xbf, 0xb9, 0x9a, 0x3a, 0x81, 0x64, 0x07, 0xe7, 0xdd,
239 0x6d, 0xd2, 0x10, 0x03, 0x55, 0x4d, 0x4f, 0x7a, 0x99, 0xc9, 0x3e, 0xbf, 0xce, 0x5c,
240 0x30, 0x2f, 0xf0, 0xe1, 0x1f, 0x26, 0xf8, 0x3f, 0xe6, 0x69, 0xac, 0xef, 0xb0, 0xc1,
241 0xbb, 0xb8, 0xb1, 0xe9, 0x09, 0xbd, 0x14, 0xaa, 0x48, 0xba, 0x34, 0x45, 0xc8, 0x8b,
242 0x0e, 0x11, 0x90, 0xee, 0xf7, 0x65, 0xad, 0x89, 0x8a, 0xb8, 0xca, 0x2f, 0xe5, 0x07,
243 0x01, 0x5f, 0x15, 0x78, 0xf1, 0x0d, 0xce, 0x3c, 0x11, 0xa5, 0x5f, 0xb9, 0x43, 0x4e,
244 0xe6, 0xe9, 0xad, 0x6c, 0xc0, 0xfd, 0xc4, 0x68, 0x44, 0x47, 0xa9, 0xb3, 0xb1, 0x56,
245 0xb9, 0x08, 0x64, 0x63, 0x60, 0xf2, 0x4f, 0xec, 0x2d, 0x8f, 0xa6, 0x9e, 0x2c, 0x93,
246 0xdb, 0x78, 0x70, 0x8f, 0xcd, 0x2e, 0xef, 0x74, 0x3d, 0xcb, 0x93, 0x53, 0x81, 0x9b,
247 0x8d, 0x66, 0x7c, 0x48, 0xed, 0x54, 0xcd, 0x43, 0x6f, 0xb1, 0x47, 0x65, 0x98, 0xc4,
248 0xa1, 0xd7, 0x02, 0x8e, 0x6f, 0x2f, 0xf5, 0x07, 0x51, 0xdb, 0x36, 0xab, 0x6b, 0xc3,
249 0x24, 0x35, 0x15, 0x2a, 0x00, 0xab, 0xd3, 0xd5, 0x8d, 0x9a, 0x87, 0x70, 0xd9, 0xa3,
250 0xe5, 0x2d, 0x5a, 0x36, 0x28, 0xae, 0x3c, 0x9e, 0x03, 0x25,
251 ];
252 let digest = [
253 0x46, 0x50, 0x0b, 0x6a, 0xe1, 0xab, 0x40, 0xbd, 0xe0, 0x97, 0xef, 0x16, 0x8b, 0x0f,
254 0x31, 0x99, 0x04, 0x9b, 0x55, 0x54, 0x5a, 0x15, 0x88, 0x79, 0x2d, 0x39, 0xd5, 0x94,
255 0xf4, 0x93, 0xdc, 0xa7,
256 ];
257 assert_eq!(Sha256::hash(&msg), digest);
258 }
259
260 #[test]
261 fn update() {
262 let msg = [
263 0x6b, 0x91, 0x8f, 0xb1, 0xa5, 0xad, 0x1f, 0x9c, 0x5e, 0x5d, 0xbd, 0xf1, 0x0a, 0x93,
264 0xa9, 0xc8, 0xf6, 0xbc, 0xa8, 0x9f, 0x37, 0xe7, 0x9c, 0x9f, 0xe1, 0x2a, 0x57, 0x22,
265 0x79, 0x41, 0xb1, 0x73, 0xac, 0x79, 0xd8, 0xd4, 0x40, 0xcd, 0xe8, 0xc6, 0x4c, 0x4e,
266 0xbc, 0x84, 0xa4, 0xc8, 0x03, 0xd1, 0x98, 0xa2, 0x96, 0xf3, 0xde, 0x06, 0x09, 0x00,
267 0xcc, 0x42, 0x7f, 0x58, 0xca, 0x6e, 0xc3, 0x73, 0x08, 0x4f, 0x95, 0xdd, 0x6c, 0x7c,
268 0x42, 0x7e, 0xcf, 0xbf, 0x78, 0x1f, 0x68, 0xbe, 0x57, 0x2a, 0x88, 0xdb, 0xcb, 0xb1,
269 0x88, 0x58, 0x1a, 0xb2, 0x00, 0xbf, 0xb9, 0x9a, 0x3a, 0x81, 0x64, 0x07, 0xe7, 0xdd,
270 0x6d, 0xd2, 0x10, 0x03, 0x55, 0x4d, 0x4f, 0x7a, 0x99, 0xc9, 0x3e, 0xbf, 0xce, 0x5c,
271 0x30, 0x2f, 0xf0, 0xe1, 0x1f, 0x26, 0xf8, 0x3f, 0xe6, 0x69, 0xac, 0xef, 0xb0, 0xc1,
272 0xbb, 0xb8, 0xb1, 0xe9, 0x09, 0xbd, 0x14, 0xaa, 0x48, 0xba, 0x34, 0x45, 0xc8, 0x8b,
273 0x0e, 0x11, 0x90, 0xee, 0xf7, 0x65, 0xad, 0x89, 0x8a, 0xb8, 0xca, 0x2f, 0xe5, 0x07,
274 0x01, 0x5f, 0x15, 0x78, 0xf1, 0x0d, 0xce, 0x3c, 0x11, 0xa5, 0x5f, 0xb9, 0x43, 0x4e,
275 0xe6, 0xe9, 0xad, 0x6c, 0xc0, 0xfd, 0xc4, 0x68, 0x44, 0x47, 0xa9, 0xb3, 0xb1, 0x56,
276 0xb9, 0x08, 0x64, 0x63, 0x60, 0xf2, 0x4f, 0xec, 0x2d, 0x8f, 0xa6, 0x9e, 0x2c, 0x93,
277 0xdb, 0x78, 0x70, 0x8f, 0xcd, 0x2e, 0xef, 0x74, 0x3d, 0xcb, 0x93, 0x53, 0x81, 0x9b,
278 0x8d, 0x66, 0x7c, 0x48, 0xed, 0x54, 0xcd, 0x43, 0x6f, 0xb1, 0x47, 0x65, 0x98, 0xc4,
279 0xa1, 0xd7, 0x02, 0x8e, 0x6f, 0x2f, 0xf5, 0x07, 0x51, 0xdb, 0x36, 0xab, 0x6b, 0xc3,
280 0x24, 0x35, 0x15, 0x2a, 0x00, 0xab, 0xd3, 0xd5, 0x8d, 0x9a, 0x87, 0x70, 0xd9, 0xa3,
281 0xe5, 0x2d, 0x5a, 0x36, 0x28, 0xae, 0x3c, 0x9e, 0x03, 0x25,
282 ];
283 let digest = [
284 0x46, 0x50, 0x0b, 0x6a, 0xe1, 0xab, 0x40, 0xbd, 0xe0, 0x97, 0xef, 0x16, 0x8b, 0x0f,
285 0x31, 0x99, 0x04, 0x9b, 0x55, 0x54, 0x5a, 0x15, 0x88, 0x79, 0x2d, 0x39, 0xd5, 0x94,
286 0xf4, 0x93, 0xdc, 0xa7,
287 ];
288 let mut hasher = Sha256::new();
289
290 let blocks = msg.chunks_exact(Sha256::BLOCK_SIZE);
291 let remainder = blocks.remainder();
292
293 for block in blocks {
294 hasher.update(block.try_into().unwrap());
295 }
296 assert_eq!(hasher.finish_with(remainder), digest);
297 }
298}