1use crate::sha256::{encode_core, get_final_chunks_sha, process_chunk};
2use futures::io::{AsyncRead, AsyncReadExt};
3
4const H: [u32; 8] = [
5 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,
6];
7
8pub fn encode(bytes: &[u8]) -> [u8; 28] {
9 let h: [u32; 8] = encode_core(bytes, H);
10 let mut hh: [u8; 28] = [0; 28];
11 for i in 0..7 {
12 let start_index = i << 2;
13 hh[start_index..start_index + 4].copy_from_slice(&h[i].to_be_bytes());
14 }
15
16 hh
17}
18
19pub async fn encode_async<R>(mut reader: R) -> Result<[u8; 28], std::io::Error>
20where
21 R: AsyncRead + Unpin,
22{
23 let mut h = H;
24 let mut buffer = [0u8; 64];
25 let mut buffer_len = 0;
26 let mut total_length = 0;
27
28 loop {
29 let bytes_read = reader.read(&mut buffer[buffer_len..]).await?;
30 if bytes_read == 0 {
31 break;
32 }
33
34 buffer_len += bytes_read;
35 total_length += bytes_read;
36
37 if buffer_len == 64 {
38 let result =
39 process_chunk(&buffer[..64], &h);
40 for i in 0..8 {
41 h[i] = h[i].wrapping_add(result[i]);
42 }
43 buffer_len = 0;
44 }
45 }
46
47 let final_chunk2 =
48 get_final_chunks_sha(&mut buffer, total_length, buffer_len);
49
50 let result = process_chunk(&buffer, &h);
51 for i in 0..8 {
52 h[i] = h[i].wrapping_add(result[i]);
53 }
54
55 if let Some(chunk2) = final_chunk2 {
56 let result = process_chunk(&chunk2, &h);
57 for i in 0..8 {
58 h[i] = h[i].wrapping_add(result[i]);
59 }
60 }
61
62 let mut hh: [u8; 28] = [0; 28];
63 for i in 0..7 {
64 let start_index = i << 2;
65 hh[start_index..start_index + 4].copy_from_slice(&h[i].to_be_bytes());
66 }
67
68 Ok(hh)
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[tokio::test]
76 async fn test_encode_empty_string() {
77 let result = encode_async("".as_bytes()).await.unwrap();
78 assert_eq!(
79 result,
80 [
81 0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, 0x47, 0x61, 0x02, 0xbb, 0x28, 0x82,
82 0x34, 0xc4, 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, 0xc5, 0xb3, 0xe4, 0x2f
83 ]
84 );
85 }
86
87 #[tokio::test]
88 async fn test_encode_abc() {
89 let result = encode_async("abc".as_bytes()).await.unwrap();
90 assert_eq!(
91 result,
92 [
93 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2,
94 0x55, 0xB3, 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, 0xE3, 0x6C, 0x9D, 0xA7
95 ]
96 );
97 }
98
99 #[tokio::test]
100 async fn test_encode_message_digest() {
101 let result = encode_async("message digest".as_bytes()).await.unwrap();
102 assert_eq!(
103 result,
104 [
105 0x2c, 0xb2, 0x1c, 0x83, 0xae, 0x2f, 0x00, 0x4d, 0xe7, 0xe8, 0x1c, 0x3c, 0x70, 0x19,
106 0xcb, 0xcb, 0x65, 0xb7, 0x1a, 0xb6, 0x56, 0xb2, 0x2d, 0x6d, 0x0c, 0x39, 0xb8, 0xeb
107 ]
108 );
109 }
110
111 #[tokio::test]
112 async fn test_encode_abcdefghijklmnopqrstuvwxyz() {
113 let result = encode_async("abcdefghijklmnopqrstuvwxyz".as_bytes()).await.unwrap();
114 assert_eq!(
115 result,
116 [
117 0x45, 0xa5, 0xf7, 0x2c, 0x39, 0xc5, 0xcf, 0xf2, 0x52, 0x2e, 0xb3, 0x42, 0x97, 0x99,
118 0xe4, 0x9e, 0x5f, 0x44, 0xb3, 0x56, 0xef, 0x92, 0x6b, 0xcf, 0x39, 0x0d, 0xcc, 0xc2
119 ]
120 );
121 }
122
123 #[tokio::test]
124 async fn test_encode_alphanumeric_string() {
125 let result = encode_async("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".as_bytes()).await.unwrap();
126 assert_eq!(
127 result,
128 [
129 0xbf, 0xf7, 0x2b, 0x4f, 0xcb, 0x7d, 0x75, 0xe5, 0x63, 0x29, 0x00, 0xac, 0x5f, 0x90,
130 0xd2, 0x19, 0xe0, 0x5e, 0x97, 0xa7, 0xbd, 0xe7, 0x2e, 0x74, 0x0d, 0xb3, 0x93, 0xd9
131 ]
132 );
133 }
134
135 #[tokio::test]
136 async fn test_encode_abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq() {
137 let result = encode_async("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".as_bytes()).await.unwrap();
138 assert_eq!(
139 result,
140 [
141 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89,
142 0x01, 0x50, 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, 0x52, 0x52, 0x25, 0x25
143 ]
144 );
145 }
146
147 #[tokio::test]
148 async fn test_encode_million_a() {
149 let result = encode_async(vec!["a".as_bytes()[0]; 1000000].as_slice()).await.unwrap();
150 assert_eq!(
151 result,
152 [
153 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61,
154 0x8A, 0x4B, 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, 0x4E, 0xE7, 0xAD, 0x67
155 ]
156 );
157 }
158
159 #[tokio::test]
160 async fn test_encode_repeated_pattern() {
161 let result = encode_async(
162 vec!["01234567012345670123456701234567"; 20]
163 .join("")
164 .as_bytes(),
165 ).await.unwrap();
166 assert_eq!(
167 result,
168 [
169 0x56, 0x7F, 0x69, 0xF1, 0x68, 0xCD, 0x78, 0x44, 0xE6, 0x52, 0x59, 0xCE, 0x65, 0x8F,
170 0xE7, 0xAA, 0xDF, 0xA2, 0x52, 0x16, 0xE6, 0x8E, 0xCA, 0x0E, 0xB7, 0xAB, 0x82, 0x62
171 ]
172 );
173 }
174
175 #[tokio::test]
176 async fn test_encode_single_byte_07() {
177 let result = encode_async([0x07].as_slice()).await.unwrap();
178 assert_eq!(
179 result,
180 [
181 0x00, 0xEC, 0xD5, 0xF1, 0x38, 0x42, 0x2B, 0x8A, 0xD7, 0x4C, 0x97, 0x99, 0xFD, 0x82,
182 0x6C, 0x53, 0x1B, 0xAD, 0x2F, 0xCA, 0xBC, 0x74, 0x50, 0xBE, 0xE2, 0xAA, 0x8C, 0x2A
183 ]
184 );
185 }
186
187 #[tokio::test]
188 async fn test_encode_16_byte_array() {
189 let result = encode_async([
190 0x18, 0x80, 0x40, 0x05, 0xdd, 0x4f, 0xbd, 0x15, 0x56, 0x29, 0x9d, 0x6f, 0x9d, 0x93,
191 0xdf, 0x62,
192 ].as_slice()).await.unwrap();
193 assert_eq!(
194 result,
195 [
196 0xDF, 0x90, 0xD7, 0x8A, 0xA7, 0x88, 0x21, 0xC9, 0x9B, 0x40, 0xBA, 0x4C, 0x96, 0x69,
197 0x21, 0xAC, 0xCD, 0x8F, 0xFB, 0x1E, 0x98, 0xAC, 0x38, 0x8E, 0x56, 0x19, 0x1D, 0xB1
198 ]
199 );
200 }
201
202 #[tokio::test]
203 async fn test_encode_large_byte_array() {
204 let result = encode_async([
205 0x55, 0xb2, 0x10, 0x07, 0x9c, 0x61, 0xb5, 0x3a, 0xdd, 0x52, 0x06, 0x22, 0xd1, 0xac,
206 0x97, 0xd5, 0xcd, 0xbe, 0x8c, 0xb3, 0x3a, 0xa0, 0xae, 0x34, 0x45, 0x17, 0xbe, 0xe4,
207 0xd7, 0xba, 0x09, 0xab, 0xc8, 0x53, 0x3c, 0x52, 0x50, 0x88, 0x7a, 0x43, 0xbe, 0xbb,
208 0xac, 0x90, 0x6c, 0x2e, 0x18, 0x37, 0xf2, 0x6b, 0x36, 0xa5, 0x9a, 0xe3, 0xbe, 0x78,
209 0x14, 0xd5, 0x06, 0x89, 0x6b, 0x71, 0x8b, 0x2a, 0x38, 0x3e, 0xcd, 0xac, 0x16, 0xb9,
210 0x61, 0x25, 0x55, 0x3f, 0x41, 0x6f, 0xf3, 0x2c, 0x66, 0x74, 0xc7, 0x45, 0x99, 0xa9,
211 0x00, 0x53, 0x86, 0xd9, 0xce, 0x11, 0x12, 0x24, 0x5f, 0x48, 0xee, 0x47, 0x0d, 0x39,
212 0x6c, 0x1e, 0xd6, 0x3b, 0x92, 0x67, 0x0c, 0xa5, 0x6e, 0xc8, 0x4d, 0xee, 0xa8, 0x14,
213 0xb6, 0x13, 0x5e, 0xca, 0x54, 0x39, 0x2b, 0xde, 0xdb, 0x94, 0x89, 0xbc, 0x9b, 0x87,
214 0x5a, 0x8b, 0xaf, 0x0d, 0xc1, 0xae, 0x78, 0x57, 0x36, 0x91, 0x4a, 0xb7, 0xda, 0xa2,
215 0x64, 0xbc, 0x07, 0x9d, 0x26, 0x9f, 0x2c, 0x0d, 0x7e, 0xdd, 0xd8, 0x10, 0xa4, 0x26,
216 0x14, 0x5a, 0x07, 0x76, 0xf6, 0x7c, 0x87, 0x82, 0x73,
217 ].as_slice()).await.unwrap();
218 assert_eq!(
219 result,
220 [
221 0x0B, 0x31, 0x89, 0x4E, 0xC8, 0x93, 0x7A, 0xD9, 0xB9, 0x1B, 0xDF, 0xBC, 0xBA, 0x29,
222 0x4D, 0x9A, 0xDE, 0xFA, 0xA1, 0x8E, 0x09, 0x30, 0x5E, 0x9F, 0x20, 0xD5, 0xC3, 0xA4
223 ]
224 );
225 }
226
227}