#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ZipEncryption {
ZipCrypto,
Aes128,
Aes192,
Aes256,
Unknown,
}
impl std::fmt::Display for ZipEncryption {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ZipEncryption::ZipCrypto => write!(f, "ZipCrypto"),
ZipEncryption::Aes128 => write!(f, "AES-128"),
ZipEncryption::Aes192 => write!(f, "AES-192"),
ZipEncryption::Aes256 => write!(f, "AES-256"),
ZipEncryption::Unknown => write!(f, "Unknown"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RarEncryption {
Legacy,
Aes128,
Aes256,
Unknown,
}
impl std::fmt::Display for RarEncryption {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RarEncryption::Legacy => write!(f, "RAR Legacy"),
RarEncryption::Aes128 => write!(f, "AES-128"),
RarEncryption::Aes256 => write!(f, "AES-256"),
RarEncryption::Unknown => write!(f, "Unknown"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SevenZEncryption {
Aes256,
Unknown,
}
impl std::fmt::Display for SevenZEncryption {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SevenZEncryption::Aes256 => write!(f, "AES-256"),
SevenZEncryption::Unknown => write!(f, "Unknown"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ArjEncryption {
Garble,
Gost40,
Gost256,
Unknown,
}
impl std::fmt::Display for ArjEncryption {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ArjEncryption::Garble => write!(f, "Garble (XOR)"),
ArjEncryption::Gost40 => write!(f, "GOST40"),
ArjEncryption::Gost256 => write!(f, "GOST-256"),
ArjEncryption::Unknown => write!(f, "Unknown"),
}
}
}
impl ArjEncryption {
pub fn from_version(version: u8, is_garbled: bool) -> Option<Self> {
if !is_garbled {
return None;
}
Some(match version {
0 | 1 => ArjEncryption::Garble,
2 => ArjEncryption::Gost40,
v if v >= 3 => ArjEncryption::Gost256,
_ => ArjEncryption::Unknown,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum EncryptionMethod {
#[default]
None,
Zip(ZipEncryption),
Rar(RarEncryption),
SevenZ(SevenZEncryption),
Ace,
Arj(ArjEncryption),
Unknown,
}
impl EncryptionMethod {
pub fn is_encrypted(&self) -> bool {
!matches!(self, EncryptionMethod::None)
}
pub fn is_weak(&self) -> bool {
matches!(
self,
EncryptionMethod::Zip(ZipEncryption::ZipCrypto)
| EncryptionMethod::Rar(RarEncryption::Legacy)
| EncryptionMethod::Arj(ArjEncryption::Garble)
| EncryptionMethod::Arj(ArjEncryption::Gost40)
)
}
pub fn description(&self) -> &'static str {
match self {
EncryptionMethod::None => "None",
EncryptionMethod::Zip(ZipEncryption::ZipCrypto) => "ZIP Traditional (weak)",
EncryptionMethod::Zip(ZipEncryption::Aes128) => "ZIP AES-128",
EncryptionMethod::Zip(ZipEncryption::Aes192) => "ZIP AES-192",
EncryptionMethod::Zip(ZipEncryption::Aes256) => "ZIP AES-256",
EncryptionMethod::Zip(ZipEncryption::Unknown) => "ZIP Encrypted",
EncryptionMethod::Rar(RarEncryption::Legacy) => "RAR Legacy (weak)",
EncryptionMethod::Rar(RarEncryption::Aes128) => "RAR AES-128",
EncryptionMethod::Rar(RarEncryption::Aes256) => "RAR AES-256",
EncryptionMethod::Rar(RarEncryption::Unknown) => "RAR Encrypted",
EncryptionMethod::SevenZ(SevenZEncryption::Aes256) => "7z AES-256",
EncryptionMethod::SevenZ(SevenZEncryption::Unknown) => "7z Encrypted",
EncryptionMethod::Ace => "ACE Blowfish",
EncryptionMethod::Arj(ArjEncryption::Garble) => "ARJ Garble (weak)",
EncryptionMethod::Arj(ArjEncryption::Gost40) => "ARJ GOST40 (weak)",
EncryptionMethod::Arj(ArjEncryption::Gost256) => "ARJ GOST-256",
EncryptionMethod::Arj(ArjEncryption::Unknown) => "ARJ Encrypted",
EncryptionMethod::Unknown => "Unknown",
}
}
}
impl std::fmt::Display for EncryptionMethod {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.description())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_encrypted() {
assert!(!EncryptionMethod::None.is_encrypted());
assert!(EncryptionMethod::Zip(ZipEncryption::Aes256).is_encrypted());
assert!(EncryptionMethod::Ace.is_encrypted());
assert!(EncryptionMethod::Unknown.is_encrypted());
}
#[test]
fn test_is_weak() {
assert!(!EncryptionMethod::None.is_weak());
assert!(EncryptionMethod::Zip(ZipEncryption::ZipCrypto).is_weak());
assert!(!EncryptionMethod::Zip(ZipEncryption::Aes256).is_weak());
assert!(EncryptionMethod::Arj(ArjEncryption::Garble).is_weak());
assert!(EncryptionMethod::Arj(ArjEncryption::Gost40).is_weak());
assert!(!EncryptionMethod::Arj(ArjEncryption::Gost256).is_weak());
assert!(EncryptionMethod::Rar(RarEncryption::Legacy).is_weak());
assert!(!EncryptionMethod::Rar(RarEncryption::Aes256).is_weak());
}
#[test]
fn test_default() {
assert_eq!(EncryptionMethod::default(), EncryptionMethod::None);
}
#[test]
fn test_display() {
assert_eq!(EncryptionMethod::Zip(ZipEncryption::Aes256).to_string(), "ZIP AES-256");
assert_eq!(EncryptionMethod::Ace.to_string(), "ACE Blowfish");
}
}