1use crate::Hasher;
24
25const H0: [u32; 8] = [
26 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
27];
28
29const K: [u32; 64] = [
30 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98,
31 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
32 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8,
33 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
34 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
35 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
36 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7,
37 0xc67178f2,
38];
39
40#[derive(Clone)]
46pub struct Sha256 {
47 state: [u32; 8],
48 buf: [u8; 64],
49 buf_len: usize,
50 total_len: u64,
51}
52
53fn compress(state: &mut [u32; 8], block: &[u8]) {
54 let mut w = [0u32; 64];
55 for i in 0..16 {
56 w[i] = u32::from_be_bytes([block[4 * i], block[4 * i + 1], block[4 * i + 2], block[4 * i + 3]]);
57 }
58 for i in 16..64 {
59 let s0 = w[i - 15].rotate_right(7) ^ w[i - 15].rotate_right(18) ^ (w[i - 15] >> 3);
60 let s1 = w[i - 2].rotate_right(17) ^ w[i - 2].rotate_right(19) ^ (w[i - 2] >> 10);
61 w[i] = w[i - 16].wrapping_add(s0).wrapping_add(w[i - 7]).wrapping_add(s1);
62 }
63
64 let mut a = state[0];
65 let mut b = state[1];
66 let mut c = state[2];
67 let mut d = state[3];
68 let mut e = state[4];
69 let mut f = state[5];
70 let mut g = state[6];
71 let mut h = state[7];
72
73 for i in 0..64 {
74 let s1 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25);
75 let ch = (e & f) ^ ((!e) & g);
76 let temp1 = h
77 .wrapping_add(s1)
78 .wrapping_add(ch)
79 .wrapping_add(K[i])
80 .wrapping_add(w[i]);
81 let s0 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22);
82 let maj = (a & b) ^ (a & c) ^ (b & c);
83 let temp2 = s0.wrapping_add(maj);
84
85 h = g;
86 g = f;
87 f = e;
88 e = d.wrapping_add(temp1);
89 d = c;
90 c = b;
91 b = a;
92 a = temp1.wrapping_add(temp2);
93 }
94
95 state[0] = state[0].wrapping_add(a);
96 state[1] = state[1].wrapping_add(b);
97 state[2] = state[2].wrapping_add(c);
98 state[3] = state[3].wrapping_add(d);
99 state[4] = state[4].wrapping_add(e);
100 state[5] = state[5].wrapping_add(f);
101 state[6] = state[6].wrapping_add(g);
102 state[7] = state[7].wrapping_add(h);
103}
104
105impl Sha256 {
106 pub(crate) fn new_with_iv(iv: [u32; 8]) -> Self {
107 Self {
108 state: iv,
109 buf: [0u8; 64],
110 buf_len: 0,
111 total_len: 0,
112 }
113 }
114}
115
116impl Hasher for Sha256 {
117 const OUTPUT_LEN: usize = 32;
118 const BLOCK_LEN: usize = 64;
119
120 fn new() -> Self {
121 Self {
122 state: H0,
123 buf: [0u8; 64],
124 buf_len: 0,
125 total_len: 0,
126 }
127 }
128
129 fn update(&mut self, data: &[u8]) {
130 let mut pos = 0;
131 self.total_len += data.len() as u64;
132
133 if self.buf_len > 0 {
134 let need = 64 - self.buf_len;
135 let take = need.min(data.len());
136 self.buf[self.buf_len..self.buf_len + take].copy_from_slice(&data[..take]);
137 self.buf_len += take;
138 pos = take;
139 if self.buf_len == 64 {
140 let block = self.buf;
141 compress(&mut self.state, &block);
142 self.buf_len = 0;
143 }
144 }
145
146 while pos + 64 <= data.len() {
147 compress(&mut self.state, &data[pos..pos + 64]);
148 pos += 64;
149 }
150
151 if pos < data.len() {
152 let remaining = data.len() - pos;
153 self.buf[..remaining].copy_from_slice(&data[pos..]);
154 self.buf_len = remaining;
155 }
156 }
157
158 fn finalize(self) -> Vec<u8> {
159 let mut out = vec![0u8; 32];
160 self.finalize_into(&mut out);
161 out
162 }
163
164 fn finalize_into(mut self, out: &mut [u8]) {
165 let bit_len = self.total_len * 8;
166 let mut pad = [0u8; 72];
167 pad[0] = 0x80;
168 let pad_len = if self.buf_len < 56 {
169 56 - self.buf_len
170 } else {
171 120 - self.buf_len
172 };
173 self.update(&pad[..pad_len]);
174 self.update(&bit_len.to_be_bytes());
175
176 for (i, word) in self.state.iter().enumerate() {
177 let bytes = word.to_be_bytes();
178 let start = i * 4;
179 if start + 4 <= out.len() {
180 out[start..start + 4].copy_from_slice(&bytes);
181 } else if start < out.len() {
182 let end = out.len() - start;
183 out[start..].copy_from_slice(&bytes[..end]);
184 }
185 }
186 }
187}
188
189#[cfg(test)]
190mod tests {
191 use super::*;
192 use crate::Hasher;
193
194 #[test]
195 fn test_sha256_empty() {
196 let digest = Sha256::hash(b"");
197 let expected: [u8; 32] = [
198 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae,
199 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
200 ];
201 assert_eq!(&digest[..], &expected[..]);
202 }
203
204 #[test]
205 fn test_sha256_abc() {
206 let digest = Sha256::hash(b"abc");
207 let expected: [u8; 32] = [
208 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03,
209 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
210 ];
211 assert_eq!(&digest[..], &expected[..]);
212 }
213}