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
164pub 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
221pub struct Sha1 {
223 state: [u32; STATE_SIZE],
224 len: u64,
225 buffer: [u8; BLOCK_SIZE],
226}
227
228impl Sha1 {
229 pub const fn new() -> Self {
231 Self {
232 state: INIT_STATE,
233 len: 0,
234 buffer: [0; BLOCK_SIZE]
235 }
236 }
237
238 pub fn reset(&mut self) {
240 *self = Self::new();
241 }
242
243 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 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 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 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}