aboutsummaryrefslogtreecommitdiff
path: root/src/zip/encryption/weak.rs
blob: ebddb2dc346b226059a5312a1b855349562987ea (plain)
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
use std::io::{Read, Result as IoResult};

const TABLE: [u32; 256] = generate_table();

const fn generate_table() -> [u32; 256] {
    let mut table = [0; 256];

    let mut i = 0;
    while i <= 255 {
        let mut t = i as u32;

        let mut j = 0;
        while j < 8 {
            if (t & 1) > 0 {
                t = (t >> 1) ^ 0xEDB88320
            } else {
                t >>= 1
            }
            j += 1;
        }

        table[i] = t;
        i += 1
    }

    table
}

fn crc32(byte: u8, crc: u32) -> u32 {
    (crc >> 8) ^ TABLE[((crc & 0xFF) as u8 ^ byte) as usize]
}

pub struct Keys {
    key0: u32,
    key1: u32,
    key2: u32,
}

impl Keys {
    pub fn new() -> Self {
        Self {
            key0: 305419896,
            key1: 591751049,
            key2: 878082192,
        }
    }

    pub fn update(&mut self, byte: u8) {
        self.key0 = crc32(byte, self.key0);
        self.key1 = self
            .key1
            .wrapping_add(self.key0 & 0xFF)
            .wrapping_mul(134775813)
            .wrapping_add(1);
        self.key2 = crc32((self.key1 >> 24) as u8, self.key2);
    }

    #[allow(dead_code)]
    pub fn encode_bytes(&mut self, byte: u8) -> u8 {
        let key = self.key2 | 2;
        self.update(byte);
        byte ^ ((key.wrapping_mul(key ^ 1)) >> 8) as u8
    }

    pub fn decode_byte(&mut self, byte: u8) -> u8 {
        let key = self.key2 | 2;
        let byte = byte ^ ((key.wrapping_mul(key ^ 1)) >> 8) as u8;
        self.update(byte);
        byte
    }
}

pub struct WeakDecoder<Io: Read> {
    io: Io,
    keys: Keys,
}

impl<Io: Read> WeakDecoder<Io> {
    pub fn new(io: Io, keys: Keys) -> Self {
        WeakDecoder { io, keys }
    }
}

impl<Io: Read> Read for WeakDecoder<Io> {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        let bytes = self.io.read(buf)?;
        for i in 0..bytes {
            buf[i] = self.keys.decode_byte(buf[i]);
        }
        Ok(bytes)
    }
}