lhash/
sha1.rs

1const BLOCK_SIZE: usize = 64;
2const STATE_SIZE: usize = 5;
3const RESULT_SIZE: usize = 20;
4const INIT_STATE: [u32; STATE_SIZE] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
5
6const K1: u32 = 0x5a827999;
7const K2: u32 = 0x6ed9eba1;
8const K3: u32 = 0x8f1bbcdc;
9const K4: u32 = 0xca62c1d6;
10
11#[inline(always)]
12const fn f1(x: u32, y: u32, z: u32) -> u32 {
13    z ^ (x & (y ^ z))
14}
15
16#[inline(always)]
17const fn f2(x: u32, y: u32, z: u32) -> u32 {
18    x ^ y ^ z
19}
20
21#[inline(always)]
22const fn f3(x: u32, y: u32, z: u32) -> u32 {
23    (x & y) | (z & (x | y))
24}
25
26#[inline(always)]
27const fn f4(x: u32, y: u32, z: u32) -> u32 {
28    x ^ y ^ z
29}
30
31macro_rules! M {
32    ($x:expr, $idx:expr, $tm:expr) => {{
33        $tm = $x[$idx & 0x0f] ^ $x[($idx-14) & 0x0f] ^ $x[($idx-8) & 0x0f] ^ $x[($idx-3) & 0x0f];
34        $x[$idx & 0x0f] = $tm.rotate_left(1);
35        $x[$idx & 0x0f]
36    }}
37}
38
39macro_rules! step {
40    ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $k:expr, $m:expr) => {{
41        $e = $e.wrapping_add($a.rotate_left(5).wrapping_add($f($b, $c, $d)).wrapping_add($k).wrapping_add($m));
42        $b = $b.rotate_left(30);
43    }}
44}
45
46const fn sha1_transform(state: [u32; STATE_SIZE], cursor: usize, input: &[u8]) -> [u32; STATE_SIZE] {
47    let mut a = state[0];
48    let mut b = state[1];
49    let mut c = state[2];
50    let mut d = state[3];
51    let mut e = state[4];
52
53    let mut tm;
54
55    let mut x = [
56        u32::from_be_bytes([input[cursor], input[cursor + 1], input[cursor + 2], input[cursor + 3]]),
57        u32::from_be_bytes([input[cursor + 4], input[cursor + 5], input[cursor + 6], input[cursor + 7]]),
58        u32::from_be_bytes([input[cursor + 8], input[cursor + 9], input[cursor + 10], input[cursor + 11]]),
59        u32::from_be_bytes([input[cursor + 12], input[cursor + 13], input[cursor + 14], input[cursor + 15]]),
60        u32::from_be_bytes([input[cursor + 16], input[cursor + 17], input[cursor + 18], input[cursor + 19]]),
61        u32::from_be_bytes([input[cursor + 20], input[cursor + 21], input[cursor + 22], input[cursor + 23]]),
62        u32::from_be_bytes([input[cursor + 24], input[cursor + 25], input[cursor + 26], input[cursor + 27]]),
63        u32::from_be_bytes([input[cursor + 28], input[cursor + 29], input[cursor + 30], input[cursor + 31]]),
64        u32::from_be_bytes([input[cursor + 32], input[cursor + 33], input[cursor + 34], input[cursor + 35]]),
65        u32::from_be_bytes([input[cursor + 36], input[cursor + 37], input[cursor + 38], input[cursor + 39]]),
66        u32::from_be_bytes([input[cursor + 40], input[cursor + 41], input[cursor + 42], input[cursor + 43]]),
67        u32::from_be_bytes([input[cursor + 44], input[cursor + 45], input[cursor + 46], input[cursor + 47]]),
68        u32::from_be_bytes([input[cursor + 48], input[cursor + 49], input[cursor + 50], input[cursor + 51]]),
69        u32::from_be_bytes([input[cursor + 52], input[cursor + 53], input[cursor + 54], input[cursor + 55]]),
70        u32::from_be_bytes([input[cursor + 56], input[cursor + 57], input[cursor + 58], input[cursor + 59]]),
71        u32::from_be_bytes([input[cursor + 60], input[cursor + 61], input[cursor + 62], input[cursor + 63]]),
72    ];
73
74    step!(a, b, c, d, e, f1, K1, x[0]);
75    step!(e, a, b, c, d, f1, K1, x[1]);
76    step!(d, e, a, b, c, f1, K1, x[2]);
77    step!(c, d, e, a, b, f1, K1, x[3]);
78    step!(b, c, d, e, a, f1, K1, x[4]);
79    step!(a, b, c, d, e, f1, K1, x[5]);
80    step!(e, a, b, c, d, f1, K1, x[6]);
81    step!(d, e, a, b, c, f1, K1, x[7]);
82    step!(c, d, e, a, b, f1, K1, x[8]);
83    step!(b, c, d, e, a, f1, K1, x[9]);
84    step!(a, b, c, d, e, f1, K1, x[10]);
85    step!(e, a, b, c, d, f1, K1, x[11]);
86    step!(d, e, a, b, c, f1, K1, x[12]);
87    step!(c, d, e, a, b, f1, K1, x[13]);
88    step!(b, c, d, e, a, f1, K1, x[14]);
89    step!(a, b, c, d, e, f1, K1, x[15]);
90    step!(e, a, b, c, d, f1, K1, M!(x, 16, tm));
91    step!(d, e, a, b, c, f1, K1, M!(x, 17, tm));
92    step!(c, d, e, a, b, f1, K1, M!(x, 18, tm));
93    step!(b, c, d, e, a, f1, K1, M!(x, 19, tm));
94    step!(a, b, c, d, e, f2, K2, M!(x, 20, tm));
95    step!(e, a, b, c, d, f2, K2, M!(x, 21, tm));
96    step!(d, e, a, b, c, f2, K2, M!(x, 22, tm));
97    step!(c, d, e, a, b, f2, K2, M!(x, 23, tm));
98    step!(b, c, d, e, a, f2, K2, M!(x, 24, tm));
99    step!(a, b, c, d, e, f2, K2, M!(x, 25, tm));
100    step!(e, a, b, c, d, f2, K2, M!(x, 26, tm));
101    step!(d, e, a, b, c, f2, K2, M!(x, 27, tm));
102    step!(c, d, e, a, b, f2, K2, M!(x, 28, tm));
103    step!(b, c, d, e, a, f2, K2, M!(x, 29, tm));
104    step!(a, b, c, d, e, f2, K2, M!(x, 30, tm));
105    step!(e, a, b, c, d, f2, K2, M!(x, 31, tm));
106    step!(d, e, a, b, c, f2, K2, M!(x, 32, tm));
107    step!(c, d, e, a, b, f2, K2, M!(x, 33, tm));
108    step!(b, c, d, e, a, f2, K2, M!(x, 34, tm));
109    step!(a, b, c, d, e, f2, K2, M!(x, 35, tm));
110    step!(e, a, b, c, d, f2, K2, M!(x, 36, tm));
111    step!(d, e, a, b, c, f2, K2, M!(x, 37, tm));
112    step!(c, d, e, a, b, f2, K2, M!(x, 38, tm));
113    step!(b, c, d, e, a, f2, K2, M!(x, 39, tm));
114    step!(a, b, c, d, e, f3, K3, M!(x, 40, tm));
115    step!(e, a, b, c, d, f3, K3, M!(x, 41, tm));
116    step!(d, e, a, b, c, f3, K3, M!(x, 42, tm));
117    step!(c, d, e, a, b, f3, K3, M!(x, 43, tm));
118    step!(b, c, d, e, a, f3, K3, M!(x, 44, tm));
119    step!(a, b, c, d, e, f3, K3, M!(x, 45, tm));
120    step!(e, a, b, c, d, f3, K3, M!(x, 46, tm));
121    step!(d, e, a, b, c, f3, K3, M!(x, 47, tm));
122    step!(c, d, e, a, b, f3, K3, M!(x, 48, tm));
123    step!(b, c, d, e, a, f3, K3, M!(x, 49, tm));
124    step!(a, b, c, d, e, f3, K3, M!(x, 50, tm));
125    step!(e, a, b, c, d, f3, K3, M!(x, 51, tm));
126    step!(d, e, a, b, c, f3, K3, M!(x, 52, tm));
127    step!(c, d, e, a, b, f3, K3, M!(x, 53, tm));
128    step!(b, c, d, e, a, f3, K3, M!(x, 54, tm));
129    step!(a, b, c, d, e, f3, K3, M!(x, 55, tm));
130    step!(e, a, b, c, d, f3, K3, M!(x, 56, tm));
131    step!(d, e, a, b, c, f3, K3, M!(x, 57, tm));
132    step!(c, d, e, a, b, f3, K3, M!(x, 58, tm));
133    step!(b, c, d, e, a, f3, K3, M!(x, 59, tm));
134    step!(a, b, c, d, e, f4, K4, M!(x, 60, tm));
135    step!(e, a, b, c, d, f4, K4, M!(x, 61, tm));
136    step!(d, e, a, b, c, f4, K4, M!(x, 62, tm));
137    step!(c, d, e, a, b, f4, K4, M!(x, 63, tm));
138    step!(b, c, d, e, a, f4, K4, M!(x, 64, tm));
139    step!(a, b, c, d, e, f4, K4, M!(x, 65, tm));
140    step!(e, a, b, c, d, f4, K4, M!(x, 66, tm));
141    step!(d, e, a, b, c, f4, K4, M!(x, 67, tm));
142    step!(c, d, e, a, b, f4, K4, M!(x, 68, tm));
143    step!(b, c, d, e, a, f4, K4, M!(x, 69, tm));
144    step!(a, b, c, d, e, f4, K4, M!(x, 70, tm));
145    step!(e, a, b, c, d, f4, K4, M!(x, 71, tm));
146    step!(d, e, a, b, c, f4, K4, M!(x, 72, tm));
147    step!(c, d, e, a, b, f4, K4, M!(x, 73, tm));
148    step!(b, c, d, e, a, f4, K4, M!(x, 74, tm));
149    step!(a, b, c, d, e, f4, K4, M!(x, 75, tm));
150    step!(e, a, b, c, d, f4, K4, M!(x, 76, tm));
151    step!(d, e, a, b, c, f4, K4, M!(x, 77, tm));
152    step!(c, d, e, a, b, f4, K4, M!(x, 78, tm));
153    step!(b, c, d, e, a, f4, K4, M!(x, 79, tm));
154
155    [
156        state[0].wrapping_add(a),
157        state[1].wrapping_add(b),
158        state[2].wrapping_add(c),
159        state[3].wrapping_add(d),
160        state[4].wrapping_add(e),
161    ]
162}
163
164///const `SHA1` algorithm implementation
165pub const fn sha1(input: &[u8]) -> [u8; RESULT_SIZE] {
166    let mut state = INIT_STATE;
167    let mut cursor = 0;
168
169    while cursor + 64 <= input.len() {
170        state = sha1_transform(state, cursor, input);
171        cursor += 64;
172    }
173
174    let mut pos = 0;
175    let mut buffer = [0; BLOCK_SIZE];
176
177    while pos < input.len() - cursor {
178        buffer[pos] = input[cursor + pos];
179        pos += 1;
180    }
181    buffer[pos] = 0x80;
182    pos += 1;
183
184    while pos != (BLOCK_SIZE - core::mem::size_of::<u64>()) {
185        pos &= BLOCK_SIZE - 1;
186
187        if pos == 0 {
188            state = sha1_transform(state, 0, &buffer);
189        }
190
191        buffer[pos] = 0;
192        pos += 1;
193    }
194
195    let len = (input.len() as u64).wrapping_shl(3).to_be_bytes();
196    buffer[pos] = len[0];
197    buffer[pos + 1] = len[1];
198    buffer[pos + 2] = len[2];
199    buffer[pos + 3] = len[3];
200    buffer[pos + 4] = len[4];
201    buffer[pos + 5] = len[5];
202    buffer[pos + 6] = len[6];
203    buffer[pos + 7] = len[7];
204
205    state = sha1_transform(state, 0, &buffer);
206
207    let a = state[0].to_be_bytes();
208    let b = state[1].to_be_bytes();
209    let c = state[2].to_be_bytes();
210    let d = state[3].to_be_bytes();
211    let e = state[4].to_be_bytes();
212    [
213        a[0], a[1], a[2], a[3],
214        b[0], b[1], b[2], b[3],
215        c[0], c[1], c[2], c[3],
216        d[0], d[1], d[2], d[3],
217        e[0], e[1], e[2], e[3],
218    ]
219}
220
221///`Sha1` algorithm implementation
222pub struct Sha1 {
223    state: [u32; STATE_SIZE],
224    len: u64,
225    buffer: [u8; BLOCK_SIZE],
226}
227
228impl Sha1 {
229    ///Creates new instance
230    pub const fn new() -> Self {
231        Self {
232            state: INIT_STATE,
233            len: 0,
234            buffer: [0; BLOCK_SIZE]
235        }
236    }
237
238    ///Resets algorithm's state.
239    pub fn reset(&mut self) {
240        *self = Self::new();
241    }
242
243    ///Hashes input
244    pub const fn const_update(mut self, input: &[u8]) -> Self {
245        let num = (self.len & (BLOCK_SIZE as u64 - 1)) as usize;
246        self.len += input.len() as u64;
247
248        let mut cursor = 0;
249
250        if num > 0 {
251            let block_num = BLOCK_SIZE - num;
252
253            if input.len() < block_num {
254                let mut idx = 0;
255                while idx < input.len() {
256                    self.buffer[num + idx] = input[idx];
257                    idx += 1;
258                }
259                return self;
260            }
261
262            let mut idx = 0;
263            while idx < block_num {
264                self.buffer[num + idx] = input[idx];
265                idx += 1;
266            }
267            self.state = sha1_transform(self.state, 0, &self.buffer);
268            cursor += block_num
269        }
270
271        while input.len() - cursor >= BLOCK_SIZE {
272            self.state = sha1_transform(self.state, cursor, input);
273            cursor += BLOCK_SIZE;
274        }
275
276        let remains = input.len() - cursor;
277        let mut idx = 0;
278        while idx < remains {
279            self.buffer[idx] = input[cursor + idx];
280            idx += 1;
281        }
282
283        self
284    }
285
286    ///Hashes input
287    pub fn update(&mut self, input: &[u8]) {
288        let mut num = (self.len & (BLOCK_SIZE as u64 - 1)) as usize;
289        self.len += input.len() as u64;
290
291        let mut cursor = 0;
292
293        if num > 0 {
294            let buffer = &mut self.buffer[num..];
295            num = BLOCK_SIZE - num;
296
297            if input.len() < num {
298                buffer[..input.len()].copy_from_slice(input);
299                return;
300            }
301
302            buffer.copy_from_slice(&input[..num]);
303            self.state = sha1_transform(self.state, 0, &self.buffer);
304            cursor += num;
305        }
306
307        while input.len() - cursor >= BLOCK_SIZE {
308            self.state = sha1_transform(self.state, cursor, input);
309            cursor += BLOCK_SIZE;
310        }
311
312        let remains = input.len() - cursor;
313        if remains > 0 {
314            self.buffer[..remains].copy_from_slice(&input[cursor..]);
315        }
316    }
317
318    ///Finalizes algorithm, returning the hash.
319    pub const fn const_result(mut self) -> [u8; RESULT_SIZE] {
320        let mut pos = (self.len & (BLOCK_SIZE as u64 - 1)) as usize;
321
322        self.buffer[pos] = 0x80;
323        pos += 1;
324
325        while pos != (BLOCK_SIZE - core::mem::size_of::<u64>()) {
326            pos &= BLOCK_SIZE - 1;
327
328            if pos == 0 {
329                self.state = sha1_transform(self.state, 0, &self.buffer);
330            }
331
332            self.buffer[pos] = 0;
333            pos += 1;
334        }
335
336        let len = self.len.wrapping_shl(3).to_be_bytes();
337        self.buffer[pos] = len[0];
338        self.buffer[pos + 1] = len[1];
339        self.buffer[pos + 2] = len[2];
340        self.buffer[pos + 3] = len[3];
341        self.buffer[pos + 4] = len[4];
342        self.buffer[pos + 5] = len[5];
343        self.buffer[pos + 6] = len[6];
344        self.buffer[pos + 7] = len[7];
345
346        self.state = sha1_transform(self.state, 0, &self.buffer);
347
348        let a = self.state[0].to_be_bytes();
349        let b = self.state[1].to_be_bytes();
350        let c = self.state[2].to_be_bytes();
351        let d = self.state[3].to_be_bytes();
352        let e = self.state[4].to_be_bytes();
353        [
354            a[0], a[1], a[2], a[3],
355            b[0], b[1], b[2], b[3],
356            c[0], c[1], c[2], c[3],
357            d[0], d[1], d[2], d[3],
358            e[0], e[1], e[2], e[3],
359        ]
360    }
361
362    ///Finalizes algorithm, returning the hash.
363    pub fn result(&mut self) -> [u8; RESULT_SIZE] {
364        let mut pos = (self.len & (BLOCK_SIZE as u64 - 1)) as usize;
365
366        self.buffer[pos] = 0x80;
367        pos += 1;
368
369        while pos != (BLOCK_SIZE - core::mem::size_of::<u64>()) {
370            pos &= BLOCK_SIZE - 1;
371
372            if pos == 0 {
373                self.state = sha1_transform(self.state, 0, &self.buffer);
374            }
375
376            self.buffer[pos] = 0;
377            pos += 1;
378        }
379
380        let len = self.len.wrapping_shl(3).to_be_bytes();
381        self.buffer[pos] = len[0];
382        self.buffer[pos + 1] = len[1];
383        self.buffer[pos + 2] = len[2];
384        self.buffer[pos + 3] = len[3];
385        self.buffer[pos + 4] = len[4];
386        self.buffer[pos + 5] = len[5];
387        self.buffer[pos + 6] = len[6];
388        self.buffer[pos + 7] = len[7];
389
390        self.state = sha1_transform(self.state, 0, &self.buffer);
391
392        let a = self.state[0].to_be_bytes();
393        let b = self.state[1].to_be_bytes();
394        let c = self.state[2].to_be_bytes();
395        let d = self.state[3].to_be_bytes();
396        let e = self.state[4].to_be_bytes();
397        [
398            a[0], a[1], a[2], a[3],
399            b[0], b[1], b[2], b[3],
400            c[0], c[1], c[2], c[3],
401            d[0], d[1], d[2], d[3],
402            e[0], e[1], e[2], e[3],
403        ]
404    }
405}
406
407impl super::Digest for Sha1 {
408    type OutputType = [u8; RESULT_SIZE];
409    type BlockType = [u8; BLOCK_SIZE];
410
411    #[inline(always)]
412    fn new() -> Self {
413        Self::new()
414    }
415
416    #[inline(always)]
417    fn reset(&mut self) {
418        self.reset();
419    }
420
421    #[inline(always)]
422    fn update(&mut self, input: &[u8]) {
423        self.update(input);
424    }
425
426    #[inline(always)]
427    fn result(&mut self) -> Self::OutputType {
428        self.result()
429    }
430}