1use futures::io::{AsyncRead, AsyncReadExt};
2
3use crate::sha256::get_final_chunks_sha;
4
5pub fn encode(bytes: &[u8]) -> [u8; 20] {
6 let mut h0: u32 = 0x67452301;
7 let mut h1: u32 = 0xEFCDAB89;
8 let mut h2: u32 = 0x98BADCFE;
9 let mut h3: u32 = 0x10325476;
10 let mut h4: u32 = 0xC3D2E1F0;
11
12 let bytes = get_normalized_message_bytes(bytes);
13 for chunk_num in 0..(bytes.len() >> 6) {
15 let chunk_start_index = chunk_num << 6;
17 let chunk: &[u8] = &bytes[chunk_start_index..chunk_start_index + 64];
18
19 let result = process_chunk(chunk, h0, h1, h2, h3, h4);
20 h0 = (h0 as u64 + result.0 as u64) as u32;
21 h1 = (h1 as u64 + result.1 as u64) as u32;
22 h2 = (h2 as u64 + result.2 as u64) as u32;
23 h3 = (h3 as u64 + result.3 as u64) as u32;
24 h4 = (h4 as u64 + result.4 as u64) as u32;
25 }
26
27 let mut hh: [u8; 20] = [0; 20];
28 hh[..4].copy_from_slice(&h0.to_be_bytes());
29 hh[4..8].copy_from_slice(&h1.to_be_bytes());
30 hh[8..12].copy_from_slice(&h2.to_be_bytes());
31 hh[12..16].copy_from_slice(&h3.to_be_bytes());
32 hh[16..].copy_from_slice(&h4.to_be_bytes());
33
34 hh
35}
36
37pub async fn encode_async<R>(mut reader: R) -> Result<[u8; 20], std::io::Error>
38where
39 R: AsyncRead + Unpin,
40{
41 let mut h0: u32 = 0x67452301;
42 let mut h1: u32 = 0xEFCDAB89;
43 let mut h2: u32 = 0x98BADCFE;
44 let mut h3: u32 = 0x10325476;
45 let mut h4: u32 = 0xC3D2E1F0;
46
47 let mut buffer = [0u8; 64];
48 let mut buffer_len = 0;
49 let mut total_length = 0;
50
51 loop {
52 let bytes_read = reader.read(&mut buffer[buffer_len..]).await?;
53 if bytes_read == 0 {
54 break;
55 }
56
57 buffer_len += bytes_read;
58 total_length += bytes_read;
59 if buffer_len == 64 {
60 let result = process_chunk(&buffer, h0, h1, h2, h3, h4);
61 h0 = h0.wrapping_add(result.0);
62 h1 = h1.wrapping_add(result.1);
63 h2 = h2.wrapping_add(result.2);
64 h3 = h3.wrapping_add(result.3);
65 h4 = h4.wrapping_add(result.4);
66 buffer_len = 0;
67 }
68 }
69
70 let final_chunk2 =
71 get_final_chunks_sha(&mut buffer, total_length, buffer_len);
72
73 let result = process_chunk(&buffer, h0, h1, h2, h3, h4);
74 h0 = h0.wrapping_add(result.0);
75 h1 = h1.wrapping_add(result.1);
76 h2 = h2.wrapping_add(result.2);
77 h3 = h3.wrapping_add(result.3);
78 h4 = h4.wrapping_add(result.4);
79
80 if let Some(chunk2) = final_chunk2 {
81 let result = process_chunk(&chunk2, h0, h1, h2, h3, h4);
82 h0 = h0.wrapping_add(result.0);
83 h1 = h1.wrapping_add(result.1);
84 h2 = h2.wrapping_add(result.2);
85 h3 = h3.wrapping_add(result.3);
86 h4 = h4.wrapping_add(result.4);
87 }
88
89 let mut hh: [u8; 20] = [0; 20];
90 hh[0..4].copy_from_slice(&h0.to_be_bytes());
91 hh[4..8].copy_from_slice(&h1.to_be_bytes());
92 hh[8..12].copy_from_slice(&h2.to_be_bytes());
93 hh[12..16].copy_from_slice(&h3.to_be_bytes());
94 hh[16..20].copy_from_slice(&h4.to_be_bytes());
95
96 Ok(hh)
97}
98
99
100fn get_normalized_message_bytes(bytes: &[u8]) -> Vec<u8> {
101 let message_length: u64 = bytes.len() as u64;
102 let message_bit_length: u64 = message_length << 3;
103 let mut bytes: Vec<u8> = bytes.to_vec();
104 bytes.push(0x80);
105
106 for _ in 0..64 - (message_length + 9) % 64 {
107 bytes.push(0);
108 }
109
110 let message_length_as_bytes: [u8; 8] = message_bit_length.to_be_bytes();
111 bytes.extend_from_slice(&message_length_as_bytes);
112
113 bytes
114}
115
116fn process_chunk(
117 chunk: &[u8],
118 a: u32,
119 b: u32,
120 c: u32,
121 d: u32,
122 e: u32,
123) -> (u32, u32, u32, u32, u32) {
124 let mut chunk_u32 = [0u32; 16];
125
126 for i in 0..16 {
127 let start = i * 4;
128 chunk_u32[i] = u32::from_be_bytes([
129 chunk[start],
130 chunk[start + 1],
131 chunk[start + 2],
132 chunk[start + 3]
133 ]);
134 }
135 let mut w: [u32; 80] = [0; 80];
136 w[0..16].copy_from_slice(&chunk_u32);
137 for num in 16..80 {
138 w[num] = (w[num - 3] ^ w[num - 8] ^ w[num - 14] ^ w[num - 16]).rotate_left(1);
139 }
140
141 let mut a = a;
142 let mut b = b;
143 let mut c = c;
144 let mut d = d;
145 let mut e = e;
146 for num in 0..80 {
147 let (f, k) = match num {
148 0..=19 => {
149 let f = d ^ (b & (c ^ d));
150 (f, 0x5A827999)
151 },
152 20..=39 => {
153 let f = b ^ c ^ d;
154 (f, 0x6ED9EBA1)
155 },
156 40..=59 => {
157 let f = (b & c) ^ (d & (b ^ c));
158 (f, 0x8F1BBCDC)
159 },
160 _ => {
161 let f = b ^ c ^ d;
162 (f, 0xCA62C1D6)
163 }
164 };
165
166 let temp = a.rotate_left(5).wrapping_add(f).wrapping_add(e).wrapping_add(k).wrapping_add(w[num]);
167 e = d;
168 d = c;
169 c = b.rotate_left(30);
170 b = a;
171 a = temp;
172 }
173
174 (a, b, c, d, e)
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180 #[test]
181 fn test_get_normalized_message_bytes() {
182 let bytes = get_normalized_message_bytes("message".as_bytes());
183 let message = b"message";
185 assert_eq!(bytes.len(), 64);
186 assert_eq!(bytes[0], message[0]);
187 assert_eq!(bytes[6], message[6]);
188 assert_eq!(bytes[7], 0x80);
189 assert_eq!(bytes[8], 0x0);
190 assert_eq!(bytes[63], 56);
191 }
192
193 #[tokio::test]
194 async fn test_encode_quick_brown_fox_dog() {
195 let sha1 = encode_async("The quick brown fox jumps over the lazy dog".as_bytes()).await.unwrap();
196 assert_eq!(
198 sha1,
199 [
200 0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84, 0x9e, 0xe1, 0xbb, 0x76,
201 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12
202 ]
203 );
204 }
205
206 #[tokio::test]
207 async fn test_encode_quick_brown_fox_cog() {
208 let sha1 = encode_async("The quick brown fox jumps over the lazy cog".as_bytes()).await.unwrap();
209 assert_eq!(
211 sha1,
212 [
213 0xde, 0x9f, 0x2c, 0x7f, 0xd2, 0x5e, 0x1b, 0x3a, 0xfa, 0xd3, 0xe8, 0x5a, 0x0b, 0xd1,
214 0x7d, 0x9b, 0x10, 0x0d, 0xb4, 0xb3
215 ]
216 );
217 }
218
219 #[tokio::test]
220 async fn test_encode_empty_string() {
221 let sha1 = encode_async("".as_bytes()).await.unwrap();
222 assert_eq!(
224 sha1,
225 [
226 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60,
227 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09
228 ]
229 );
230 }
231
232 #[tokio::test]
233 async fn test_encode_message_digest() {
234 let sha1 = encode_async("message digest".as_bytes()).await.unwrap();
235 assert_eq!(
236 sha1,
237 [
238 0xc1, 0x22, 0x52, 0xce, 0xda, 0x8b, 0xe8, 0x99, 0x4d, 0x5f, 0xa0, 0x29, 0x0a, 0x47,
239 0x23, 0x1c, 0x1d, 0x16, 0xaa, 0xe3
240 ]
241 );
242 }
243
244 #[tokio::test]
245 async fn test_encode_abcdefghijklmnopqrstuvwxyz() {
246 let sha1 = encode_async("abcdefghijklmnopqrstuvwxyz".as_bytes()).await.unwrap();
247 assert_eq!(
248 sha1,
249 [
250 0x32, 0xd1, 0x0c, 0x7b, 0x8c, 0xf9, 0x65, 0x70, 0xca, 0x04, 0xce, 0x37, 0xf2, 0xa1,
251 0x9d, 0x84, 0x24, 0x0d, 0x3a, 0x89
252 ]
253 );
254 }
255
256 #[tokio::test]
257 async fn test_encode_alphanumeric_string() {
258 let sha1 = encode_async("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".as_bytes()).await.unwrap();
259 assert_eq!(
260 sha1,
261 [
262 0x76, 0x1c, 0x45, 0x7b, 0xf7, 0x3b, 0x14, 0xd2, 0x7e, 0x9e, 0x92, 0x65, 0xc4, 0x6f,
263 0x4b, 0x4d, 0xda, 0x11, 0xf9, 0x40
264 ]
265 );
266 }
267
268 #[tokio::test]
269 async fn test_encode2() {
270 let bytes = [
271 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
272 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
273 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
274 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
275 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x37, 0x66, 0x37, 0xc8, 0x92, 0x3d,
276 0xc5, 0x95, 0xe4, 0x1a, 0x27, 0x97, 0x2e, 0x99, 0x51, 0x21, 0x1d, 0x40, 0xce, 0x98,
277 ];
278 let sha1 = encode_async(bytes.as_slice()).await.unwrap();
279 assert_eq!(
280 sha1,
281 [
282 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37,
283 0x8c, 0x8e, 0xf1, 0x46, 0xbe, 0x00
284 ]
285 );
286 }
287
288}