enc_file 0.5.6

Password-based file encryption tool with a versioned header, AEAD, Argon2id KDF, and streaming mode. Library + CLI.
Documentation

Rust Crates.io Documentation Crates.io Crates.io Deploy

enc_file

Password-based, authenticated file encryption with a small versioned header and Argon2id KDF. Ships as both a library and a CLI.

Security note: This project is neither audited nor reviewed. It protects data at rest but cannot defend a compromised host or advanced side channels. Use at your own risk. For important or sensitive information, use Veracrypt (or similar) instead.

Features

  • Argon2id password KDF (per-file salt + stored parameters).
  • AEAD: XChaCha20-Poly1305 (default) or AES-256-GCM-SIV.
  • Compact binary header (magic, version, alg, KDF kind/params, salt, nonce, length).
  • Optional ASCII armor for transport.
  • Streaming mode for large files (constant memory; configurable chunk_size).
  • Zeroize-sensitive buffers and use secrecy wrappers.
  • Compute a file hash and print it as hex.
  • Usable as library and CLI.

Install

You can install enc-file in several ways:

From crates.io (requires Rust toolchain)

cargo install enc-file

From GitHub Releases (prebuilt binaries)

  1. Visit the Releases page.
  2. Download the binary for your platform.
  3. Place it in a directory in your PATH.

From source

# from source
cargo build --release
# binary
target/release/enc-file --help

Add to a project as a library:

# Cargo.toml
[dependencies]
enc_file = "0.5.0"

Available optional features (check Cargo.toml): aes for AES-256-GCM-SIV.


CLI Usage

enc-file <SUBCOMMAND>

Subcommands:
  enc     Encrypt a file (use --stream for large files)
  dec     Decrypt a file
  key     Manage an encrypted key map
  hash    Compute a file hash and print it as hex

Encrypt

# Simple: prompts for password (if your CLI is set up that way) or read from file if supported
enc-file enc --in secret.pdf --out secret.enc --alg xchacha

Options of interest:

  • --alg / -a AEAD algorithm: xchacha (default), aes
  • --stream stream mode for large inputs
  • --chunk-size <bytes> chunk size in streaming mode (default from library)
  • --armor ASCII-armor output
  • --force overwrite output if it exists
  • --password-file <PATH> read password from a file (if your CLI wiring includes it)

Decrypt

enc-file dec --in secret.enc --out secret.pdf

Hash

# Default blake3
enc-file hash README.md
# Specific algorithm (see below)
enc-file hash README.md --alg sha256

Key map (optional)

If you use the library’s key map helpers, the CLI can provide small helpers to init/save/load (if wired). Check enc-file key --help for available subcommands.


Library Usage

Encrypt / Decrypt bytes

use enc_file::{encrypt_bytes, decrypt_bytes, EncryptOptions, AeadAlg};
use secrecy::SecretString;

let pw = SecretString::new("correct horse battery staple".into());
let opts = EncryptOptions {
    alg: AeadAlg::XChaCha20Poly1305,
    ..Default::default()
};

let ct = encrypt_bytes(b"hello", pw.clone(), &opts)?;
let pt = decrypt_bytes(&ct, pw)?;
assert_eq!(pt, b"hello");
# Ok::<(), enc_file::EncFileError>(())

Encrypt / Decrypt files

use enc_file::{encrypt_file, decrypt_file, EncryptOptions, AeadAlg};
use secrecy::SecretString;
use std::path::Path;

let pw = SecretString::new("pw".into());
let opts = EncryptOptions {
    alg: AeadAlg::XChaCha20Poly1305, // or AeadAlg::Aes256GcmSiv (with "aes" feature)
    stream: false,  // set true for large files
    armor: false,
    ..Default::default()
};

let out = encrypt_file(Path::new("in.bin"), Some(Path::new("out.enc")), pw.clone(), opts)?;
let back = decrypt_file(&out, Some(Path::new("back.bin")), pw)?;
assert!(back.exists());
# Ok::<(), enc_file::EncFileError>(())

Streaming encryption

use enc_file::{encrypt_file_streaming, EncryptOptions, AeadAlg};
use secrecy::SecretString;
use std::path::Path;

let pw = SecretString::new("pw".into());
let opts = EncryptOptions {
    alg: AeadAlg::XChaCha20Poly1305,
    stream: true,
    chunk_size: 1024 * 1024, // 1 MiB chunks (example)
    ..Default::default()
};
let out = encrypt_file_streaming(Path::new("big.dat"), None, pw, opts)?;
# Ok::<(), enc_file::EncFileError>(())

Hash helpers

Supported Hash Algorithms

Both the CLI and library support multiple hashing algorithms for files and byte slices:

Algorithm CLI --alg value(s) Output length
BLAKE3 blake3 32 bytes
BLAKE2b-512 blake2b 64 bytes
SHA-256 sha256 32 bytes
SHA-512 sha512 64 bytes
SHA3-256 sha3-256, sha3256, sha3_256 32 bytes
SHA3-512 sha3-512, sha3512, sha3_512 64 bytes
XXH3-64 xxh3-64, xxh364 8 bytes
XXH3-128 xxh3-128, xxh3128 16 bytes
CRC32 crc32 4 bytes

CLI Example:

# Compute SHA3-512 hash of a file
enc-file hash --file data.bin --alg sha3-512

# Use XXH3-64 (fast, non-cryptographic)
enc-file hash --file data.bin --alg xxh3-64

Library Example:

use enc_file::{hash_file, to_hex_lower, HashAlg};
let digest = hash_file(std::path::Path::new("data.bin"), HashAlg::Sha3_512)?;
println!("{}", to_hex_lower(&digest));
# Ok::<(), enc_file::EncFileError>(())
use enc_file::{hash_bytes, hash_file, to_hex_lower, HashAlg};

let digest = hash_bytes(b"abc", HashAlg::Sha256);
assert_eq!(
    to_hex_lower(&digest),
    "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
);

let file_digest = hash_file(std::path::Path::new("README.md"), HashAlg::Blake3)?;
println!("{}", to_hex_lower(&file_digest));
# Ok::<(), enc_file::EncFileError>(())

Keyed BLAKE3 (MAC-style)

use enc_file::hash_bytes_keyed_blake3;
let key = [0u8; 32];
let tag = hash_bytes_keyed_blake3(b"message", &key);
assert_eq!(tag.len(), 32);
# Ok::<(), ()>(())

Key map helpers

use enc_file::{KeyMap, load_keymap, save_keymap};
use secrecy::SecretString;
use std::path::Path;

let mut km = KeyMap::new();
km.insert("service".into(), "supersecret".into());

let pw = SecretString::new("pw".into());
let path = Path::new("keymap.enc");
save_keymap(&km, path, pw.clone())?;

let loaded = load_keymap(path, pw)?;
assert_eq!(loaded, km);
# Ok::<(), enc_file::EncFileError>(())

Error handling

All fallible APIs return Result<_, EncFileError>. Common cases:

  • EncFileError::Io I/O failures
  • EncFileError::Crypto AEAD failures (bad password, tamper)
  • EncFileError::Format header parsing/validation issues

Tips

  • Use streaming for large files to keep memory predictable.
  • Consider --armor when moving ciphertexts through systems that mangle binaries.
  • For CLI automation, prefer --password-file over interactive prompts.

License

Licensed under either of

at your option.

Any contribution intentionally submitted for inclusion in this work shall be dual licensed as above, without any additional terms or conditions.


Note on names

The library crate is named enc_file (snake_case), which is the name you use when importing it in Rust code:

use enc_file::{hash_file, HashAlg};

The compiled CLI binary is named enc-file (kebab-case), which is the name you use when invoking it from the shell:

enc-file hash --file test.txt

This naming separation is intentional and follows common conventions.


Feedback & Issues

Feedback, bug reports, and pull requests are highly appreciated! Open an Issue or start a discussion.