From 7bcdc3b4ca460aec2b98fb2dca6165788c562b05 Mon Sep 17 00:00:00 2001 From: Igor Tolmachev Date: Sat, 20 Jul 2024 16:52:39 +0900 Subject: Partial aes implementation and others improvements --- src/zip/encryption/aes.rs | 46 ++++++++++++++++++++ src/zip/encryption/mod.rs | 5 +++ src/zip/encryption/weak.rs | 105 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 src/zip/encryption/aes.rs create mode 100644 src/zip/encryption/mod.rs create mode 100644 src/zip/encryption/weak.rs (limited to 'src/zip/encryption') diff --git a/src/zip/encryption/aes.rs b/src/zip/encryption/aes.rs new file mode 100644 index 0000000..6f41aaa --- /dev/null +++ b/src/zip/encryption/aes.rs @@ -0,0 +1,46 @@ +use crate::utils::ReadUtils; +use aes::cipher::generic_array::GenericArray; +use aes::cipher::BlockEncrypt; +use std::io::{Read, Result as IoResult}; + +#[allow(dead_code)] +pub struct AesDecoder { + io: Io, + aes: Aes, + + counter: u128, + block: [u8; 16], + cursor: usize, +} + +impl AesDecoder { + pub fn new(mut io: Io, aes: Aes) -> IoResult { + let block = io.read_arr::<16>()?; + let mut decoder = Self { + io, + aes, + counter: 1, + block, + cursor: 0, + }; + decoder.decrypt_block(); + Ok(decoder) + } + + #[inline] + fn decrypt_block(&mut self) { + let mut mask = self.counter.to_le_bytes(); + self.aes + .encrypt_block(GenericArray::from_mut_slice(&mut mask)); + for (b, m) in self.block.iter_mut().zip(mask) { + *b ^= m + } + self.counter += 1; + } +} + +impl Read for AesDecoder { + fn read(&mut self, buf: &mut [u8]) -> IoResult { + todo!() + } +} diff --git a/src/zip/encryption/mod.rs b/src/zip/encryption/mod.rs new file mode 100644 index 0000000..8cacaf9 --- /dev/null +++ b/src/zip/encryption/mod.rs @@ -0,0 +1,5 @@ +mod aes; +mod weak; + +pub use aes::AesDecoder; +pub use weak::{Keys, WeakDecoder}; diff --git a/src/zip/encryption/weak.rs b/src/zip/encryption/weak.rs new file mode 100644 index 0000000..144cd53 --- /dev/null +++ b/src/zip/encryption/weak.rs @@ -0,0 +1,105 @@ +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, + } + } + + 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); + } + + pub fn set_password(&mut self, passwd: &[u8]) { + for b in passwd { + self.update(*b) + } + } + + pub fn set_header(&mut self, header: [u8; 12]) -> u8 { + for b in &header[..11] { + self.decode_byte(*b); + } + self.decode_byte(header[11]) + } + + #[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: Io, + keys: Keys, +} + +impl WeakDecoder { + pub fn new(io: Io, keys: Keys) -> Self { + WeakDecoder { io, keys } + } +} + +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.keys.decode_byte(buf[i]); + } + Ok(bytes) + } +} -- cgit v1.2.3