1pub const DIGEST_SIZE: usize = 32;
10
11pub const BLOCK_SIZE: usize = 64;
13
14const K: [u32; 64] = [
16 0x428a_2f98,
17 0x7137_4491,
18 0xb5c0_fbcf,
19 0xe9b5_dba5,
20 0x3956_c25b,
21 0x59f1_11f1,
22 0x923f_82a4,
23 0xab1c_5ed5,
24 0xd807_aa98,
25 0x1283_5b01,
26 0x2431_85be,
27 0x550c_7dc3,
28 0x72be_5d74,
29 0x80de_b1fe,
30 0x9bdc_06a7,
31 0xc19b_f174,
32 0xe49b_69c1,
33 0xefbe_4786,
34 0x0fc1_9dc6,
35 0x240c_a1cc,
36 0x2de9_2c6f,
37 0x4a74_84aa,
38 0x5cb0_a9dc,
39 0x76f9_88da,
40 0x983e_5152,
41 0xa831_c66d,
42 0xb003_27c8,
43 0xbf59_7fc7,
44 0xc6e0_0bf3,
45 0xd5a7_9147,
46 0x06ca_6351,
47 0x1429_2967,
48 0x27b7_0a85,
49 0x2e1b_2138,
50 0x4d2c_6dfc,
51 0x5338_0d13,
52 0x650a_7354,
53 0x766a_0abb,
54 0x81c2_c92e,
55 0x9272_2c85,
56 0xa2bf_e8a1,
57 0xa81a_664b,
58 0xc24b_8b70,
59 0xc76c_51a3,
60 0xd192_e819,
61 0xd699_0624,
62 0xf40e_3585,
63 0x106a_a070,
64 0x19a4_c116,
65 0x1e37_6c08,
66 0x2748_774c,
67 0x34b0_bcb5,
68 0x391c_0cb3,
69 0x4ed8_aa4a,
70 0x5b9c_ca4f,
71 0x682e_6ff3,
72 0x748f_82ee,
73 0x78a5_636f,
74 0x84c8_7814,
75 0x8cc7_0208,
76 0x90be_fffa,
77 0xa450_6ceb,
78 0xbef9_a3f7,
79 0xc671_78f2,
80];
81
82const H: [u32; 8] = [
83 0x6a09_e667,
84 0xbb67_ae85,
85 0x3c6e_f372,
86 0xa54f_f53a,
87 0x510e_527f,
88 0x9b05_688c,
89 0x1f83_d9ab,
90 0x5be0_cd19,
91];
92
93fn ch(x: u32, y: u32, z: u32) -> u32 {
95 (x & y) ^ ((!x) & z)
96}
97
98fn maj(x: u32, y: u32, z: u32) -> u32 {
100 (x & y) ^ (x & z) ^ (y & z)
101}
102
103fn rotr(n: u32, s: u32) -> u32 {
104 (n << (32 - s)) | (n >> s)
105}
106
107fn bsig0(x: u32) -> u32 {
109 rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22)
110}
111
112fn bsig1(x: u32) -> u32 {
114 rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25)
115}
116
117fn ssig0(x: u32) -> u32 {
119 rotr(x, 7) ^ rotr(x, 18) ^ (x >> 3)
120}
121
122fn ssig1(x: u32) -> u32 {
124 rotr(x, 17) ^ rotr(x, 19) ^ (x >> 10)
125}
126
127fn fill_block(input: &[u8; BLOCK_SIZE], output: &mut [u32; BLOCK_SIZE / 4]) {
128 for i in 0..output.len() {
129 let i0 = u32::from(input[i * 4]);
130 let i1 = u32::from(input[i * 4 + 1]);
131 let i2 = u32::from(input[i * 4 + 2]);
132 let i3 = u32::from(input[i * 4 + 3]);
133
134 output[i] = (i0 << 24) | (i1 << 16) | (i2 << 8) | i3;
135 }
136}
137
138fn write_u64_be(data: &mut [u8], value: u64) {
139 data[0] = (value >> 56) as u8;
140 data[1] = (value >> 48) as u8;
141 data[2] = (value >> 40) as u8;
142 data[3] = (value >> 32) as u8;
143 data[4] = (value >> 24) as u8;
144 data[5] = (value >> 16) as u8;
145 data[6] = (value >> 8) as u8;
146 data[7] = (value) as u8;
147}
148
149pub struct SHA256 {
170 h: [u32; 8],
171 buffer: [u8; BLOCK_SIZE],
172 length: usize,
173}
174
175impl SHA256 {
176 pub fn new() -> SHA256 {
180 SHA256 {
181 h: H,
182 buffer: [0; BLOCK_SIZE],
183 length: 0,
184 }
185 }
186
187 fn process_block(self: &mut SHA256, block: &[u32; 16]) {
188 let mut w: [u32; 64] = [0; 64];
196 let mut a: u32;
197 let mut b: u32;
198 let mut c: u32;
199 let mut d: u32;
200 let mut e: u32;
201 let mut f: u32;
202 let mut g: u32;
203 let mut h: u32;
204
205 w[..16].clone_from_slice(&block[..16]);
206
207 for t in 16..64 {
208 w[t] = wrapping_sum!(ssig1(w[t - 2]), w[t - 7], ssig0(w[t - 15]), w[t - 16]);
209 }
210
211 a = self.h[0];
223 b = self.h[1];
224 c = self.h[2];
225 d = self.h[3];
226 e = self.h[4];
227 f = self.h[5];
228 g = self.h[6];
229 h = self.h[7];
230
231 for t in 0..64 {
246 let t1 = wrapping_sum!(h, bsig1(e), ch(e, f, g), K[t], w[t]);
247 let t2 = wrapping_sum!(bsig0(a), maj(a, b, c));
248 h = g;
249 g = f;
250 f = e;
251 e = wrapping_sum!(d, t1);
252 d = c;
253 c = b;
254 b = a;
255 a = wrapping_sum!(t1, t2);
256 }
257
258 self.h[0] = wrapping_sum!(self.h[0], a);
270 self.h[1] = wrapping_sum!(self.h[1], b);
271 self.h[2] = wrapping_sum!(self.h[2], c);
272 self.h[3] = wrapping_sum!(self.h[3], d);
273 self.h[4] = wrapping_sum!(self.h[4], e);
274 self.h[5] = wrapping_sum!(self.h[5], f);
275 self.h[6] = wrapping_sum!(self.h[6], g);
276 self.h[7] = wrapping_sum!(self.h[7], h);
277 }
278
279 pub fn update(self: &mut SHA256, data: &[u8]) {
283 let mut block: [u32; BLOCK_SIZE / 4] = [0; BLOCK_SIZE / 4];
284
285 for &b in data {
286 let off = self.length % BLOCK_SIZE;
287
288 self.buffer[off] = b;
290 self.length += 1;
291
292 if self.length % BLOCK_SIZE != 0 {
293 continue;
294 }
295
296 fill_block(&self.buffer, &mut block);
297 self.process_block(&block);
298 }
299 }
300
301 pub fn digest(self: &mut SHA256) -> [u8; DIGEST_SIZE] {
305 let mut block: [u32; BLOCK_SIZE / 4] = [0; BLOCK_SIZE / 4];
325
326 let mut off = self.length % BLOCK_SIZE;
330
331 for i in off..self.buffer.len() {
333 self.buffer[i] = 0;
334 }
335
336 let has_overflow = off + 9 > BLOCK_SIZE;
341 if has_overflow {
342 self.buffer[off] |= 0x80;
344
345 fill_block(&self.buffer, &mut block);
346 self.process_block(&block);
347
348 off = 0;
349 self.buffer = [0; BLOCK_SIZE];
350 }
351
352 let len_off = self.buffer.len() - 8;
354 write_u64_be(&mut self.buffer[len_off..], (self.length * 8) as u64);
355
356 if !has_overflow {
358 self.buffer[off] |= 0x80;
359 }
360
361 fill_block(&self.buffer, &mut block);
362 self.process_block(&block);
363
364 let mut out: [u8; DIGEST_SIZE] = [0; DIGEST_SIZE];
365 for i in 0..self.h.len() {
366 out[i * 4] = (self.h[i] >> 24) as u8;
367 out[i * 4 + 1] = (self.h[i] >> 16) as u8;
368 out[i * 4 + 2] = (self.h[i] >> 8) as u8;
369 out[i * 4 + 3] = (self.h[i]) as u8;
370 }
371 out
372 }
373}
374
375impl Default for SHA256 {
376 fn default() -> SHA256 {
377 SHA256::new()
378 }
379}
380
381#[cfg(test)]
382mod tests {
383 use super::*;
384
385 fn check(inputs: &[&str], expected: [u8; DIGEST_SIZE]) {
386 let mut sha256 = SHA256::new();
387
388 for chunk in inputs {
389 sha256.update(chunk.as_bytes());
390 }
391 assert_eq!(sha256.digest(), expected);
392 }
393
394 #[test]
395 fn it_should_compute_digest_for_abc() {
396 check(
397 &["abc"],
398 [
399 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE,
400 0x22, 0x23, 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, 0xB4, 0x10, 0xFF, 0x61,
401 0xF2, 0x00, 0x15, 0xAD,
402 ],
403 );
404 }
405
406 #[test]
407 fn it_should_compute_digest_for_a_b_c() {
408 check(
409 &["a", "b", "c"],
410 [
411 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE,
412 0x22, 0x23, 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, 0xB4, 0x10, 0xFF, 0x61,
413 0xF2, 0x00, 0x15, 0xAD,
414 ],
415 );
416 }
417
418 #[test]
419 fn it_should_compute_digest_for_long_str() {
420 check(
421 &["abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"],
422 [
423 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E,
424 0x60, 0x39, 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, 0xF6, 0xEC, 0xED, 0xD4,
425 0x19, 0xDB, 0x06, 0xC1,
426 ],
427 );
428 }
429
430 #[test]
431 fn it_should_compute_digest_for_long_chunked_str() {
432 check(
433 &[
434 "abcdbcdec",
435 "defdefgefg",
436 "hfghighijhi",
437 "jkijkljklmkl",
438 "mnlmnomnopnopq",
439 ],
440 [
441 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E,
442 0x60, 0x39, 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, 0xF6, 0xEC, 0xED, 0xD4,
443 0x19, 0xDB, 0x06, 0xC1,
444 ],
445 );
446 }
447
448 #[test]
449 fn it_should_compute_digest_for_doubled_chunked_long_str() {
450 check(
451 &[
452 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
453 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
454 ],
455 [
456 0x59, 0xf1, 0x09, 0xd9, 0x53, 0x3b, 0x2b, 0x70, 0xe7, 0xc3, 0xb8, 0x14, 0xa2, 0xbd,
457 0x21, 0x8f, 0x78, 0xea, 0x5d, 0x37, 0x14, 0x45, 0x5b, 0xc6, 0x79, 0x87, 0xcf, 0x0d,
458 0x66, 0x43, 0x99, 0xcf,
459 ],
460 );
461 }
462
463 #[test]
464 fn it_should_compute_digest_for_doubled_long_str() {
465 check(
466 &[
467 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqabc\
468 dbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
469 ],
470 [
471 0x59, 0xf1, 0x09, 0xd9, 0x53, 0x3b, 0x2b, 0x70, 0xe7, 0xc3, 0xb8, 0x14, 0xa2, 0xbd,
472 0x21, 0x8f, 0x78, 0xea, 0x5d, 0x37, 0x14, 0x45, 0x5b, 0xc6, 0x79, 0x87, 0xcf, 0x0d,
473 0x66, 0x43, 0x99, 0xcf,
474 ],
475 );
476 }
477}