wz_reader 0.0.18

A wz file reader to resolve wz file with thread safe
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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
91
92
93
94
95
96
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
use scroll::{Pread, LE};

#[derive(Debug, Default)]
struct Snow2Context {
    keys: [u32; 16],
    r1: u32,
    r2: u32,

    s0: u32,
    s1: u32,
    s2: u32,
    s3: u32,

    s4: u32,
    s5: u32,
    s6: u32,
    s7: u32,

    s8: u32,
    s9: u32,
    s10: u32,
    s11: u32,

    s12: u32,
    s13: u32,
    s14: u32,
    s15: u32,
}
impl Snow2Context {
    pub fn with_key_and_iv(mut self, key: [u8; 16], iv: Option<[u8; 4]>) -> Self {
        let signed_key = [
            key[0] as i8,
            key[1] as i8,
            key[2] as i8,
            key[3] as i8,
            key[4] as i8,
            key[5] as i8,
            key[6] as i8,
            key[7] as i8,
            key[8] as i8,
            key[9] as i8,
            key[10] as i8,
            key[11] as i8,
            key[12] as i8,
            key[13] as i8,
            key[14] as i8,
            key[15] as i8,
        ];

        self.s15 = ((signed_key[0] as u32) << 24)
            | ((signed_key[1] as u32) << 16)
            | ((signed_key[2] as u32) << 8)
            | (signed_key[3] as u32);
        self.s14 = ((signed_key[4] as u32) << 24)
            | ((signed_key[5] as u32) << 16)
            | ((signed_key[6] as u32) << 8)
            | (signed_key[7] as u32);
        self.s13 = ((signed_key[8] as u32) << 24)
            | ((signed_key[9] as u32) << 16)
            | ((signed_key[10] as u32) << 8)
            | (signed_key[11] as u32);
        self.s12 = ((signed_key[12] as u32) << 24)
            | ((signed_key[13] as u32) << 16)
            | ((signed_key[14] as u32) << 8)
            | (signed_key[15] as u32);
        self.s11 = !self.s15; // bitwise inverse
        self.s10 = !self.s14;
        self.s9 = !self.s13;
        self.s8 = !self.s12;
        self.s7 = self.s15; // just copy
        self.s6 = self.s14;
        self.s5 = self.s13;
        self.s4 = self.s12;
        self.s3 = !self.s15; // bitwise inverse
        self.s2 = !self.s14;
        self.s1 = !self.s13;
        self.s0 = !self.s12;

        if let Some(iv) = iv {
            self.calc_iv(iv);
        }

        /* Do 32 initial clockings */
        self.initial_clocking();
        self.initial_clocking();

        self.generate_keys();

        self
    }
    #[allow(dead_code)]
    pub fn with_key_32_and_iv(mut self, key: [u8; 32], iv: Option<[u8; 4]>) -> Self {
        let signed_key = [
            key[0] as i8,
            key[1] as i8,
            key[2] as i8,
            key[3] as i8,
            key[4] as i8,
            key[5] as i8,
            key[6] as i8,
            key[7] as i8,
            key[8] as i8,
            key[9] as i8,
            key[10] as i8,
            key[11] as i8,
            key[12] as i8,
            key[13] as i8,
            key[14] as i8,
            key[15] as i8,
            key[16] as i8,
            key[17] as i8,
            key[18] as i8,
            key[19] as i8,
            key[20] as i8,
            key[21] as i8,
            key[22] as i8,
            key[23] as i8,
            key[24] as i8,
            key[25] as i8,
            key[26] as i8,
            key[27] as i8,
            key[28] as i8,
            key[29] as i8,
            key[30] as i8,
            key[31] as i8,
        ];
        self.s15 = ((signed_key[0] as u32) << 24)
            | ((signed_key[1] as u32) << 16)
            | ((signed_key[2] as u32) << 8)
            | (signed_key[3] as u32);
        self.s14 = ((signed_key[4] as u32) << 24)
            | ((signed_key[5] as u32) << 16)
            | ((signed_key[6] as u32) << 8)
            | (signed_key[7] as u32);
        self.s13 = ((signed_key[8] as u32) << 24)
            | ((signed_key[9] as u32) << 16)
            | ((signed_key[10] as u32) << 8)
            | (signed_key[11] as u32);
        self.s12 = ((signed_key[12] as u32) << 24)
            | ((signed_key[13] as u32) << 16)
            | ((signed_key[14] as u32) << 8)
            | (signed_key[15] as u32);
        self.s11 = ((signed_key[16] as u32) << 24)
            | ((signed_key[17] as u32) << 16)
            | ((signed_key[18] as u32) << 8)
            | (signed_key[19] as u32);
        self.s10 = ((signed_key[20] as u32) << 24)
            | ((signed_key[21] as u32) << 16)
            | ((signed_key[22] as u32) << 8)
            | (signed_key[23] as u32);
        self.s9 = ((signed_key[24] as u32) << 24)
            | ((signed_key[25] as u32) << 16)
            | ((signed_key[26] as u32) << 8)
            | (signed_key[27] as u32);
        self.s8 = ((signed_key[28] as u32) << 24)
            | ((signed_key[29] as u32) << 16)
            | ((signed_key[30] as u32) << 8)
            | (signed_key[31] as u32);
        self.s7 = !self.s15; // bitwise inverse
        self.s6 = !self.s14;
        self.s5 = !self.s13;
        self.s4 = !self.s12;
        self.s3 = !self.s11;
        self.s2 = !self.s10;
        self.s1 = !self.s9;
        self.s0 = !self.s8;

        if let Some(iv) = iv {
            self.calc_iv(iv);
        }

        /* Do 32 initial clockings */
        self.initial_clocking();
        self.initial_clocking();

        self
    }
    #[inline]
    fn calc_iv(&mut self, iv: [u8; 4]) {
        /* XOR IV values */
        self.s15 ^= iv[0] as u32;
        self.s12 ^= iv[1] as u32;
        self.s10 ^= iv[2] as u32;
        self.s9 ^= iv[3] as u32;
    }
    #[inline(always)]
    fn initial_clocking(&mut self) {
        let out_from_fsm = u32::wrapping_add(self.r1, self.s15) ^ self.r2;
        self.s0 = a_mul(self.s0) ^ self.s2 ^ ainv_mul(self.s11) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s5);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s0) ^ self.r2;
        self.s1 = a_mul(self.s1) ^ self.s3 ^ ainv_mul(self.s12) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s6);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s1) ^ self.r2;
        self.s2 = a_mul(self.s2) ^ self.s4 ^ ainv_mul(self.s13) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s7);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s2) ^ self.r2;
        self.s3 = a_mul(self.s3) ^ self.s5 ^ ainv_mul(self.s14) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s8);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s3) ^ self.r2;
        self.s4 = a_mul(self.s4) ^ self.s6 ^ ainv_mul(self.s15) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s9);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s4) ^ self.r2;
        self.s5 = a_mul(self.s5) ^ self.s7 ^ ainv_mul(self.s0) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s10);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s5) ^ self.r2;
        self.s6 = a_mul(self.s6) ^ self.s8 ^ ainv_mul(self.s1) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s11);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s6) ^ self.r2;
        self.s7 = a_mul(self.s7) ^ self.s9 ^ ainv_mul(self.s2) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s12);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s7) ^ self.r2;
        self.s8 = a_mul(self.s8) ^ self.s10 ^ ainv_mul(self.s3) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s13);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s8) ^ self.r2;
        self.s9 = a_mul(self.s9) ^ self.s11 ^ ainv_mul(self.s4) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s14);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s9) ^ self.r2;
        self.s10 = a_mul(self.s10) ^ self.s12 ^ ainv_mul(self.s5) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s15);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s10) ^ self.r2;
        self.s11 = a_mul(self.s11) ^ self.s13 ^ ainv_mul(self.s6) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s0);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s11) ^ self.r2;
        self.s12 = a_mul(self.s12) ^ self.s14 ^ ainv_mul(self.s7) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s1);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s12) ^ self.r2;
        self.s13 = a_mul(self.s13) ^ self.s15 ^ ainv_mul(self.s8) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s2);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s13) ^ self.r2;
        self.s14 = a_mul(self.s14) ^ self.s0 ^ ainv_mul(self.s9) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s3);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;

        let out_from_fsm = u32::wrapping_add(self.r1, self.s14) ^ self.r2;
        self.s15 = a_mul(self.s15) ^ self.s1 ^ ainv_mul(self.s10) ^ out_from_fsm;
        let fsm_tmp = u32::wrapping_add(self.r2, self.s4);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsm_tmp;
    }
    pub fn generate_keys(&mut self) {
        let mut buffer: [u32; 16] = [0; 16];

        self.s0 = a_mul(self.s0) ^ self.s2 ^ ainv_mul(self.s11);
        let fsmtmp = u32::wrapping_add(self.r2, self.s5);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[0] = u32::wrapping_add(self.r1, self.s0) ^ self.r2 ^ self.s1;

        self.s1 = a_mul(self.s1) ^ self.s3 ^ ainv_mul(self.s12);
        let fsmtmp = u32::wrapping_add(self.r2, self.s6);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[1] = u32::wrapping_add(self.r1, self.s1) ^ self.r2 ^ self.s2;

        self.s2 = a_mul(self.s2) ^ self.s4 ^ ainv_mul(self.s13);
        let fsmtmp = u32::wrapping_add(self.r2, self.s7);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[2] = u32::wrapping_add(self.r1, self.s2) ^ self.r2 ^ self.s3;

        self.s3 = a_mul(self.s3) ^ self.s5 ^ ainv_mul(self.s14);
        let fsmtmp = u32::wrapping_add(self.r2, self.s8);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[3] = u32::wrapping_add(self.r1, self.s3) ^ self.r2 ^ self.s4;

        self.s4 = a_mul(self.s4) ^ self.s6 ^ ainv_mul(self.s15);
        let fsmtmp = u32::wrapping_add(self.r2, self.s9);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[4] = u32::wrapping_add(self.r1, self.s4) ^ self.r2 ^ self.s5;

        self.s5 = a_mul(self.s5) ^ self.s7 ^ ainv_mul(self.s0);
        let fsmtmp = u32::wrapping_add(self.r2, self.s10);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[5] = u32::wrapping_add(self.r1, self.s5) ^ self.r2 ^ self.s6;

        self.s6 = a_mul(self.s6) ^ self.s8 ^ ainv_mul(self.s1);
        let fsmtmp = u32::wrapping_add(self.r2, self.s11);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[6] = u32::wrapping_add(self.r1, self.s6) ^ self.r2 ^ self.s7;

        self.s7 = a_mul(self.s7) ^ self.s9 ^ ainv_mul(self.s2);
        let fsmtmp = u32::wrapping_add(self.r2, self.s12);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[7] = u32::wrapping_add(self.r1, self.s7) ^ self.r2 ^ self.s8;

        self.s8 = a_mul(self.s8) ^ self.s10 ^ ainv_mul(self.s3);
        let fsmtmp = u32::wrapping_add(self.r2, self.s13);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[8] = u32::wrapping_add(self.r1, self.s8) ^ self.r2 ^ self.s9;

        self.s9 = a_mul(self.s9) ^ self.s11 ^ ainv_mul(self.s4);
        let fsmtmp = u32::wrapping_add(self.r2, self.s14);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[9] = u32::wrapping_add(self.r1, self.s9) ^ self.r2 ^ self.s10;

        self.s10 = a_mul(self.s10) ^ self.s12 ^ ainv_mul(self.s5);
        let fsmtmp = u32::wrapping_add(self.r2, self.s15);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[10] = u32::wrapping_add(self.r1, self.s10) ^ self.r2 ^ self.s11;

        self.s11 = a_mul(self.s11) ^ self.s13 ^ ainv_mul(self.s6);
        let fsmtmp = u32::wrapping_add(self.r2, self.s0);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[11] = u32::wrapping_add(self.r1, self.s11) ^ self.r2 ^ self.s12;

        self.s12 = a_mul(self.s12) ^ self.s14 ^ ainv_mul(self.s7);
        let fsmtmp = u32::wrapping_add(self.r2, self.s1);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[12] = u32::wrapping_add(self.r1, self.s12) ^ self.r2 ^ self.s13;

        self.s13 = a_mul(self.s13) ^ self.s15 ^ ainv_mul(self.s8);
        let fsmtmp = u32::wrapping_add(self.r2, self.s2);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[13] = u32::wrapping_add(self.r1, self.s13) ^ self.r2 ^ self.s14;

        self.s14 = a_mul(self.s14) ^ self.s0 ^ ainv_mul(self.s9);
        let fsmtmp = u32::wrapping_add(self.r2, self.s3);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[14] = u32::wrapping_add(self.r1, self.s14) ^ self.r2 ^ self.s15;

        self.s15 = a_mul(self.s15) ^ self.s1 ^ ainv_mul(self.s10);
        let fsmtmp = u32::wrapping_add(self.r2, self.s4);
        self.r2 = SNOW_T0[byte(0, self.r1)]
            ^ SNOW_T1[byte(1, self.r1)]
            ^ SNOW_T2[byte(2, self.r1)]
            ^ SNOW_T3[byte(3, self.r1)];
        self.r1 = fsmtmp;
        buffer[15] = u32::wrapping_add(self.r1, self.s15) ^ self.r2 ^ self.s0;

        self.keys = buffer;
    }
}
// TODO: make this using cipher
pub struct Snow2Decryptor {
    index: usize,
    context: Snow2Context,
}
impl Snow2Decryptor {
    pub fn new(key: [u8; 16]) -> Self {
        Self {
            index: 0,
            context: Snow2Context::default().with_key_and_iv(key, None),
        }
    }
    #[inline]
    pub fn decrypt_block(&mut self, data: &u32) -> u32 {
        let key = self.context.keys[self.index];
        let num = data.wrapping_sub(key);
        self.index += 1;

        if self.index >= 16 {
            self.context.generate_keys();
            self.index = 0;
        }
        num
    }
    /* logic from https://github.com/Kagamia/WzComparerR2/pull/271/files#diff-e84c5dd639ef929d7688b9d1f0005c771d0b4a65313f623404b896f53d35dad6 */
    /// seen it decrypt 4 bytes at a time, the slice is suggestd to be a multiple of 4
    pub fn decrypt_slice(&mut self, data: &mut [u8]) -> usize {
        // decrypt block by 4 bytes
        let mut data_iter = data.chunks_exact_mut(4);

        for chunk in &mut data_iter {
            let origin = chunk.pread_with::<u32>(0, LE).unwrap_or(0);

            chunk.copy_from_slice(&u32::to_le_bytes(self.decrypt_block(&origin)));
        }
        data_iter.into_remainder().len()
    }
    #[inline]
    pub fn make_decrypt_slice(&mut self, data: &[u8]) -> Vec<u8> {
        let mut data = data.to_vec();
        self.decrypt_slice(&mut data);
        data
    }
}

/* consts */
const SNOW_ALPHA_MUL: [u32; 256] = [
    0x0, 0xE19FCF13, 0x6B973726, 0x8A08F835, 0xD6876E4C, 0x3718A15F, 0xBD10596A, 0x5C8F9679,
    0x5A7DC98, 0xE438138B, 0x6E30EBBE, 0x8FAF24AD, 0xD320B2D4, 0x32BF7DC7, 0xB8B785F2, 0x59284AE1,
    0xAE71199, 0xEB78DE8A, 0x617026BF, 0x80EFE9AC, 0xDC607FD5, 0x3DFFB0C6, 0xB7F748F3, 0x566887E0,
    0xF40CD01, 0xEEDF0212, 0x64D7FA27, 0x85483534, 0xD9C7A34D, 0x38586C5E, 0xB250946B, 0x53CF5B78,
    0x1467229B, 0xF5F8ED88, 0x7FF015BD, 0x9E6FDAAE, 0xC2E04CD7, 0x237F83C4, 0xA9777BF1, 0x48E8B4E2,
    0x11C0FE03, 0xF05F3110, 0x7A57C925, 0x9BC80636, 0xC747904F, 0x26D85F5C, 0xACD0A769, 0x4D4F687A,
    0x1E803302, 0xFF1FFC11, 0x75170424, 0x9488CB37, 0xC8075D4E, 0x2998925D, 0xA3906A68, 0x420FA57B,
    0x1B27EF9A, 0xFAB82089, 0x70B0D8BC, 0x912F17AF, 0xCDA081D6, 0x2C3F4EC5, 0xA637B6F0, 0x47A879E3,
    0x28CE449F, 0xC9518B8C, 0x435973B9, 0xA2C6BCAA, 0xFE492AD3, 0x1FD6E5C0, 0x95DE1DF5, 0x7441D2E6,
    0x2D699807, 0xCCF65714, 0x46FEAF21, 0xA7616032, 0xFBEEF64B, 0x1A713958, 0x9079C16D, 0x71E60E7E,
    0x22295506, 0xC3B69A15, 0x49BE6220, 0xA821AD33, 0xF4AE3B4A, 0x1531F459, 0x9F390C6C, 0x7EA6C37F,
    0x278E899E, 0xC611468D, 0x4C19BEB8, 0xAD8671AB, 0xF109E7D2, 0x109628C1, 0x9A9ED0F4, 0x7B011FE7,
    0x3CA96604, 0xDD36A917, 0x573E5122, 0xB6A19E31, 0xEA2E0848, 0xBB1C75B, 0x81B93F6E, 0x6026F07D,
    0x390EBA9C, 0xD891758F, 0x52998DBA, 0xB30642A9, 0xEF89D4D0, 0xE161BC3, 0x841EE3F6, 0x65812CE5,
    0x364E779D, 0xD7D1B88E, 0x5DD940BB, 0xBC468FA8, 0xE0C919D1, 0x156D6C2, 0x8B5E2EF7, 0x6AC1E1E4,
    0x33E9AB05, 0xD2766416, 0x587E9C23, 0xB9E15330, 0xE56EC549, 0x4F10A5A, 0x8EF9F26F, 0x6F663D7C,
    0x50358897, 0xB1AA4784, 0x3BA2BFB1, 0xDA3D70A2, 0x86B2E6DB, 0x672D29C8, 0xED25D1FD, 0xCBA1EEE,
    0x5592540F, 0xB40D9B1C, 0x3E056329, 0xDF9AAC3A, 0x83153A43, 0x628AF550, 0xE8820D65, 0x91DC276,
    0x5AD2990E, 0xBB4D561D, 0x3145AE28, 0xD0DA613B, 0x8C55F742, 0x6DCA3851, 0xE7C2C064, 0x65D0F77,
    0x5F754596, 0xBEEA8A85, 0x34E272B0, 0xD57DBDA3, 0x89F22BDA, 0x686DE4C9, 0xE2651CFC, 0x3FAD3EF,
    0x4452AA0C, 0xA5CD651F, 0x2FC59D2A, 0xCE5A5239, 0x92D5C440, 0x734A0B53, 0xF942F366, 0x18DD3C75,
    0x41F57694, 0xA06AB987, 0x2A6241B2, 0xCBFD8EA1, 0x977218D8, 0x76EDD7CB, 0xFCE52FFE, 0x1D7AE0ED,
    0x4EB5BB95, 0xAF2A7486, 0x25228CB3, 0xC4BD43A0, 0x9832D5D9, 0x79AD1ACA, 0xF3A5E2FF, 0x123A2DEC,
    0x4B12670D, 0xAA8DA81E, 0x2085502B, 0xC11A9F38, 0x9D950941, 0x7C0AC652, 0xF6023E67, 0x179DF174,
    0x78FBCC08, 0x9964031B, 0x136CFB2E, 0xF2F3343D, 0xAE7CA244, 0x4FE36D57, 0xC5EB9562, 0x24745A71,
    0x7D5C1090, 0x9CC3DF83, 0x16CB27B6, 0xF754E8A5, 0xABDB7EDC, 0x4A44B1CF, 0xC04C49FA, 0x21D386E9,
    0x721CDD91, 0x93831282, 0x198BEAB7, 0xF81425A4, 0xA49BB3DD, 0x45047CCE, 0xCF0C84FB, 0x2E934BE8,
    0x77BB0109, 0x9624CE1A, 0x1C2C362F, 0xFDB3F93C, 0xA13C6F45, 0x40A3A056, 0xCAAB5863, 0x2B349770,
    0x6C9CEE93, 0x8D032180, 0x70BD9B5, 0xE69416A6, 0xBA1B80DF, 0x5B844FCC, 0xD18CB7F9, 0x301378EA,
    0x693B320B, 0x88A4FD18, 0x2AC052D, 0xE333CA3E, 0xBFBC5C47, 0x5E239354, 0xD42B6B61, 0x35B4A472,
    0x667BFF0A, 0x87E43019, 0xDECC82C, 0xEC73073F, 0xB0FC9146, 0x51635E55, 0xDB6BA660, 0x3AF46973,
    0x63DC2392, 0x8243EC81, 0x84B14B4, 0xE9D4DBA7, 0xB55B4DDE, 0x54C482CD, 0xDECC7AF8, 0x3F53B5EB,
];
const SNOW_ALPHAINV_MUL: [u32; 256] = [
    0x0, 0x180F40CD, 0x301E8033, 0x2811C0FE, 0x603CA966, 0x7833E9AB, 0x50222955, 0x482D6998,
    0xC078FBCC, 0xD877BB01, 0xF0667BFF, 0xE8693B32, 0xA04452AA, 0xB84B1267, 0x905AD299, 0x88559254,
    0x29F05F31, 0x31FF1FFC, 0x19EEDF02, 0x1E19FCF, 0x49CCF657, 0x51C3B69A, 0x79D27664, 0x61DD36A9,
    0xE988A4FD, 0xF187E430, 0xD99624CE, 0xC1996403, 0x89B40D9B, 0x91BB4D56, 0xB9AA8DA8, 0xA1A5CD65,
    0x5249BE62, 0x4A46FEAF, 0x62573E51, 0x7A587E9C, 0x32751704, 0x2A7A57C9, 0x26B9737, 0x1A64D7FA,
    0x923145AE, 0x8A3E0563, 0xA22FC59D, 0xBA208550, 0xF20DECC8, 0xEA02AC05, 0xC2136CFB, 0xDA1C2C36,
    0x7BB9E153, 0x63B6A19E, 0x4BA76160, 0x53A821AD, 0x1B854835, 0x38A08F8, 0x2B9BC806, 0x339488CB,
    0xBBC11A9F, 0xA3CE5A52, 0x8BDF9AAC, 0x93D0DA61, 0xDBFDB3F9, 0xC3F2F334, 0xEBE333CA, 0xF3EC7307,
    0xA492D5C4, 0xBC9D9509, 0x948C55F7, 0x8C83153A, 0xC4AE7CA2, 0xDCA13C6F, 0xF4B0FC91, 0xECBFBC5C,
    0x64EA2E08, 0x7CE56EC5, 0x54F4AE3B, 0x4CFBEEF6, 0x4D6876E, 0x1CD9C7A3, 0x34C8075D, 0x2CC74790,
    0x8D628AF5, 0x956DCA38, 0xBD7C0AC6, 0xA5734A0B, 0xED5E2393, 0xF551635E, 0xDD40A3A0, 0xC54FE36D,
    0x4D1A7139, 0x551531F4, 0x7D04F10A, 0x650BB1C7, 0x2D26D85F, 0x35299892, 0x1D38586C, 0x53718A1,
    0xF6DB6BA6, 0xEED42B6B, 0xC6C5EB95, 0xDECAAB58, 0x96E7C2C0, 0x8EE8820D, 0xA6F942F3, 0xBEF6023E,
    0x36A3906A, 0x2EACD0A7, 0x6BD1059, 0x1EB25094, 0x569F390C, 0x4E9079C1, 0x6681B93F, 0x7E8EF9F2,
    0xDF2B3497, 0xC724745A, 0xEF35B4A4, 0xF73AF469, 0xBF179DF1, 0xA718DD3C, 0x8F091DC2, 0x97065D0F,
    0x1F53CF5B, 0x75C8F96, 0x2F4D4F68, 0x37420FA5, 0x7F6F663D, 0x676026F0, 0x4F71E60E, 0x577EA6C3,
    0xE18D0321, 0xF98243EC, 0xD1938312, 0xC99CC3DF, 0x81B1AA47, 0x99BEEA8A, 0xB1AF2A74, 0xA9A06AB9,
    0x21F5F8ED, 0x39FAB820, 0x11EB78DE, 0x9E43813, 0x41C9518B, 0x59C61146, 0x71D7D1B8, 0x69D89175,
    0xC87D5C10, 0xD0721CDD, 0xF863DC23, 0xE06C9CEE, 0xA841F576, 0xB04EB5BB, 0x985F7545, 0x80503588,
    0x805A7DC, 0x100AE711, 0x381B27EF, 0x20146722, 0x68390EBA, 0x70364E77, 0x58278E89, 0x4028CE44,
    0xB3C4BD43, 0xABCBFD8E, 0x83DA3D70, 0x9BD57DBD, 0xD3F81425, 0xCBF754E8, 0xE3E69416, 0xFBE9D4DB,
    0x73BC468F, 0x6BB30642, 0x43A2C6BC, 0x5BAD8671, 0x1380EFE9, 0xB8FAF24, 0x239E6FDA, 0x3B912F17,
    0x9A34E272, 0x823BA2BF, 0xAA2A6241, 0xB225228C, 0xFA084B14, 0xE2070BD9, 0xCA16CB27, 0xD2198BEA,
    0x5A4C19BE, 0x42435973, 0x6A52998D, 0x725DD940, 0x3A70B0D8, 0x227FF015, 0xA6E30EB, 0x12617026,
    0x451FD6E5, 0x5D109628, 0x750156D6, 0x6D0E161B, 0x25237F83, 0x3D2C3F4E, 0x153DFFB0, 0xD32BF7D,
    0x85672D29, 0x9D686DE4, 0xB579AD1A, 0xAD76EDD7, 0xE55B844F, 0xFD54C482, 0xD545047C, 0xCD4A44B1,
    0x6CEF89D4, 0x74E0C919, 0x5CF109E7, 0x44FE492A, 0xCD320B2, 0x14DC607F, 0x3CCDA081, 0x24C2E04C,
    0xAC977218, 0xB49832D5, 0x9C89F22B, 0x8486B2E6, 0xCCABDB7E, 0xD4A49BB3, 0xFCB55B4D, 0xE4BA1B80,
    0x17566887, 0xF59284A, 0x2748E8B4, 0x3F47A879, 0x776AC1E1, 0x6F65812C, 0x477441D2, 0x5F7B011F,
    0xD72E934B, 0xCF21D386, 0xE7301378, 0xFF3F53B5, 0xB7123A2D, 0xAF1D7AE0, 0x870CBA1E, 0x9F03FAD3,
    0x3EA637B6, 0x26A9777B, 0xEB8B785, 0x16B7F748, 0x5E9A9ED0, 0x4695DE1D, 0x6E841EE3, 0x768B5E2E,
    0xFEDECC7A, 0xE6D18CB7, 0xCEC04C49, 0xD6CF0C84, 0x9EE2651C, 0x86ED25D1, 0xAEFCE52F, 0xB6F3A5E2,
];
const SNOW_T0: [u32; 256] = [
    0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0xdf2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591,
    0x50303060, 0x3010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec,
    0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0xbf0f0fb,
    0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b,
    0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x2f7f7f5, 0x4fcccc83,
    0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x8f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
    0xc040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0xf05050a, 0xb59a9a2f,
    0x907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea,
    0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
    0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
    0xf55353a6, 0x68d1d1b9, 0x0, 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6,
    0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
    0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511,
    0xcf45458a, 0x10f9f9e9, 0x6020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b,
    0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x4f5f5f1,
    0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5, 0xef3f3fd, 0x6dd2d2bf,
    0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e,
    0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
    0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b,
    0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
    0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0xa06060c, 0x6c242448, 0xe45c5cb8,
    0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2,
    0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949,
    0xb46c6cd8, 0xfa5656ac, 0x7f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
    0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
    0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f,
    0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x5030306, 0x1f6f6f7, 0x120e0e1c,
    0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27,
    0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433,
    0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
    0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0,
    0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c,
];
const SNOW_T1: [u32; 256] = [
    0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154,
    0x30306050, 0x1010203, 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a,
    0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87, 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b,
    0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b,
    0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f,
    0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908, 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f,
    0x404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1, 0x5050a0f, 0x9a9a2fb5,
    0x7070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d, 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f,
    0x909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb,
    0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, 0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397,
    0x5353a6f5, 0xd1d1b968, 0x0, 0xededc12c, 0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed,
    0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a,
    0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194,
    0x45458acf, 0xf9f9e910, 0x2020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3,
    0x5151a2f3, 0xa3a35dfe, 0x404080c0, 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,
    0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d,
    0xcdcd814c, 0xc0c1814, 0x13132635, 0xececc32f, 0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39,
    0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47, 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695,
    0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e, 0x90903bab, 0x88880b83,
    0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c, 0xdedea779, 0x5e5ebce2, 0xb0b161d, 0xdbdbad76,
    0xe0e0db3b, 0x32326456, 0x3a3a744e, 0xa0a141e, 0x494992db, 0x6060c0a, 0x2424486c, 0x5c5cb8e4,
    0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b,
    0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7, 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0,
    0x6c6cd8b4, 0x5656acfa, 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x8081018,
    0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751,
    0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, 0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85,
    0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x3030605, 0xf6f6f701, 0xe0e1c12,
    0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, 0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9,
    0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7,
    0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
    0x8c8c038f, 0xa1a159f8, 0x89890980, 0xd0d1a17, 0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8,
    0x414182c3, 0x999929b0, 0x2d2d5a77, 0xf0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a,
];

const SNOW_T2: [u32; 256] = [
    0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5,
    0x30605030, 0x1020301, 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76,
    0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d, 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0,
    0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0,
    0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc,
    0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1, 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15,
    0x4080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196, 0x50a0f05, 0x9a2fb59a,
    0x70e0907, 0x12243612, 0x801b9b80, 0xe2df3de2, 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75,
    0x9121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0,
    0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, 0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784,
    0x53a6f553, 0xd1b968d1, 0x0, 0xedc12ced, 0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b,
    0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf,
    0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485,
    0x458acf45, 0xf9e910f9, 0x2040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8,
    0x51a2f351, 0xa35dfea3, 0x4080c040, 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,
    0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2,
    0xcd814ccd, 0xc18140c, 0x13263513, 0xecc32fec, 0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917,
    0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d, 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573,
    0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a, 0x903bab90, 0x880b8388,
    0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14, 0xdea779de, 0x5ebce25e, 0xb161d0b, 0xdbad76db,
    0xe0db3be0, 0x32645632, 0x3a744e3a, 0xa141e0a, 0x4992db49, 0x60c0a06, 0x24486c24, 0x5cb8e45c,
    0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79,
    0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d, 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9,
    0x6cd8b46c, 0x56acfa56, 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x8101808,
    0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6,
    0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, 0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a,
    0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x3060503, 0xf6f701f6, 0xe1c120e,
    0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, 0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e,
    0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794,
    0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
    0x8c038f8c, 0xa159f8a1, 0x89098089, 0xd1a170d, 0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868,
    0x4182c341, 0x9929b099, 0x2d5a772d, 0xf1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16,
];

const SNOW_T3: [u32; 256] = [
    0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5,
    0x60503030, 0x2030101, 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676,
    0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d, 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0,
    0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0,
    0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc,
    0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1, 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515,
    0x80c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696, 0xa0f0505, 0x2fb59a9a,
    0xe090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2, 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575,
    0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0,
    0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484,
    0xa6f55353, 0xb968d1d1, 0x0, 0xc12ceded, 0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b,
    0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf,
    0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585,
    0x8acf4545, 0xe910f9f9, 0x4060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8,
    0xa2f35151, 0x5dfea3a3, 0x80c04040, 0x58a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,
    0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2,
    0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec, 0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717,
    0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d, 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373,
    0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a, 0x3bab9090, 0xb838888,
    0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb,
    0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949, 0xc0a0606, 0x486c2424, 0xb8e45c5c,
    0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979,
    0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d, 0x18c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9,
    0xd8b46c6c, 0xacfa5656, 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808,
    0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6,
    0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, 0x96dd4b4b, 0x61dcbdbd, 0xd868b8b, 0xf858a8a,
    0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x6050303, 0xf701f6f6, 0x1c120e0e,
    0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, 0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e,
    0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9, 0x7898e8e, 0x33a79494,
    0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
    0x38f8c8c, 0x59f8a1a1, 0x9808989, 0x1a170d0d, 0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868,
    0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616,
];

#[inline(always)]
fn byte(n: i32, w: u32) -> usize {
    ((w >> (n * 8)) & 0xFF) as usize
}

#[inline(always)]
fn ainv_mul(w: u32) -> u32 {
    ((w) >> 8) ^ (SNOW_ALPHAINV_MUL[(w as usize) & 0xff])
}

#[inline(always)]
fn a_mul(w: u32) -> u32 {
    ((w) << 8) ^ (SNOW_ALPHA_MUL[(w as usize) >> 24])
}