zip Rust Library

repository·master·Indexed 43 days ago

https://github.com/zip-rs/zip2

A Rust library for reading and writing ZIP archives, implementing PKWARE's APPNOTE.TXT v6.3.9. Version 9.0.0-pre3 supports a wide range of compression algorithms including Deflate, Bzip2, ZStandard, LZMA, XZ, and PPMd, as well as AES encryption (AE-1 and AE-2) and ZipCrypto.

Tokens
11.4K
Snippets
42
Records
57
Agent score
57%

What's inside zip

  1. Setup fuzzing with `cargo afl`

    master

    Fuzzing is supported via cargo afl. To begin, install the tool and then follow the specific build commands for reading or writing.

    Install cargo-afl:

    cargo install cargo-afl

    Fuzzing Extraction (Reading):

    1. Create an output directory: mkdir -vp fuzz-read-out
    2. Build the fuzzer: cargo afl build --manifest-path=fuzz/Cargo.toml --all-features -p fuzz_read
    3. Run with a curated corpus: cargo afl fuzz -i fuzz/read/in -o fuzz-read-out fuzz/target/debug/fuzz_read
    4. Run with test data: cargo afl fuzz -i tests/data -e zip -o fuzz-read-out fuzz/target/debug/fuzz_read

    Fuzzing Creation (Writing):

    1. Create an output directory: mkdir -vp fuzz-write-out
    2. Build the fuzzer: cargo afl build --manifest-path=fuzz/Cargo.toml --all-features -p fuzz_write
    3. Run with corpus and dictionary: cargo afl fuzz -x fuzz/write/fuzz.dict -i fuzz/write/in -o fuzz-write-out fuzz/target/debug/fuzz_write
    # Example: Install cargo-afl
    cargo install cargo-afl
  2. Configure `zip` for Wasm environments

    master

    When working in a WebAssembly (Wasm) environment, you may need to disable features that rely on non-Rust libraries. It is recommended to set default-features = false and manually enable only the required features (e.g., deflate, zstd, time).

    # example configuration for Wasm
    zip = { version = "latest", default-features = false, features = [
        "deflate64",
        "deflate",
        "lzma",
        "time",
        "zstd",
    ] }
  3. Understand the AES encryption file structure

    master

    AES encrypted files in this implementation follow the WinZip specification. The structure of the encrypted data section is:

    1. Salt: Variable length depending on AesMode.
    2. Password Verification Value: Exactly 2 bytes (PWD_VERIFY_LENGTH).
    3. Encrypted Data: The actual payload.
    4. Authentication Code: Exactly 10 bytes (AUTH_CODE_LENGTH), used for HMAC-Sha1-80 integrity verification.

    If the file is marked as AE-2, the CRC field is ignored even if it is set.

  4. Available ZIP compression methods

    master

    The CompressionMethod enum identifies the storage format used to compress a file within a ZIP archive. When creating ZIP files, you can specify the method using crate::write::FileOptions::compression_method.

    Note that availability of certain methods depends on enabled Cargo features (e.g., deflate64, bzip2, zstd, lzma, xz, ppmd, aes-crypto).

    Common methods include:

    • Stored: No compression applied.
    • Deflated: Standard Deflate compression (requires _deflate-any).
    • Deflate64: Deflate64 compression (requires deflate64).
    • Bzip2: BZIP2 compression (requires _bzip2_any).
    • Zstd: ZStandard compression (requires zstd).
    • Lzma: LZMA compression (requires lzma).
    • Xz: XZ compression (requires xz).
    • Ppmd: PPMd compression (requires ppmd).
    • Aes: AES encryption (requires aes-crypto).
    • Legacy methods: Shrink, Reduce, and Implode (requires legacy-zip).
    use zip::CompressionMethod;
    
    // Example: Using a compression method in FileOptions (contextual)
    // let options = FileOptions::default().compression_method(CompressionMethod::Deflated);
  5. Safely extract files using enclosed_name

    master

    When extracting files from a ZIP archive, using the raw filename is dangerous as it may contain absolute paths or directory traversal components (e.g., ../).

    To prevent path-based exploits, use the enclosed_name method. It ensures the path:

    • Does not contain NULL bytes.
    • Is not an absolute path.
    • Cannot resolve to a path outside the current directory (e.g., foo/../../bar is rejected).

    If enclosed_name returns None, the file should be considered unsafe for extraction.

    // Assuming `zip_file` is an instance of `ZipFile` or `ZipFileSeek`
    if let Some(safe_path) = zip_file.enclosed_name() {
        // It is safe to use `safe_path` for extraction
        std::fs::create_dir_all(safe_path.parent().unwrap())?;
        std::fs::File::create(safe_path)?;
    }
  6. Encrypt files with AES using `AesWriter`

    master

    To encrypt data using AES, use AesWriter. This writer handles the generation of a random salt, derivation of keys via PBKDF2, and the appending of the HMAC authentication code.

    1. Initialize the writer with AesWriter::new_with_options(writer, aes_mode, password, custom_salt). Pass None for custom_salt to use a randomly generated one.
    2. Write your plaintext data using the Write trait implementation.
    3. Crucially, call .finish() to write the encrypted file header and the final 10-byte authentication code. If you do not call finish(), the archive will be invalid.

    Warning: AesWriter uses an internal buffer to ensure proper encryption and zeroizes memory to prevent cleartext leakage.

    use std::io::Write;
    // Assuming AesWriter and AesMode are available in scope
    let mut writer = AesWriter::new_with_options(&mut output_writer, AesMode::Aes256, password, None)?;
    writer.write_all(plaintext_data)?;
    writer.finish()?; // Must call finish to append HMAC and header
  7. Decrypt AES encrypted files with `AesReader`

    master

    To decrypt a file encrypted with AES, use AesReader to read the header and validate the password. The validate method performs an initial password check using PBKDF2. Note that a full integrity check (HMAC) is only performed after the entire file has been read via the resulting AesReaderValid instance.

    1. Create an AesReader using AesReader::new(reader, aes_mode, compressed_size).
    2. Call .validate(password) to get an AesReaderValid instance.
    3. Read the data from the AesReaderValid instance. If the password was incorrect or the data was tampered with, the final read call (when data_remaining reaches 0) will return an io::Error with ErrorKind::InvalidData.

    Note: There is a 1 in 65,536 chance that an incorrect password passes the initial validate check; the HMAC check in AesReaderValid is the definitive verification.

    use std::io::Read;
    // Assuming AesReader and AesMode are available in scope
    let mut reader = AesReader::new(&mut input_reader, AesMode::Aes256, compressed_size);
    let mut valid_reader = reader.validate(password_bytes)?;
    let mut decrypted_data = Vec::new();
    valid_reader.read_to_end(&mut decrypted_data)?;
  8. Write ZIP archives

    master

    The library provides three primary ways to write ZIP files:

    1. Create a new archive: Use ZipWriter::new().
    2. Append to an existing archive: Use ZipWriter::new_append() to read and add content to an existing file.
    3. Stream mode: Use ZipWriter::new_stream() for writing in a streaming fashion.
  9. Use nt-time feature for Windows file times

    master

    If you need to work with Windows-specific file time types, enable the nt-time feature in your Cargo.toml. This allows the Ntfs struct to provide methods that return nt_time::FileTime instead of raw u64 values.

    Methods available with nt-time enabled:

    • modified_file_time()
    • accessed_file_time()
    • created_file_time()
  10. Available feature flags for compression and encryption

    master

    You can enable or disable specific compression algorithms and features using Cargo features. By default, the following are enabled: aes-crypto, bzip2, deflate, deflate64, lzma, ppmd, time, xz, and zstd.

    FeatureDescription
    aes-cryptoEnables AES decryption (AE-1 and AE-2).
    deflateDefault deflate compression (quality 1..=264).
    deflate-flate2Uses flate2 backend for deflate quality 1..=9.
    deflate-zopfliUses zopfli for highly effective (but slow) deflate compression (quality 10..=264).
    deflate64Enables Deflate64 decompression.
    lzmaEnables LZMA decompression.
    bzip2Enables BZip2 compression/decompression.
    ppmdEnables PPMd compression/decompression.
    timeEnables features using the time crate.
    chronoConverts zip::DateTime to/from chrono::NaiveDateTime.
    jiff-02Converts zip::DateTime to/from jiff::civil::DateTime.
    nt-timeReturns NTFS timestamps as nt_time::FileTime.
    xzEnables XZ compression/decompression.
    zstdEnables Zstandard compression/decompression.
  11. Supported compression formats and encryption

    master

    The zip library supports various compression algorithms and encryption methods for both reading and writing.

    Reading Support:

    • Stored (none)
    • Implode, Shrink, Reduce
    • Deflate
    • Deflate64 (Decompression only)
    • Bzip2
    • ZStandard
    • LZMA (Decompression only)
    • XZ
    • PPMd
    • AES encryption (AE-1 and AE-2)
    • ZipCrypto (deprecated)

    Writing Support:

    • Stored (none)
    • Deflate
    • Bzip2
    • ZStandard
    • XZ
    • PPMd
    • AES encryption
    • ZipCrypto (deprecated)