1pub struct Sha1 {
4 state: [u32; STATE_LEN],
5 block: [u8; U8_BLOCK_LEN],
6 total: usize,
7 in_block: usize
8}
9
10impl Sha1 {
11 pub fn new() -> Sha1 {
12 Self {
13 state: SHA1_INIT_STATE,
14 block: [0u8; U8_BLOCK_LEN],
15 in_block: 0,
16 total: 0
17 }
18 }
19
20 pub fn update(&mut self, bytes: &[u8]) {
21 for &byte in bytes {
23 self.block[self.in_block] = byte;
24 self.in_block += 1;
25 if self.in_block == U8_BLOCK_LEN {
26 sha1_digest_bytes(&mut self.state, &self.block);
27 self.block = [0u8; U8_BLOCK_LEN];
28 self.in_block = 0;
29 self.total += U8_BLOCK_LEN;
30 }
31 }
32 }
33
34 pub fn finalise(mut self) -> [u8; U8_STATE_LEN] {
35
36 let bits = (self.total as u64 + (self.in_block as u64)) * 8;
37 let extra = bits.to_be_bytes();
38 let mut last_one = [0u8; U8_BLOCK_LEN];
39 let mut last_two = [0u8; U8_BLOCK_LEN];
40 last_one[..self.in_block].clone_from_slice(&self.block[..self.in_block]);
41 last_one[self.in_block] = 0x80;
42 if self.in_block < 56 {
43 last_one[56..64].clone_from_slice(&extra);
44 sha1_digest_bytes(&mut self.state, &last_one);
45 } else {
46 last_two[56..64].clone_from_slice(&extra);
47 sha1_digest_bytes(&mut self.state, &last_one);
48 sha1_digest_bytes(&mut self.state, &last_two);
49 }
50
51 sha1_state_to_bytes(&self.state)
52 }
53}
54
55impl Default for Sha1 {
56 fn default() -> Self {
57 Self::new()
58 }
59}
60
61const BASE64_TABLE: &[u8; 64] = &[65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47,];
62
63pub fn base64_encode(input: &[u8]) -> String {
64 let mut out = String::new();
65 let mut rem: usize = 0;
66 let mut step = 0;
67 for &inp in input {
68 let inp = inp as usize;
69 if step == 0 {
70 out.push(BASE64_TABLE[inp >> 2] as char);
71 rem = inp & 3;
72 step += 1;
73 }
74 else if step == 1 {
75 out.push(BASE64_TABLE[rem << 4 | inp >> 4] as char);
76 rem = inp & 0xf;
77 step += 1;
78 }
79 else if step == 2 {
80 out.push(BASE64_TABLE[rem << 2 | inp >> 6] as char);
81 out.push(BASE64_TABLE[inp & 0x3f] as char);
82 step = 0;
83 }
84 }
85 if step == 1 {
86 out.push(BASE64_TABLE[rem << 4] as char);
87 out.push('=');
88 out.push('=');
89 }
90 if step == 2 {
91 out.push(BASE64_TABLE[rem << 2] as char);
92 out.push('=');
93 }
94 out
95}
96
97
98pub const STATE_LEN: usize = 5;
101pub const BLOCK_LEN: usize = 16;
102pub const U8_BLOCK_LEN: usize = BLOCK_LEN * 4;
103pub const U8_STATE_LEN: usize = STATE_LEN * 4;
104pub const K0: u32 = 0x5A827999u32;
105pub const K1: u32 = 0x6ED9EBA1u32;
106pub const K2: u32 = 0x8F1BBCDCu32;
107pub const K3: u32 = 0xCA62C1D6u32;
108pub const SHA1_INIT_STATE: [u32; STATE_LEN] = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0];
109
110#[inline(always)]
111fn add(a: [u32; 4], b: [u32; 4]) -> [u32; 4] {
112 [
113 a[0].wrapping_add(b[0]),
114 a[1].wrapping_add(b[1]),
115 a[2].wrapping_add(b[2]),
116 a[3].wrapping_add(b[3]),
117 ]
118}
119
120#[inline(always)]
121fn xor(a: [u32; 4], b: [u32; 4]) -> [u32; 4] {
122 [a[0] ^ b[0], a[1] ^ b[1], a[2] ^ b[2], a[3] ^ b[3]]
123}
124
125#[inline]
126pub fn sha1_first_add(e: u32, w0: [u32; 4]) -> [u32; 4] {
127 let [a, b, c, d] = w0;
128 [e.wrapping_add(a), b, c, d]
129}
130
131fn sha1msg1(a: [u32; 4], b: [u32; 4]) -> [u32; 4] {
132 let [_, _, w2, w3] = a;
133 let [w4, w5, _, _] = b;
134 [a[0] ^ w2, a[1] ^ w3, a[2] ^ w4, a[3] ^ w5]
135}
136
137fn sha1msg2(a: [u32; 4], b: [u32; 4]) -> [u32; 4] {
138 let [x0, x1, x2, x3] = a;
139 let [_, w13, w14, w15] = b;
140
141 let w16 = (x0 ^ w13).rotate_left(1);
142 let w17 = (x1 ^ w14).rotate_left(1);
143 let w18 = (x2 ^ w15).rotate_left(1);
144 let w19 = (x3 ^ w16).rotate_left(1);
145
146 [w16, w17, w18, w19]
147}
148
149#[inline]
150fn sha1_first_half(abcd: [u32; 4], msg: [u32; 4]) -> [u32; 4] {
151 sha1_first_add(abcd[0].rotate_left(30), msg)
152}
153
154fn sha1_digest_round_x4(abcd: [u32; 4], work: [u32; 4], i: i8) -> [u32; 4] {
155 const K0V: [u32; 4] = [K0, K0, K0, K0];
156 const K1V: [u32; 4] = [K1, K1, K1, K1];
157 const K2V: [u32; 4] = [K2, K2, K2, K2];
158 const K3V: [u32; 4] = [K3, K3, K3, K3];
159
160 match i {
161 0 => sha1rnds4c(abcd, add(work, K0V)),
162 1 => sha1rnds4p(abcd, add(work, K1V)),
163 2 => sha1rnds4m(abcd, add(work, K2V)),
164 3 => sha1rnds4p(abcd, add(work, K3V)),
165 _ => unreachable!("unknown icosaround index"),
166 }
167}
168
169fn sha1rnds4c(abcd: [u32; 4], msg: [u32; 4]) -> [u32; 4] {
170 let [mut a, mut b, mut c, mut d] = abcd;
171 let [t, u, v, w] = msg;
172 let mut e = 0u32;
173
174 macro_rules!bool3ary_202 {
175 ( $ a: expr, $ b: expr, $ c: expr) => {
176 $ c ^ ( $ a & ( $ b ^ $ c))
177 };
178 } e = e
181 .wrapping_add(a.rotate_left(5))
182 .wrapping_add(bool3ary_202!(b, c, d))
183 .wrapping_add(t);
184 b = b.rotate_left(30);
185
186 d = d
187 .wrapping_add(e.rotate_left(5))
188 .wrapping_add(bool3ary_202!(a, b, c))
189 .wrapping_add(u);
190 a = a.rotate_left(30);
191
192 c = c
193 .wrapping_add(d.rotate_left(5))
194 .wrapping_add(bool3ary_202!(e, a, b))
195 .wrapping_add(v);
196 e = e.rotate_left(30);
197
198 b = b
199 .wrapping_add(c.rotate_left(5))
200 .wrapping_add(bool3ary_202!(d, e, a))
201 .wrapping_add(w);
202 d = d.rotate_left(30);
203
204 [b, c, d, e]
205}
206
207fn sha1rnds4p(abcd: [u32; 4], msg: [u32; 4]) -> [u32; 4] {
208 let [mut a, mut b, mut c, mut d] = abcd;
209 let [t, u, v, w] = msg;
210 let mut e = 0u32;
211
212 macro_rules!bool3ary_150 {
213 ( $ a: expr, $ b: expr, $ c: expr) => {
214 $ a ^ $ b ^ $ c
215 };
216 } e = e
219 .wrapping_add(a.rotate_left(5))
220 .wrapping_add(bool3ary_150!(b, c, d))
221 .wrapping_add(t);
222 b = b.rotate_left(30);
223
224 d = d
225 .wrapping_add(e.rotate_left(5))
226 .wrapping_add(bool3ary_150!(a, b, c))
227 .wrapping_add(u);
228 a = a.rotate_left(30);
229
230 c = c
231 .wrapping_add(d.rotate_left(5))
232 .wrapping_add(bool3ary_150!(e, a, b))
233 .wrapping_add(v);
234 e = e.rotate_left(30);
235
236 b = b
237 .wrapping_add(c.rotate_left(5))
238 .wrapping_add(bool3ary_150!(d, e, a))
239 .wrapping_add(w);
240 d = d.rotate_left(30);
241
242 [b, c, d, e]
243}
244
245fn sha1rnds4m(abcd: [u32; 4], msg: [u32; 4]) -> [u32; 4] {
246 let [mut a, mut b, mut c, mut d] = abcd;
247 let [t, u, v, w] = msg;
248 let mut e = 0u32;
249
250 macro_rules!bool3ary_232 {
251 ( $ a: expr, $ b: expr, $ c: expr) => {
252 ( $ a & $ b) ^ ( $ a & $ c) ^ ( $ b & $ c)
253 };
254 } e = e
257 .wrapping_add(a.rotate_left(5))
258 .wrapping_add(bool3ary_232!(b, c, d))
259 .wrapping_add(t);
260 b = b.rotate_left(30);
261
262 d = d
263 .wrapping_add(e.rotate_left(5))
264 .wrapping_add(bool3ary_232!(a, b, c))
265 .wrapping_add(u);
266 a = a.rotate_left(30);
267
268 c = c
269 .wrapping_add(d.rotate_left(5))
270 .wrapping_add(bool3ary_232!(e, a, b))
271 .wrapping_add(v);
272 e = e.rotate_left(30);
273
274 b = b
275 .wrapping_add(c.rotate_left(5))
276 .wrapping_add(bool3ary_232!(d, e, a))
277 .wrapping_add(w);
278 d = d.rotate_left(30);
279
280 [b, c, d, e]
281}
282
283macro_rules!rounds4 {
284 ( $ h0: ident, $ h1: ident, $ wk: expr, $ i: expr) => {
285 sha1_digest_round_x4( $ h0, sha1_first_half( $ h1, $ wk), $ i)
286 };
287}
288
289macro_rules!schedule {
290 ( $ v0: expr, $ v1: expr, $ v2: expr, $ v3: expr) => {
291 sha1msg2(xor(sha1msg1( $ v0, $ v1), $ v2), $ v3)
292 };
293}
294
295macro_rules!schedule_rounds4 {
296 (
297 $ h0: ident,
298 $ h1: ident,
299 $ w0: expr,
300 $ w1: expr,
301 $ w2: expr,
302 $ w3: expr,
303 $ w4: expr,
304 $ i: expr
305 ) => {
306 $ w4 = schedule!( $ w0, $ w1, $ w2, $ w3);
307 $ h1 = rounds4!( $ h0, $ h1, $ w4, $ i);
308 };
309}
310
311#[inline(always)]
312fn sha1_digest_block_u32(state: &mut [u32; 5], block: &[u32; 16]) {
313 let mut w0 = [block[0], block[1], block[2], block[3]];
314 let mut w1 = [block[4], block[5], block[6], block[7]];
315 let mut w2 = [block[8], block[9], block[10], block[11]];
316 let mut w3 = [block[12], block[13], block[14], block[15]];
317 let mut w4;
318
319 let mut h0 = [state[0], state[1], state[2], state[3]];
320 let mut h1 = sha1_first_add(state[4], w0);
321
322 h1 = sha1_digest_round_x4(h0, h1, 0);
324 h0 = rounds4!(h1, h0, w1, 0);
325 h1 = rounds4!(h0, h1, w2, 0);
326 h0 = rounds4!(h1, h0, w3, 0);
327 schedule_rounds4!(h0, h1, w0, w1, w2, w3, w4, 0);
328
329 schedule_rounds4!(h1, h0, w1, w2, w3, w4, w0, 1);
331 schedule_rounds4!(h0, h1, w2, w3, w4, w0, w1, 1);
332 schedule_rounds4!(h1, h0, w3, w4, w0, w1, w2, 1);
333 schedule_rounds4!(h0, h1, w4, w0, w1, w2, w3, 1);
334 schedule_rounds4!(h1, h0, w0, w1, w2, w3, w4, 1);
335
336 schedule_rounds4!(h0, h1, w1, w2, w3, w4, w0, 2);
338 schedule_rounds4!(h1, h0, w2, w3, w4, w0, w1, 2);
339 schedule_rounds4!(h0, h1, w3, w4, w0, w1, w2, 2);
340 schedule_rounds4!(h1, h0, w4, w0, w1, w2, w3, 2);
341 schedule_rounds4!(h0, h1, w0, w1, w2, w3, w4, 2);
342
343 schedule_rounds4!(h1, h0, w1, w2, w3, w4, w0, 3);
345 schedule_rounds4!(h0, h1, w2, w3, w4, w0, w1, 3);
346 schedule_rounds4!(h1, h0, w3, w4, w0, w1, w2, 3);
347 schedule_rounds4!(h0, h1, w4, w0, w1, w2, w3, 3);
348 schedule_rounds4!(h1, h0, w0, w1, w2, w3, w4, 3);
349
350 let e = h1[0].rotate_left(30);
351 let [a, b, c, d] = h0;
352
353 state[0] = state[0].wrapping_add(a);
354 state[1] = state[1].wrapping_add(b);
355 state[2] = state[2].wrapping_add(c);
356 state[3] = state[3].wrapping_add(d);
357 state[4] = state[4].wrapping_add(e);
358}
359
360pub fn sha1_digest_bytes(state: &mut[u32; STATE_LEN], bytes: &[u8; U8_BLOCK_LEN]) {
361 let mut block_u32 = [0u32; 16];
362 for (i, n) in block_u32.iter_mut().enumerate() {
363 let off = i * 4;
364 *n = (bytes[off + 3] as u32)
365 | ((bytes[off + 2] as u32) << 8)
366 | ((bytes[off + 1] as u32) << 16)
367 | ((bytes[off] as u32) << 24);
368 }
369 sha1_digest_block_u32(state, &block_u32);
370}
371
372pub fn sha1_state_to_bytes(state: &[u32; STATE_LEN]) -> [u8; U8_STATE_LEN] {
373 let mut state_bytes = [0u8; STATE_LEN * 4];
374 for i in 0..STATE_LEN {
375 let bytes = state[i].to_be_bytes();
376 for j in 0..4 {
377 state_bytes[i * 4 + j] = bytes[j];
378 }
379 };
380 state_bytes
381}
382