aboutsummaryrefslogtreecommitdiff
path: root/src/zip/encryption
diff options
context:
space:
mode:
authorIgor Tolmachev <me@igorek.dev>2024-07-20 16:52:39 +0900
committerIgor Tolmachev <me@igorek.dev>2024-07-20 16:52:39 +0900
commit7bcdc3b4ca460aec2b98fb2dca6165788c562b05 (patch)
tree63f9616fc1b7f9ca6e414a4d32910720e155690c /src/zip/encryption
parent5f4ceda88c7299deb317f8d22a99ab2521c5a380 (diff)
downloadarchivator-7bcdc3b4ca460aec2b98fb2dca6165788c562b05.tar.gz
archivator-7bcdc3b4ca460aec2b98fb2dca6165788c562b05.zip
Partial aes implementation and others improvements
Diffstat (limited to 'src/zip/encryption')
-rw-r--r--src/zip/encryption/aes.rs46
-rw-r--r--src/zip/encryption/mod.rs5
-rw-r--r--src/zip/encryption/weak.rs105
3 files changed, 156 insertions, 0 deletions
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 @@
1use crate::utils::ReadUtils;
2use aes::cipher::generic_array::GenericArray;
3use aes::cipher::BlockEncrypt;
4use std::io::{Read, Result as IoResult};
5
6#[allow(dead_code)]
7pub struct AesDecoder<Io: Read, Aes: BlockEncrypt> {
8 io: Io,
9 aes: Aes,
10
11 counter: u128,
12 block: [u8; 16],
13 cursor: usize,
14}
15
16impl<Io: Read, Aes: BlockEncrypt> AesDecoder<Io, Aes> {
17 pub fn new(mut io: Io, aes: Aes) -> IoResult<Self> {
18 let block = io.read_arr::<16>()?;
19 let mut decoder = Self {
20 io,
21 aes,
22 counter: 1,
23 block,
24 cursor: 0,
25 };
26 decoder.decrypt_block();
27 Ok(decoder)
28 }
29
30 #[inline]
31 fn decrypt_block(&mut self) {
32 let mut mask = self.counter.to_le_bytes();
33 self.aes
34 .encrypt_block(GenericArray::from_mut_slice(&mut mask));
35 for (b, m) in self.block.iter_mut().zip(mask) {
36 *b ^= m
37 }
38 self.counter += 1;
39 }
40}
41
42impl<Io: Read, Aes: BlockEncrypt> Read for AesDecoder<Io, Aes> {
43 fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
44 todo!()
45 }
46}
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 @@
1mod aes;
2mod weak;
3
4pub use aes::AesDecoder;
5pub 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 @@
1use std::io::{Read, Result as IoResult};
2
3const TABLE: [u32; 256] = generate_table();
4
5const fn generate_table() -> [u32; 256] {
6 let mut table = [0; 256];
7
8 let mut i = 0;
9 while i <= 255 {
10 let mut t = i as u32;
11
12 let mut j = 0;
13 while j < 8 {
14 if (t & 1) > 0 {
15 t = (t >> 1) ^ 0xEDB88320
16 } else {
17 t >>= 1
18 }
19 j += 1;
20 }
21
22 table[i] = t;
23 i += 1
24 }
25
26 table
27}
28
29fn crc32(byte: u8, crc: u32) -> u32 {
30 (crc >> 8) ^ TABLE[((crc & 0xFF) as u8 ^ byte) as usize]
31}
32
33pub struct Keys {
34 key0: u32,
35 key1: u32,
36 key2: u32,
37}
38
39impl Keys {
40 pub fn new() -> Self {
41 Self {
42 key0: 305419896,
43 key1: 591751049,
44 key2: 878082192,
45 }
46 }
47
48 fn update(&mut self, byte: u8) {
49 self.key0 = crc32(byte, self.key0);
50 self.key1 = self
51 .key1
52 .wrapping_add(self.key0 & 0xFF)
53 .wrapping_mul(134775813)
54 .wrapping_add(1);
55 self.key2 = crc32((self.key1 >> 24) as u8, self.key2);
56 }
57
58 pub fn set_password(&mut self, passwd: &[u8]) {
59 for b in passwd {
60 self.update(*b)
61 }
62 }
63
64 pub fn set_header(&mut self, header: [u8; 12]) -> u8 {
65 for b in &header[..11] {
66 self.decode_byte(*b);
67 }
68 self.decode_byte(header[11])
69 }
70
71 #[allow(dead_code)]
72 pub fn encode_bytes(&mut self, byte: u8) -> u8 {
73 let key = self.key2 | 2;
74 self.update(byte);
75 byte ^ ((key.wrapping_mul(key ^ 1)) >> 8) as u8
76 }
77
78 pub fn decode_byte(&mut self, byte: u8) -> u8 {
79 let key = self.key2 | 2;
80 let byte = byte ^ ((key.wrapping_mul(key ^ 1)) >> 8) as u8;
81 self.update(byte);
82 byte
83 }
84}
85
86pub struct WeakDecoder<Io: Read> {
87 io: Io,
88 keys: Keys,
89}
90
91impl<Io: Read> WeakDecoder<Io> {
92 pub fn new(io: Io, keys: Keys) -> Self {
93 WeakDecoder { io, keys }
94 }
95}
96
97impl<Io: Read> Read for WeakDecoder<Io> {
98 fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
99 let bytes = self.io.read(buf)?;
100 for i in 0..bytes {
101 buf[i] = self.keys.decode_byte(buf[i]);
102 }
103 Ok(bytes)
104 }
105}