use crate::utils::ReadUtils; use crate::zip::{ZipError, ZipResult}; 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 b = 0; while b <= 255 { let mut crc = b as u32; let mut i = 0; while i < 8 { if (crc & 1) > 0 { crc = (crc >> 1) ^ 0xEDB88320 } else { crc >>= 1 } i += 1; } table[b] = crc; b += 1 } table } fn crc32(byte: u8, crc: u32) -> u32 { (crc >> 8) ^ TABLE[((crc & 0xFF) as u8 ^ byte) as usize] } pub struct WeakDecoder { key0: u32, key1: u32, key2: u32, io: Io, } impl WeakDecoder { pub fn new(io: Io, check: u8, password: &[u8]) -> ZipResult { let mut decoder = Self { key0: 305419896, key1: 591751049, key2: 878082192, io, }; for c in password { decoder.update_keys(*c) } let buf = decoder.read_arr::<12>()?; if check != buf[11] { return Err(ZipError::IncorrectPassword.into()); } Ok(decoder) } fn update_keys(&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); } 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_keys(byte); byte } } impl Read for WeakDecoder { fn read(&mut self, buf: &mut [u8]) -> IoResult { let bytes = self.io.read(buf)?; for i in 0..bytes { buf[i] = self.decode_byte(buf[i]); } Ok(bytes) } }