crypto_async_rs/
sha1.rs

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    //break message into 512 - bit chunks (64 bytes = 2^6)
14    for chunk_num in 0..(bytes.len() >> 6) {
15        //break chunk into sixteen 32 - bit big - endian words
16        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        //println!("message {:?}", b"message");
184        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        //2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
197        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        //de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3
210        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        //da39a3ee5e6b4b0d3255bfef95601890afd80709
223        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}