1#![allow(clippy::many_single_char_names)]
2
3pub const fn sha1(data: &ConstBuffer) -> Digest {
4 let state: [u32; 5] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
5 let len: u64 = 0;
6 let blocks: Blocks = Blocks { len: 0, data: [0; 64] };
7 let (blocks: Blocks, len: u64, state: [u32; 5]) = process_blocks(blocks, data, len, state);
8 digest(state, len, blocks)
9}
10
11const BUFFER_SIZE: usize = 1024;
12
13pub struct ConstBuffer {
14 data: [u8; BUFFER_SIZE],
15 head: usize,
16}
17
18impl ConstBuffer {
19 pub const fn from_slice(slice: &[u8]) -> Self {
20 let s = Self::new();
21 s.push_slice(slice)
22 }
23
24 pub const fn new() -> Self {
25 Self { data: [0; BUFFER_SIZE], head: 0 }
26 }
27
28 pub const fn push_slice(self, slice: &[u8]) -> Self {
29 self.push_amount(slice, slice.len())
30 }
31
32 const fn get(&self, index: usize) -> u8 {
33 self.data[index]
34 }
35
36 const fn len(&self) -> usize {
37 self.head
38 }
39
40 const fn as_slice(&self) -> &[u8] {
41 &self.data
42 }
43
44 pub const fn push_other(self, other: Self) -> Self {
45 self.push_amount(other.as_slice(), other.len())
46 }
47
48 const fn push_amount(mut self, slice: &[u8], amount: usize) -> Self {
49 let mut i = 0;
50 while i < amount {
51 self.data[self.head + i] = slice[i];
52 i += 1;
53 }
54 self.head += i;
55 self
56 }
57}
58
59struct Blocks {
60 len: u32,
61 data: [u8; 64],
62}
63
64const fn process_blocks(mut blocks: Blocks, data: &ConstBuffer, mut len: u64, mut state: [u32; 5]) -> (Blocks, u64, [u32; 5]) {
65 const fn as_block(input: &ConstBuffer, offset: usize) -> [u32; 16] {
66 let mut result = [0u32; 16];
67
68 let mut i = 0;
69 while i != 16 {
70 let off = offset + (i * 4);
71 result[i] = (input.get(off + 3) as u32) | ((input.get(off + 2) as u32) << 8) | ((input.get(off + 1) as u32) << 16) | ((input.get(off) as u32) << 24);
72 i += 1;
73 }
74 result
75 }
76
77 const fn clone_from_slice_64(mut data: [u8; 64], slice: &[u8], offset: usize, num_elems: usize) -> [u8; 64] {
78 let mut i = 0;
79 while i < num_elems {
80 data[i] = slice[offset + i];
81 i += 1;
82 }
83 data
84 }
85
86 let mut i = 0;
87 while i < data.len() {
88 if data.len() - i >= 64 {
89 let chunk_block = as_block(data, i);
90 len += 64;
91 state = process_state(state, chunk_block);
92 i += 64;
93 } else {
94 let num_elems = data.len() - i;
95 blocks.data = clone_from_slice_64(blocks.data, data.as_slice(), i, num_elems);
96 blocks.len = num_elems as u32;
97 break;
98 }
99 }
100 (blocks, len, state)
101}
102
103const fn process_state(mut state: [u32; 5], block: [u32; 16]) -> [u32; 5] {
104 let a = state[0];
105 let b = state[1];
106 let c = state[2];
107 let d = state[3];
108 let e = state[4];
109 let (block, b, e) = r0(block, a, b, c, d, e, 0);
110 let (block, a, d) = r0(block, e, a, b, c, d, 1);
111 let (block, e, c) = r0(block, d, e, a, b, c, 2);
112 let (block, d, b) = r0(block, c, d, e, a, b, 3);
113 let (block, c, a) = r0(block, b, c, d, e, a, 4);
114 let (block, b, e) = r0(block, a, b, c, d, e, 5);
115 let (block, a, d) = r0(block, e, a, b, c, d, 6);
116 let (block, e, c) = r0(block, d, e, a, b, c, 7);
117 let (block, d, b) = r0(block, c, d, e, a, b, 8);
118 let (block, c, a) = r0(block, b, c, d, e, a, 9);
119 let (block, b, e) = r0(block, a, b, c, d, e, 10);
120 let (block, a, d) = r0(block, e, a, b, c, d, 11);
121 let (block, e, c) = r0(block, d, e, a, b, c, 12);
122 let (block, d, b) = r0(block, c, d, e, a, b, 13);
123 let (block, c, a) = r0(block, b, c, d, e, a, 14);
124 let (block, b, e) = r0(block, a, b, c, d, e, 15);
125 let (block, a, d) = r1(block, e, a, b, c, d, 0);
126 let (block, e, c) = r1(block, d, e, a, b, c, 1);
127 let (block, d, b) = r1(block, c, d, e, a, b, 2);
128 let (block, c, a) = r1(block, b, c, d, e, a, 3);
129 let (block, b, e) = r2(block, a, b, c, d, e, 4);
130 let (block, a, d) = r2(block, e, a, b, c, d, 5);
131 let (block, e, c) = r2(block, d, e, a, b, c, 6);
132 let (block, d, b) = r2(block, c, d, e, a, b, 7);
133 let (block, c, a) = r2(block, b, c, d, e, a, 8);
134 let (block, b, e) = r2(block, a, b, c, d, e, 9);
135 let (block, a, d) = r2(block, e, a, b, c, d, 10);
136 let (block, e, c) = r2(block, d, e, a, b, c, 11);
137 let (block, d, b) = r2(block, c, d, e, a, b, 12);
138 let (block, c, a) = r2(block, b, c, d, e, a, 13);
139 let (block, b, e) = r2(block, a, b, c, d, e, 14);
140 let (block, a, d) = r2(block, e, a, b, c, d, 15);
141 let (block, e, c) = r2(block, d, e, a, b, c, 0);
142 let (block, d, b) = r2(block, c, d, e, a, b, 1);
143 let (block, c, a) = r2(block, b, c, d, e, a, 2);
144 let (block, b, e) = r2(block, a, b, c, d, e, 3);
145 let (block, a, d) = r2(block, e, a, b, c, d, 4);
146 let (block, e, c) = r2(block, d, e, a, b, c, 5);
147 let (block, d, b) = r2(block, c, d, e, a, b, 6);
148 let (block, c, a) = r2(block, b, c, d, e, a, 7);
149 let (block, b, e) = r3(block, a, b, c, d, e, 8);
150 let (block, a, d) = r3(block, e, a, b, c, d, 9);
151 let (block, e, c) = r3(block, d, e, a, b, c, 10);
152 let (block, d, b) = r3(block, c, d, e, a, b, 11);
153 let (block, c, a) = r3(block, b, c, d, e, a, 12);
154 let (block, b, e) = r3(block, a, b, c, d, e, 13);
155 let (block, a, d) = r3(block, e, a, b, c, d, 14);
156 let (block, e, c) = r3(block, d, e, a, b, c, 15);
157 let (block, d, b) = r3(block, c, d, e, a, b, 0);
158 let (block, c, a) = r3(block, b, c, d, e, a, 1);
159 let (block, b, e) = r3(block, a, b, c, d, e, 2);
160 let (block, a, d) = r3(block, e, a, b, c, d, 3);
161 let (block, e, c) = r3(block, d, e, a, b, c, 4);
162 let (block, d, b) = r3(block, c, d, e, a, b, 5);
163 let (block, c, a) = r3(block, b, c, d, e, a, 6);
164 let (block, b, e) = r3(block, a, b, c, d, e, 7);
165 let (block, a, d) = r3(block, e, a, b, c, d, 8);
166 let (block, e, c) = r3(block, d, e, a, b, c, 9);
167 let (block, d, b) = r3(block, c, d, e, a, b, 10);
168 let (block, c, a) = r3(block, b, c, d, e, a, 11);
169 let (block, b, e) = r4(block, a, b, c, d, e, 12);
170 let (block, a, d) = r4(block, e, a, b, c, d, 13);
171 let (block, e, c) = r4(block, d, e, a, b, c, 14);
172 let (block, d, b) = r4(block, c, d, e, a, b, 15);
173 let (block, c, a) = r4(block, b, c, d, e, a, 0);
174 let (block, b, e) = r4(block, a, b, c, d, e, 1);
175 let (block, a, d) = r4(block, e, a, b, c, d, 2);
176 let (block, e, c) = r4(block, d, e, a, b, c, 3);
177 let (block, d, b) = r4(block, c, d, e, a, b, 4);
178 let (block, c, a) = r4(block, b, c, d, e, a, 5);
179 let (block, b, e) = r4(block, a, b, c, d, e, 6);
180 let (block, a, d) = r4(block, e, a, b, c, d, 7);
181 let (block, e, c) = r4(block, d, e, a, b, c, 8);
182 let (block, d, b) = r4(block, c, d, e, a, b, 9);
183 let (block, c, a) = r4(block, b, c, d, e, a, 10);
184 let (block, b, e) = r4(block, a, b, c, d, e, 11);
185 let (block, a, d) = r4(block, e, a, b, c, d, 12);
186 let (block, e, c) = r4(block, d, e, a, b, c, 13);
187 let (block, d, b) = r4(block, c, d, e, a, b, 14);
188 let (_, c, a) = r4(block, b, c, d, e, a, 15);
189
190 state[0] = state[0].wrapping_add(a);
191 state[1] = state[1].wrapping_add(b);
192 state[2] = state[2].wrapping_add(c);
193 state[3] = state[3].wrapping_add(d);
194 state[4] = state[4].wrapping_add(e);
195 state
196}
197
198const fn digest(mut state: [u32; 5], len: u64, blocks: Blocks) -> Digest {
199 const fn clone_from_slice_128(mut data: [u8; 128], slice: &[u8], offset: usize, num_elems: usize) -> [u8; 128] {
200 let mut i = 0;
201 while i < num_elems {
202 data[i] = slice[offset + i];
203 i += 1;
204 }
205 data
206 }
207
208 const fn clone_slice_128(mut data: [u8; 128], slice: &[u8], _offset: usize) -> [u8; 128] {
209 let mut i = 0;
210 while i < slice.len() {
211 data[_offset + i] = slice[i];
212 i += 1;
213 }
214 data
215 }
216
217 const fn as_block(input: &[u8], offset: usize) -> [u32; 16] {
218 let mut result = [0u32; 16];
219
220 let mut i = 0;
221 while i != 16 {
222 let off = offset + (i * 4);
223 result[i] = (input[off + 3] as u32) | ((input[off + 2] as u32) << 8) | ((input[off + 1] as u32) << 16) | ((input[off] as u32) << 24);
224 i += 1;
225 }
226 result
227 }
228
229 let bits = (len + (blocks.len as u64)) * 8;
230 let extra = [(bits >> 56) as u8, (bits >> 48) as u8, (bits >> 40) as u8, (bits >> 32) as u8, (bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8];
231 let mut last = [0; 128];
232 let blocklen = blocks.len as usize;
233 last = clone_from_slice_128(last, &blocks.data, 0, blocklen);
234 last[blocklen] = 0x80;
235
236 if blocklen < 56 {
237 last = clone_slice_128(last, &extra, 56);
238 state = process_state(state, as_block(&last, 0));
239 } else {
240 last = clone_slice_128(last, &extra, 120);
241 state = process_state(state, as_block(&last, 0));
242 state = process_state(state, as_block(&last, 64));
243 }
244 Digest { data: state }
245}
246
247const fn rol(value: u32, bits: usize) -> u32 {
248 (value << bits) | (value >> (32 - bits))
249}
250
251const fn blk(block: &[u32], i: usize) -> u32 {
252 let value: u32 = block[(i + 13) & 15] ^ block[(i + 8) & 15] ^ block[(i + 2) & 15] ^ block[i];
253 rol(value, bits:1)
254}
255
256const fn r0(block: [u32; 16], v: u32, mut w: u32, x: u32, y: u32, mut z: u32, i: usize) -> ([u32; 16], u32, u32) {
257 let n: u32 = ((w & (x ^ y)) ^ y).wrapping_add(block[i]).wrapping_add(0x5a82_7999).wrapping_add(rol(value:v, bits:5));
258 z = z.wrapping_add(n);
259 w = rol(value:w, bits:30);
260 (block, w, z)
261}
262
263const fn r1(mut block: [u32; 16], v: u32, mut w: u32, x: u32, y: u32, mut z: u32, i: usize) -> ([u32; 16], u32, u32) {
264 block[i] = blk(&block, i);
265 let n: u32 = ((w & (x ^ y)) ^ y).wrapping_add(block[i]).wrapping_add(0x5a82_7999).wrapping_add(rol(value:v, bits:5));
266 z = z.wrapping_add(n);
267 w = rol(value:w, bits:30);
268 (block, w, z)
269}
270
271const fn r2(mut block: [u32; 16], v: u32, mut w: u32, x: u32, y: u32, mut z: u32, i: usize) -> ([u32; 16], u32, u32) {
272 block[i] = blk(&block, i);
273 let n: u32 = (w ^ x ^ y).wrapping_add(block[i]).wrapping_add(0x6ed9_eba1).wrapping_add(rol(value:v, bits:5));
274 z = z.wrapping_add(n);
275 w = rol(value:w, bits:30);
276 (block, w, z)
277}
278
279const fn r3(mut block: [u32; 16], v: u32, mut w: u32, x: u32, y: u32, mut z: u32, i: usize) -> ([u32; 16], u32, u32) {
280 block[i] = blk(&block, i);
281 let n: u32 = (((w | x) & y) | (w & x)).wrapping_add(block[i]).wrapping_add(0x8f1b_bcdc).wrapping_add(rol(value:v, bits:5));
282 z = z.wrapping_add(n);
283 w = rol(value:w, bits:30);
284 (block, w, z)
285}
286
287const fn r4(mut block: [u32; 16], v: u32, mut w: u32, x: u32, y: u32, mut z: u32, i: usize) -> ([u32; 16], u32, u32) {
288 block[i] = blk(&block, i);
289 let n: u32 = (w ^ x ^ y).wrapping_add(block[i]).wrapping_add(0xca62_c1d6).wrapping_add(rol(value:v, bits:5));
290 z = z.wrapping_add(n);
291 w = rol(value:w, bits:30);
292 (block, w, z)
293}
294
295pub struct Digest {
296 data: [u32; 5],
297}
298
299impl Digest {
300 pub const fn bytes(&self) -> [u8; 20] {
301 [
302 (self.data[0] >> 24) as u8,
303 (self.data[0] >> 16) as u8,
304 (self.data[0] >> 8) as u8,
305 self.data[0] as u8,
306 (self.data[1] >> 24) as u8,
307 (self.data[1] >> 16) as u8,
308 (self.data[1] >> 8) as u8,
309 self.data[1] as u8,
310 (self.data[2] >> 24) as u8,
311 (self.data[2] >> 16) as u8,
312 (self.data[2] >> 8) as u8,
313 self.data[2] as u8,
314 (self.data[3] >> 24) as u8,
315 (self.data[3] >> 16) as u8,
316 (self.data[3] >> 8) as u8,
317 self.data[3] as u8,
318 (self.data[4] >> 24) as u8,
319 (self.data[4] >> 16) as u8,
320 (self.data[4] >> 8) as u8,
321 self.data[4] as u8,
322 ]
323 }
324}
325
326impl std::fmt::Display for Digest {
327 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
328 for i: &u32 in self.data.iter() {
329 write!(f, "{:08x}", i)?;
330 }
331 Ok(())
332 }
333}
334