oletools_rs 0.1.0

Rust port of oletools — analysis tools for Microsoft Office files (VBA macros, DDE, OLE objects, RTF exploits)
Documentation
/// Office file decryption (wrapper around office-crypto crate).
///
/// Only available when the `crypto` feature is enabled.
///
/// Supports decrypting password-protected Office files (Office 2007+
/// OOXML encryption and legacy Office 97-2003 encryption).

#[cfg(feature = "crypto")]
use crate::error::{Error, Result};

/// Decrypt an Office file with the given passwords.
///
/// Tries each password in order and returns the decrypted content
/// on the first successful attempt.
#[cfg(feature = "crypto")]
pub fn decrypt<P: AsRef<std::path::Path>>(
    path: P,
    passwords: &[&str],
) -> Result<Vec<u8>> {
    let data = std::fs::read(path)?;
    decrypt_from_bytes(&data, passwords)
}

/// Decrypt Office file content from a byte slice.
#[cfg(feature = "crypto")]
pub fn decrypt_from_bytes(data: &[u8], passwords: &[&str]) -> Result<Vec<u8>> {
    for &password in passwords {
        match office_crypto::decrypt_from_bytes(data, password) {
            Ok(decrypted) => return Ok(decrypted),
            Err(_) => continue,
        }
    }
    Err(Error::WrongPassword)
}

/// Check if an OLE file is encrypted.
///
/// Detects Office 97-2003 and 2007+ encryption by looking for
/// the EncryptionInfo or EncryptedPackage streams.
#[cfg(feature = "crypto")]
pub fn is_encrypted(data: &[u8]) -> bool {
    use crate::ole::container::OleFile;

    if let Ok(ole) = OleFile::from_bytes(data) {
        let streams = ole.list_streams();
        streams.iter().any(|s| {
            let lower = s.to_lowercase();
            lower.contains("encryptedpackage") || lower.contains("encryptioninfo")
        })
    } else {
        false
    }
}

// Re-export empty module when crypto feature is disabled
// to allow `mod crypto` in lib.rs without conditional compilation