1use futures::io::{AsyncRead, AsyncReadExt};
2
3const K: [u32; 64] = [
4 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
5 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
6 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
7 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
8 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
9 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
10 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
11 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
12];
13
14const H: [u32; 8] = [
15 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
16];
17
18const ZERO_BUFFER: [u8; 64] = [0; 64];
19
20pub fn encode(bytes: &[u8]) -> [u8; 32] {
21 let h: [u32; 8] = encode_core(bytes, H);
22 let mut hh: [u8; 32] = [0; 32];
23 for i in 0..8 {
24 let start_index = i << 2;
25 hh[start_index..start_index + 4].copy_from_slice(&h[i].to_be_bytes());
26 }
27
28 hh
29}
30
31pub async fn encode_async<R>(mut reader: R) -> Result<[u8; 32], std::io::Error>
32where
33 R: AsyncRead + Unpin,
34{
35 let mut h = H;
36 let mut buffer = [0u8; 64];
37 let mut buffer_len = 0;
38 let mut total_length = 0;
39
40 loop {
41 let bytes_read = reader.read(&mut buffer[buffer_len..]).await?;
42 if bytes_read == 0 {
43 break;
44 }
45
46 buffer_len += bytes_read;
47 total_length += bytes_read;
48
49 if buffer_len == 64 {
50 let result = process_chunk(&buffer[..64], &h);
51 for i in 0..8 {
52 h[i] = h[i].wrapping_add(result[i]);
53 }
54 buffer_len = 0;
55 }
56 }
57
58 let final_chunk2 =
59 get_final_chunks_sha(&mut buffer, total_length, buffer_len);
60 let result = process_chunk(&buffer, &h);
61 for i in 0..8 {
62 h[i] = h[i].wrapping_add(result[i]);
63 }
64 if let Some(chunk2) = final_chunk2 {
65 let result = process_chunk(&chunk2, &h);
66 for i in 0..8 {
67 h[i] = h[i].wrapping_add(result[i]);
68 }
69 }
70
71 let mut hh: [u8; 32] = [0; 32];
72 for i in 0..8 {
73 let start_index = i << 2;
74 hh[start_index..start_index + 4].copy_from_slice(&h[i].to_be_bytes());
75 }
76
77 Ok(hh)
78}
79
80
81pub(crate) fn encode_core(bytes: &[u8], mut h: [u32; 8]) -> [u32; 8] {
82 let bytes = get_normalized_message_bytes(bytes);
83 for chunk_num in 0..(bytes.len() >> 6) {
85 let chunk_start_index = chunk_num << 6;
87 let chunk: &[u8] = &bytes[chunk_start_index..chunk_start_index + 64];
88
89 let result = process_chunk(chunk, &h);
90 for i in 0..8 {
91 h[i] = h[i].wrapping_add(result[i]);
92 }
93 }
94 h
95}
96
97fn get_normalized_message_bytes(bytes: &[u8]) -> Vec<u8> {
102 let message_length: u64 = bytes.len() as u64;
103 let message_bit_length: u64 = message_length << 3;
104 let zero_bytes_len = (message_length + 9) % 64;
105 let mut bytes: Vec<u8> = bytes.to_vec();
106 bytes.push(0x80);
107
108 if zero_bytes_len > 0 {
109 for _ in 0..64 - zero_bytes_len {
110 bytes.push(0);
111 }
112 }
113
114 bytes.extend_from_slice(&message_bit_length.to_be_bytes());
115 bytes
116}
117
118pub(crate) fn process_chunk(chunk: &[u8], vars: &[u32]) -> [u32; 8] {
119 let mut chunk_u32 = [0u32; 16];
120 for (i, chunk_bytes) in chunk.chunks_exact(4).enumerate() {
121 let chunk: [u8; 4] = chunk_bytes.try_into().unwrap();
122 chunk_u32[i] = u32::from_be_bytes(chunk);
123 }
124
125 let mut a: u32 = vars[0];
126 let mut b: u32 = vars[1];
127 let mut c: u32 = vars[2];
128 let mut d: u32 = vars[3];
129 let mut e: u32 = vars[4];
130 let mut f: u32 = vars[5];
131 let mut g: u32 = vars[6];
132 let mut h: u32 = vars[7];
133
134 let mut w: [u32; 64] = [0; 64];
135 w[0..16].copy_from_slice(&chunk_u32);
136 for num in 16..64 {
137 let s0 = w[num - 15];
138 let s1 = w[num - 2];
139 let sigma0 = s0.rotate_right(7) ^ s0.rotate_right(18) ^ (s0 >> 3);
140 let sigma1 = s1.rotate_right(17) ^ s1.rotate_right(19) ^ (s1 >> 10);
141
142 w[num] = w[num - 16]
143 .wrapping_add(sigma0)
144 .wrapping_add(w[num - 7])
145 .wrapping_add(sigma1);
146 }
147
148 for num in 0..64 {
149 let ch = g ^ (e & (f ^ g));
150 let sigma1 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25);
151 let temp1 = h.wrapping_add(sigma1).wrapping_add(ch).wrapping_add(K[num]).wrapping_add(w[num]);
152 let maj = (a & b) ^ (c & (a ^ b));
153 let sigma0 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22);
154 let temp2 = sigma0.wrapping_add(maj);
155
156 h = g;
157 g = f;
158 f = e;
159 e = d.wrapping_add(temp1);
160 d = c;
161 c = b;
162 b = a;
163 a = temp1.wrapping_add(temp2);
164 }
165
166 [a, b, c, d, e, f, g, h]
167}
168
169pub(crate) fn get_final_chunks_sha(chunk1: &mut [u8; 64], total_len: usize, partial_data_len: usize) -> Option<[u8; 64]> {
170 let total= total_len << 3;
171 let mut full_padded_length = total + 1 + 64;
172 full_padded_length += 512 - (full_padded_length % 512);
173 chunk1[partial_data_len] = 0x80;
174 chunk1[partial_data_len + 1..].copy_from_slice(&ZERO_BUFFER[..64 - partial_data_len - 1]);
175 let two_chunks = full_padded_length - total > 512;
176 if two_chunks {
177 let mut chunk2 = [0u8; 64];
178 chunk2[56..].copy_from_slice(&(total as u64).to_be_bytes());
179 Some(chunk2)
180 } else {
181 chunk1[56..].copy_from_slice(&(total as u64).to_be_bytes());
182 None
183 }
184}
185
186#[cfg(test)]
187mod tests {
188 use super::*;
189
190 #[tokio::test]
191 async fn test_encode_empty_string() {
192 let result = encode_async("".as_bytes()).await.unwrap();
193 assert_eq!(
194 result,
195 [
196 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f,
197 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b,
198 0x78, 0x52, 0xb8, 0x55
199 ]
200 );
201 }
202
203 #[tokio::test]
204 async fn test_encode_abc() {
205 let result = encode_async("abc".as_bytes()).await.unwrap();
206 assert_eq!(
207 result,
208 [
209 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae,
210 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61,
211 0xf2, 0x00, 0x15, 0xad
212 ]
213 );
214 }
215
216 #[tokio::test]
217 async fn test_encode_message_digest() {
218 let result = encode_async("message digest".as_bytes()).await.unwrap();
219 assert_eq!(
220 result,
221 [
222 0xf7, 0x84, 0x6f, 0x55, 0xcf, 0x23, 0xe1, 0x4e, 0xeb, 0xea, 0xb5, 0xb4, 0xe1, 0x55,
223 0x0c, 0xad, 0x5b, 0x50, 0x9e, 0x33, 0x48, 0xfb, 0xc4, 0xef, 0xa3, 0xa1, 0x41, 0x3d,
224 0x39, 0x3c, 0xb6, 0x50
225 ]
226 );
227 }
228
229 #[tokio::test]
230 async fn test_encode_abcdefghijklmnopqrstuvwxyz() {
231 let result = encode_async("abcdefghijklmnopqrstuvwxyz".as_bytes()).await.unwrap();
232 assert_eq!(
233 result,
234 [
235 0x71, 0xc4, 0x80, 0xdf, 0x93, 0xd6, 0xae, 0x2f, 0x1e, 0xfa, 0xd1, 0x44, 0x7c, 0x66,
236 0xc9, 0x52, 0x5e, 0x31, 0x62, 0x18, 0xcf, 0x51, 0xfc, 0x8d, 0x9e, 0xd8, 0x32, 0xf2,
237 0xda, 0xf1, 0x8b, 0x73
238 ]
239 );
240 }
241
242 #[tokio::test]
243 async fn test_encode_alphanumeric_string() {
244 let result = encode_async("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".as_bytes()).await.unwrap();
245 assert_eq!(
246 result,
247 [
248 0xdb, 0x4b, 0xfc, 0xbd, 0x4d, 0xa0, 0xcd, 0x85, 0xa6, 0x0c, 0x3c, 0x37, 0xd3, 0xfb,
249 0xd8, 0x80, 0x5c, 0x77, 0xf1, 0x5f, 0xc6, 0xb1, 0xfd, 0xfe, 0x61, 0x4e, 0xe0, 0xa7,
250 0xc8, 0xfd, 0xb4, 0xc0
251 ]
252 );
253 }
254
255 #[tokio::test]
256 async fn test_encode_12345() {
257 let result = encode_async("12345".as_bytes()).await.unwrap();
258 assert_eq!(
259 result,
260 [
261 0x59, 0x94, 0x47, 0x1a, 0xbb, 0x01, 0x11, 0x2a, 0xfc, 0xc1, 0x81, 0x59, 0xf6, 0xcc,
262 0x74, 0xb4, 0xf5, 0x11, 0xb9, 0x98, 0x06, 0xda, 0x59, 0xb3, 0xca, 0xf5, 0xa9, 0xc1,
263 0x73, 0xca, 0xcf, 0xc5
264 ]
265 );
266 }
267
268 #[tokio::test]
269 async fn test_encode_2() {
270 let text: &[u8] = &[
271 0xcd, 0xa9, 0xfe, 0x30, 0xbf, 0x85, 0x93, 0xe6, 0x1a, 0x05, 0x12, 0x0d, 0xc0, 0xac,
272 0x2d, 0x2d, 0x16, 0x46, 0x63, 0xbe, 0x91, 0xa2, 0x06, 0x7c, 0x58, 0x47, 0x16, 0x23,
273 0x68, 0xe9, 0x22, 0xac, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
274 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
275 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x20, 0x12, 0x74, 0x6c, 0x73,
276 0x31, 0x33, 0x20, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
277 0x32, 0x20, 0xda, 0x75, 0xce, 0x11, 0x39, 0xac, 0x80, 0xda, 0xe4, 0x04, 0x4d, 0xa9,
278 0x32, 0x35, 0x0c, 0xf6, 0x5c, 0x97, 0xcc, 0xc9, 0xe3, 0x3f, 0x1e, 0x6f, 0x7d, 0x2d,
279 0x4b, 0x18, 0xb7, 0x36, 0xff, 0xd5, 0x01,
280 ];
281 let expected: &[u8] = &[
282 0x60, 0x68, 0x8e, 0xe8, 0x0c, 0x78, 0x8c, 0x98, 0xb5, 0xb7, 0x95, 0x6b, 0x93, 0x19,
283 0x8e, 0x9d, 0x8a, 0x40, 0xa9, 0x66, 0xea, 0x70, 0xd3, 0x71, 0x98, 0x0e, 0xb3, 0x3b,
284 0x3f, 0x79, 0x2f, 0xa7,
285 ];
286 let result = encode_async(text).await.unwrap();
287 assert_eq!(&result, expected);
288 }
289
290
291}