1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum ZipEncryption {
9 ZipCrypto,
11 Aes128,
13 Aes192,
15 Aes256,
17 Unknown,
19}
20
21impl std::fmt::Display for ZipEncryption {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 match self {
24 ZipEncryption::ZipCrypto => write!(f, "ZipCrypto"),
25 ZipEncryption::Aes128 => write!(f, "AES-128"),
26 ZipEncryption::Aes192 => write!(f, "AES-192"),
27 ZipEncryption::Aes256 => write!(f, "AES-256"),
28 ZipEncryption::Unknown => write!(f, "Unknown"),
29 }
30 }
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
35pub enum RarEncryption {
36 Legacy,
38 Aes128,
40 Aes256,
42 Unknown,
44}
45
46impl std::fmt::Display for RarEncryption {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 match self {
49 RarEncryption::Legacy => write!(f, "RAR Legacy"),
50 RarEncryption::Aes128 => write!(f, "AES-128"),
51 RarEncryption::Aes256 => write!(f, "AES-256"),
52 RarEncryption::Unknown => write!(f, "Unknown"),
53 }
54 }
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
59pub enum SevenZEncryption {
60 Aes256,
62 Unknown,
64}
65
66impl std::fmt::Display for SevenZEncryption {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 match self {
69 SevenZEncryption::Aes256 => write!(f, "AES-256"),
70 SevenZEncryption::Unknown => write!(f, "Unknown"),
71 }
72 }
73}
74
75#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
77pub enum ArjEncryption {
78 Garble,
80 Gost40,
82 Gost256,
84 Unknown,
86}
87
88impl std::fmt::Display for ArjEncryption {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 match self {
91 ArjEncryption::Garble => write!(f, "Garble (XOR)"),
92 ArjEncryption::Gost40 => write!(f, "GOST40"),
93 ArjEncryption::Gost256 => write!(f, "GOST-256"),
94 ArjEncryption::Unknown => write!(f, "Unknown"),
95 }
96 }
97}
98
99impl ArjEncryption {
100 pub fn from_version(version: u8, is_garbled: bool) -> Option<Self> {
102 if !is_garbled {
103 return None;
104 }
105 Some(match version {
106 0 | 1 => ArjEncryption::Garble,
107 2 => ArjEncryption::Gost40,
108 v if v >= 3 => ArjEncryption::Gost256,
109 _ => ArjEncryption::Unknown,
110 })
111 }
112}
113
114#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
119pub enum EncryptionMethod {
120 #[default]
122 None,
123 Zip(ZipEncryption),
125 Rar(RarEncryption),
127 SevenZ(SevenZEncryption),
129 Ace,
131 Arj(ArjEncryption),
133 Unknown,
135}
136
137impl EncryptionMethod {
138 pub fn is_encrypted(&self) -> bool {
140 !matches!(self, EncryptionMethod::None)
141 }
142
143 pub fn is_weak(&self) -> bool {
145 matches!(
146 self,
147 EncryptionMethod::Zip(ZipEncryption::ZipCrypto)
148 | EncryptionMethod::Rar(RarEncryption::Legacy)
149 | EncryptionMethod::Arj(ArjEncryption::Garble)
150 | EncryptionMethod::Arj(ArjEncryption::Gost40)
151 )
152 }
153
154 pub fn description(&self) -> &'static str {
156 match self {
157 EncryptionMethod::None => "None",
158 EncryptionMethod::Zip(ZipEncryption::ZipCrypto) => "ZIP Traditional (weak)",
159 EncryptionMethod::Zip(ZipEncryption::Aes128) => "ZIP AES-128",
160 EncryptionMethod::Zip(ZipEncryption::Aes192) => "ZIP AES-192",
161 EncryptionMethod::Zip(ZipEncryption::Aes256) => "ZIP AES-256",
162 EncryptionMethod::Zip(ZipEncryption::Unknown) => "ZIP Encrypted",
163 EncryptionMethod::Rar(RarEncryption::Legacy) => "RAR Legacy (weak)",
164 EncryptionMethod::Rar(RarEncryption::Aes128) => "RAR AES-128",
165 EncryptionMethod::Rar(RarEncryption::Aes256) => "RAR AES-256",
166 EncryptionMethod::Rar(RarEncryption::Unknown) => "RAR Encrypted",
167 EncryptionMethod::SevenZ(SevenZEncryption::Aes256) => "7z AES-256",
168 EncryptionMethod::SevenZ(SevenZEncryption::Unknown) => "7z Encrypted",
169 EncryptionMethod::Ace => "ACE Blowfish",
170 EncryptionMethod::Arj(ArjEncryption::Garble) => "ARJ Garble (weak)",
171 EncryptionMethod::Arj(ArjEncryption::Gost40) => "ARJ GOST40 (weak)",
172 EncryptionMethod::Arj(ArjEncryption::Gost256) => "ARJ GOST-256",
173 EncryptionMethod::Arj(ArjEncryption::Unknown) => "ARJ Encrypted",
174 EncryptionMethod::Unknown => "Unknown",
175 }
176 }
177}
178
179impl std::fmt::Display for EncryptionMethod {
180 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181 write!(f, "{}", self.description())
182 }
183}
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188
189 #[test]
190 fn test_is_encrypted() {
191 assert!(!EncryptionMethod::None.is_encrypted());
192 assert!(EncryptionMethod::Zip(ZipEncryption::Aes256).is_encrypted());
193 assert!(EncryptionMethod::Ace.is_encrypted());
194 assert!(EncryptionMethod::Unknown.is_encrypted());
195 }
196
197 #[test]
198 fn test_is_weak() {
199 assert!(!EncryptionMethod::None.is_weak());
200 assert!(EncryptionMethod::Zip(ZipEncryption::ZipCrypto).is_weak());
201 assert!(!EncryptionMethod::Zip(ZipEncryption::Aes256).is_weak());
202 assert!(EncryptionMethod::Arj(ArjEncryption::Garble).is_weak());
203 assert!(EncryptionMethod::Arj(ArjEncryption::Gost40).is_weak());
204 assert!(!EncryptionMethod::Arj(ArjEncryption::Gost256).is_weak());
205 assert!(EncryptionMethod::Rar(RarEncryption::Legacy).is_weak());
206 assert!(!EncryptionMethod::Rar(RarEncryption::Aes256).is_weak());
207 }
208
209 #[test]
210 fn test_default() {
211 assert_eq!(EncryptionMethod::default(), EncryptionMethod::None);
212 }
213
214 #[test]
215 fn test_display() {
216 assert_eq!(
217 EncryptionMethod::Zip(ZipEncryption::Aes256).to_string(),
218 "ZIP AES-256"
219 );
220 assert_eq!(EncryptionMethod::Ace.to_string(), "ACE Blowfish");
221 }
222}