From a83767f9fbd51df654901b52bdba7838f6a10bf9 Mon Sep 17 00:00:00 2001 From: Igor Tolmachev Date: Tue, 16 Jul 2024 01:59:53 +0900 Subject: Add traditional PKWARE decryption. - Compression and encryption may not work together - Password check is not yet implemented - Unoptimized crc32 function --- src/zip/encryption.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/zip/encryption.rs (limited to 'src/zip/encryption.rs') 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 @@ +use crate::utils::ReadUtils; +use crate::zip::ZipResult; +use crc32fast::Hasher; +use std::io::{Read, Result as IoResult}; + +fn crc32(byte: u8, crc32: u32) -> u32 { + let mut hasher = Hasher::new_with_initial(crc32 ^ 0xFFFFFFFF); + hasher.update(&[byte]); + hasher.finalize() ^ 0xFFFFFFFF +} + +pub struct WeakDecoder { + key0: u32, + key1: u32, + key2: u32, + io: Io, +} + +impl WeakDecoder { + pub fn new(io: Io, password: &str) -> ZipResult { + let mut decoder = Self { + key0: 305419896, + key1: 591751049, + key2: 878082192, + io, + }; + + for c in password.chars() { + decoder.update_keys(c as u8) + } + + let buf = decoder.read_arr::<12>()?; + + 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; + byte ^ (((key * (key ^ 1)) >> 8) as u8) + } +} + +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]); + self.update_keys(buf[i]) + } + Ok(bytes) + } +} -- cgit v1.2.3