aboutsummaryrefslogtreecommitdiff
path: root/src/zip/encryption.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/zip/encryption.rs')
-rw-r--r--src/zip/encryption.rs62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/zip/encryption.rs b/src/zip/encryption.rs
new file mode 100644
index 0000000..84e30d5
--- /dev/null
+++ b/src/zip/encryption.rs
@@ -0,0 +1,62 @@
1use crate::utils::ReadUtils;
2use crate::zip::ZipResult;
3use crc32fast::Hasher;
4use std::io::{Read, Result as IoResult};
5
6fn crc32(byte: u8, crc32: u32) -> u32 {
7 let mut hasher = Hasher::new_with_initial(crc32 ^ 0xFFFFFFFF);
8 hasher.update(&[byte]);
9 hasher.finalize() ^ 0xFFFFFFFF
10}
11
12pub struct WeakDecoder<Io: Read> {
13 key0: u32,
14 key1: u32,
15 key2: u32,
16 io: Io,
17}
18
19impl<Io: Read> WeakDecoder<Io> {
20 pub fn new(io: Io, password: &str) -> ZipResult<Self> {
21 let mut decoder = Self {
22 key0: 305419896,
23 key1: 591751049,
24 key2: 878082192,
25 io,
26 };
27
28 for c in password.chars() {
29 decoder.update_keys(c as u8)
30 }
31
32 let buf = decoder.read_arr::<12>()?;
33
34 Ok(decoder)
35 }
36
37 fn update_keys(&mut self, byte: u8) {
38 self.key0 = crc32(byte, self.key0);
39 self.key1 = self
40 .key1
41 .wrapping_add(self.key0 & 0xFF)
42 .wrapping_mul(134775813)
43 .wrapping_add(1);
44 self.key2 = crc32((self.key1 >> 24) as u8, self.key2);
45 }
46
47 fn decode_byte(&mut self, byte: u8) -> u8 {
48 let key = self.key2 | 2;
49 byte ^ (((key * (key ^ 1)) >> 8) as u8)
50 }
51}
52
53impl<Io: Read> Read for WeakDecoder<Io> {
54 fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
55 let bytes = self.io.read(buf)?;
56 for i in 0..bytes {
57 buf[i] = self.decode_byte(buf[i]);
58 self.update_keys(buf[i])
59 }
60 Ok(bytes)
61 }
62}