1use crate::sha512::{encode_core, get_final_chunks_sha2, process_chunk};
2use futures::io::{AsyncRead, AsyncReadExt};
3
4const H: [u64; 8] = [
5 0xcbbb9d5dc1059ed8,
6 0x629a292a367cd507,
7 0x9159015a3070dd17,
8 0x152fecd8f70e5939,
9 0x67332667ffc00b31,
10 0x8eb44a8768581511,
11 0xdb0c2e0d64f98fa7,
12 0x47b5481dbefa4fa4,
13];
14
15pub fn encode(bytes: &[u8]) -> [u8; 48] {
16 let h: [u64; 8] = encode_core(bytes, H);
17 let mut hh: [u8; 48] = [0; 48];
18 for i in 0..6 {
19 let start_index = i << 3;
20 hh[start_index..start_index + 8].copy_from_slice(&h[i].to_be_bytes());
21 }
22
23 hh
24}
25
26
27pub async fn encode_async<R>(mut reader: R) -> Result<[u8; 48], std::io::Error>
28where
29 R: AsyncRead + Unpin,
30{
31 let mut h = H;
32 let mut buffer = [0u8; 128];
33 let mut buffer_len = 0;
34 let mut total_length = 0;
35
36 loop {
37 let bytes_read = reader.read(&mut buffer[buffer_len..]).await?;
38 if bytes_read == 0 {
39 break;
40 }
41
42 buffer_len += bytes_read;
43 total_length += bytes_read;
44
45 if buffer_len == 128 {
46 let result = process_chunk(&buffer[..buffer_len], &h);
47 for i in 0..8 {
48 h[i] = h[i].wrapping_add(result[i]);
49 }
50 buffer_len = 0;
51 }
52 }
53
54 let final_chunk2 =
55 get_final_chunks_sha2(&mut buffer, total_length, buffer_len);
56
57 let result = process_chunk(&buffer, &h);
58 for i in 0..8 {
59 h[i] = h[i].wrapping_add(result[i]);
60 }
61 if let Some(chunk2) = final_chunk2 {
62 let result = process_chunk(&chunk2, &h);
63 for i in 0..8 {
64 h[i] = h[i].wrapping_add(result[i]);
65 }
66 }
67
68 let mut hh = [0u8; 48];
69 for i in 0..6 {
70 let start_index = i << 3;
71 hh[start_index..start_index + 8].copy_from_slice(&h[i].to_be_bytes());
72 }
73
74 Ok(hh)
75}
76
77
78
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn test_encode_empty_string() {
86 let result = encode("".as_bytes());
87 assert_eq!(
88 result,
89 [
90 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1,
91 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf,
92 0x63, 0xf6, 0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a,
93 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b
94 ]
95 );
96 }
97
98 #[test]
99 fn test_encode_abc() {
100 let result = encode("abc".as_bytes());
101 assert_eq!(
102 result,
103 [
104 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6,
105 0x50, 0x07, 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, 0x1a, 0x8b, 0x60, 0x5a,
106 0x43, 0xff, 0x5b, 0xed, 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, 0x58, 0xba,
107 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7
108 ]
109 );
110 }
111
112 #[test]
113 fn test_encode_message_digest() {
114 let result = encode("message digest".as_bytes());
115 assert_eq!(
116 result,
117 [
118 0x47, 0x3e, 0xd3, 0x51, 0x67, 0xec, 0x1f, 0x5d, 0x8e, 0x55, 0x03, 0x68, 0xa3, 0xdb,
119 0x39, 0xbe, 0x54, 0x63, 0x9f, 0x82, 0x88, 0x68, 0xe9, 0x45, 0x4c, 0x23, 0x9f, 0xc8,
120 0xb5, 0x2e, 0x3c, 0x61, 0xdb, 0xd0, 0xd8, 0xb4, 0xde, 0x13, 0x90, 0xc2, 0x56, 0xdc,
121 0xbb, 0x5d, 0x5f, 0xd9, 0x9c, 0xd5
122 ]
123 );
124 }
125
126 #[test]
127 fn test_encode_abcdefghijklmnopqrstuvwxyz() {
128 let result = encode("abcdefghijklmnopqrstuvwxyz".as_bytes());
129 assert_eq!(
130 result,
131 [
132 0xfe, 0xb6, 0x73, 0x49, 0xdf, 0x3d, 0xb6, 0xf5, 0x92, 0x48, 0x15, 0xd6, 0xc3, 0xdc,
133 0x13, 0x3f, 0x09, 0x18, 0x09, 0x21, 0x37, 0x31, 0xfe, 0x5c, 0x7b, 0x5f, 0x49, 0x99,
134 0xe4, 0x63, 0x47, 0x9f, 0xf2, 0x87, 0x7f, 0x5f, 0x29, 0x36, 0xfa, 0x63, 0xbb, 0x43,
135 0x78, 0x4b, 0x12, 0xf3, 0xeb, 0xb4
136 ]
137 );
138 }
139
140 #[test]
141 fn test_encode_alphanumeric_string() {
142 let result = encode("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".as_bytes());
143 assert_eq!(
144 result,
145 [
146 0x17, 0x61, 0x33, 0x6e, 0x3f, 0x7c, 0xbf, 0xe5, 0x1d, 0xeb, 0x13, 0x7f, 0x02, 0x6f,
147 0x89, 0xe0, 0x1a, 0x44, 0x8e, 0x3b, 0x1f, 0xaf, 0xa6, 0x40, 0x39, 0xc1, 0x46, 0x4e,
148 0xe8, 0x73, 0x2f, 0x11, 0xa5, 0x34, 0x1a, 0x6f, 0x41, 0xe0, 0xc2, 0x02, 0x29, 0x47,
149 0x36, 0xed, 0x64, 0xdb, 0x1a, 0x84
150 ]
151 );
152 }
153
154 #[test]
155 fn test_encode_12345() {
156 let result = encode("12345".as_bytes());
157 assert_eq!(
158 result,
159 [
160 0x0f, 0xa7, 0x69, 0x55, 0xab, 0xfa, 0x9d, 0xaf, 0xd8, 0x3f, 0xac, 0xca, 0x83, 0x43,
161 0xa9, 0x2a, 0xa0, 0x94, 0x97, 0xf9, 0x81, 0x01, 0x08, 0x66, 0x11, 0xb0, 0xbf, 0xa9,
162 0x5d, 0xbc, 0x0d, 0xcc, 0x66, 0x1d, 0x62, 0xe9, 0x56, 0x8a, 0x5a, 0x03, 0x2b, 0xa8,
163 0x19, 0x60, 0xf3, 0xe5, 0x5d, 0x4a
164 ]
165 );
166 }
167
168 #[test]
169 fn test_encode_long_string() {
170 let result = encode(b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
171 assert_eq!(
172 result,
173 [
174 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd,
175 0x1b, 0x47, 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, 0x2f, 0xa0, 0x80, 0x86,
176 0xe3, 0xb0, 0xf7, 0x12, 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, 0x66, 0xc3,
177 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39
178 ]
179 );
180 }
181
182 #[test]
183 fn test_encode_million_a() {
184 let result = encode(&vec!["a".as_bytes()[0]; 1000000]);
185 assert_eq!(
186 result,
187 [
188 0x9d, 0x0e, 0x18, 0x09, 0x71, 0x64, 0x74, 0xcb, 0x08, 0x6e, 0x83, 0x4e, 0x31, 0x0a,
189 0x4a, 0x1c, 0xed, 0x14, 0x9e, 0x9c, 0x00, 0xf2, 0x48, 0x52, 0x79, 0x72, 0xce, 0xc5,
190 0x70, 0x4c, 0x2a, 0x5b, 0x07, 0xb8, 0xb3, 0xdc, 0x38, 0xec, 0xc4, 0xeb, 0xae, 0x97,
191 0xdd, 0xd8, 0x7f, 0x3d, 0x89, 0x85
192 ]
193 );
194 }
195
196 #[test]
197 fn test_encode_repeated_pattern() {
198 let result = encode(
199 vec!["01234567012345670123456701234567"; 20]
200 .join("")
201 .as_bytes(),
202 );
203 assert_eq!(
204 result,
205 [
206 0x2f, 0xc6, 0x4a, 0x4f, 0x50, 0x0d, 0xdb, 0x68, 0x28, 0xf6, 0xa3, 0x43, 0x0b, 0x8d,
207 0xd7, 0x2a, 0x36, 0x8e, 0xb7, 0xf3, 0xa8, 0x32, 0x2a, 0x70, 0xbc, 0x84, 0x27, 0x5b,
208 0x9c, 0x0b, 0x3a, 0xb0, 0x0d, 0x27, 0xa5, 0xcc, 0x3c, 0x2d, 0x22, 0x4a, 0xa6, 0xb6,
209 0x1a, 0x0d, 0x79, 0xfb, 0x45, 0x96
210 ]
211 );
212 }
213
214 #[test]
215 fn test_encode_single_byte_b9() {
216 let result = encode(&[0xb9]);
217 assert_eq!(
218 result,
219 [
220 0xbc, 0x80, 0x89, 0xa1, 0x90, 0x07, 0xc0, 0xb1, 0x41, 0x95, 0xf4, 0xec, 0xc7, 0x40,
221 0x94, 0xfe, 0xc6, 0x4f, 0x01, 0xf9, 0x09, 0x29, 0x28, 0x2c, 0x2f, 0xb3, 0x92, 0x88,
222 0x15, 0x78, 0x20, 0x8a, 0xd4, 0x66, 0x82, 0x8b, 0x1c, 0x6c, 0x28, 0x3d, 0x27, 0x22,
223 0xcf, 0x0a, 0xd1, 0xab, 0x69, 0x38
224 ]
225 );
226 }
227
228 #[test]
229 fn test_encode_16_byte_array() {
230 let result = encode(&[
231 0xa4, 0x1c, 0x49, 0x77, 0x79, 0xc0, 0x37, 0x5f, 0xf1, 0x0a, 0x7f, 0x4e, 0x08, 0x59,
232 0x17, 0x39,
233 ]);
234 assert_eq!(
235 result,
236 [
237 0xc9, 0xa6, 0x84, 0x43, 0xa0, 0x05, 0x81, 0x22, 0x56, 0xb8, 0xec, 0x76, 0xb0, 0x05,
238 0x16, 0xf0, 0xdb, 0xb7, 0x4f, 0xab, 0x26, 0xd6, 0x65, 0x91, 0x3f, 0x19, 0x4b, 0x6f,
239 0xfb, 0x0e, 0x91, 0xea, 0x99, 0x67, 0x56, 0x6b, 0x58, 0x10, 0x9c, 0xbc, 0x67, 0x5c,
240 0xc2, 0x08, 0xe4, 0xc8, 0x23, 0xf7
241 ]
242 );
243 }
244
245 #[test]
246 fn test_encode_large_byte_array() {
247 let result = encode(&[
248 0x39, 0x96, 0x69, 0xe2, 0x8f, 0x6b, 0x9c, 0x6d, 0xbc, 0xbb, 0x69, 0x12, 0xec, 0x10,
249 0xff, 0xcf, 0x74, 0x79, 0x03, 0x49, 0xb7, 0xdc, 0x8f, 0xbe, 0x4a, 0x8e, 0x7b, 0x3b,
250 0x56, 0x21, 0xdb, 0x0f, 0x3e, 0x7d, 0xc8, 0x7f, 0x82, 0x32, 0x64, 0xbb, 0xe4, 0x0d,
251 0x18, 0x11, 0xc9, 0xea, 0x20, 0x61, 0xe1, 0xc8, 0x4a, 0xd1, 0x0a, 0x23, 0xfa, 0xc1,
252 0x72, 0x7e, 0x72, 0x02, 0xfc, 0x3f, 0x50, 0x42, 0xe6, 0xbf, 0x58, 0xcb, 0xa8, 0xa2,
253 0x74, 0x6e, 0x1f, 0x64, 0xf9, 0xb9, 0xea, 0x35, 0x2c, 0x71, 0x15, 0x07, 0x05, 0x3c,
254 0xf4, 0xe5, 0x33, 0x9d, 0x52, 0x86, 0x5f, 0x25, 0xcc, 0x22, 0xb5, 0xe8, 0x77, 0x84,
255 0xa1, 0x2f, 0xc9, 0x61, 0xd6, 0x6c, 0xb6, 0xe8, 0x95, 0x73, 0x19, 0x9a, 0x2c, 0xe6,
256 0x56, 0x5c, 0xbd, 0xf1, 0x3d, 0xca, 0x40, 0x38, 0x32, 0xcf, 0xcb, 0x0e, 0x8b, 0x72,
257 0x11, 0xe8, 0x3a, 0xf3, 0x2a, 0x11, 0xac, 0x17, 0x92, 0x9f, 0xf1, 0xc0, 0x73, 0xa5,
258 0x1c, 0xc0, 0x27, 0xaa, 0xed, 0xef, 0xf8, 0x5a, 0xad, 0x7c, 0x2b, 0x7c, 0x5a, 0x80,
259 0x3e, 0x24, 0x04, 0xd9, 0x6d, 0x2a, 0x77, 0x35, 0x7b, 0xda, 0x1a, 0x6d, 0xae, 0xed,
260 0x17, 0x15, 0x1c, 0xb9, 0xbc, 0x51, 0x25, 0xa4, 0x22, 0xe9, 0x41, 0xde, 0x0c, 0xa0,
261 0xfc, 0x50, 0x11, 0xc2, 0x3e, 0xcf, 0xfe, 0xfd, 0xd0, 0x96, 0x76, 0x71, 0x1c, 0xf3,
262 0xdb, 0x0a, 0x34, 0x40, 0x72, 0x0e, 0x16, 0x15, 0xc1, 0xf2, 0x2f, 0xbc, 0x3c, 0x72,
263 0x1d, 0xe5, 0x21, 0xe1, 0xb9, 0x9b, 0xa1, 0xbd, 0x55, 0x77, 0x40, 0x86, 0x42, 0x14,
264 0x7e, 0xd0, 0x96,
265 ]);
266 assert_eq!(
267 result,
268 [
269 0x4f, 0x44, 0x0d, 0xb1, 0xe6, 0xed, 0xd2, 0x89, 0x9f, 0xa3, 0x35, 0xf0, 0x95, 0x15,
270 0xaa, 0x02, 0x5e, 0xe1, 0x77, 0xa7, 0x9f, 0x4b, 0x4a, 0xaf, 0x38, 0xe4, 0x2b, 0x5c,
271 0x4d, 0xe6, 0x60, 0xf5, 0xde, 0x8f, 0xb2, 0xa5, 0xb2, 0xfb, 0xd2, 0xa3, 0xcb, 0xff,
272 0xd2, 0x0c, 0xff, 0x12, 0x88, 0xc0
273 ]
274 );
275 }
276
277 #[tokio::test]
278 async fn test_encode_async() {
279 let data = "The quick brown fox jumps over the lazy dog".as_bytes();
280 let async_result = encode_async(data).await.unwrap();
281 let sync_result = encode(data);
282 assert_eq!(async_result, sync_result);
283 }
284
285}