pub fn decrypt<R, W>(
input: R,
output: W,
password: &PasswordString,
) -> Result<(), AescryptError>Expand description
Decrypts an AES Crypt v0–v3 file streamed from input and writes the
recovered plaintext to output.
decrypt parses the header (auto-detecting the format version), derives
the setup key (PBKDF2-HMAC-SHA512 for v3, ACKDF-SHA-256 for v0/v1/v2),
recovers the session IV/key, and runs the version-appropriate streaming
CBC loop. Only the version dispatched at the top of the function is
observable on output — the internal StreamConfig mapping is mediated by
crate::decryption::decrypt_ciphertext_stream.
§Format
- v0: legacy modulo padding, 32-byte trailing HMAC, ACKDF setup key.
- v1/v2: scattered modulo + 32-byte HMAC, ACKDF setup key.
- v3: PKCS#7 padding, 32-byte HMAC, PBKDF2-HMAC-SHA512 setup key, version byte folded into the session HMAC.
See crate::decryption for the full per-stage compatibility matrix.
§Errors
AescryptError::Io—input.readoroutput.write_allreturned an I/O error.AescryptError::Header— invalid magic, non-zero v1–v3 reserved byte, too many extensions, malformed iteration count, session-HMAC mismatch ("session data corrupted or tampered"), payload-HMAC mismatch ("HMAC verification failed"), or invalid v3 PKCS#7 padding.AescryptError::UnsupportedVersion— version byte is> 3.AescryptError::Crypto— KDF failure (PBKDF2 or ACKDF, including non-UTF-8 password bytes for v0–v2).
§Panics
Never panics on valid or malformed input. The internal unreachable! is
guarded by crate::decryption::read_file_version, which clamps the
version to 0..=3.
§Security
Decrypt-then-verify. For payloads larger than roughly two AES blocks
(≈32 bytes of ciphertext after the session block), decrypted data is
written to output incrementally as blocks are processed. The payload
HMAC and v3 PKCS#7 validation run only after the ciphertext stream has been
read.
If this function returns an error — for example
"HMAC verification failed" or a v3 padding error — output may already
contain partial, unauthenticated plaintext. Callers must discard or
overwrite output on error and must not treat its contents as secret or
trustworthy.
use aescrypt_rs::{decrypt, PasswordString};
use std::io::Cursor;
let mut plaintext = Vec::new();
if decrypt(reader, &mut plaintext, &password).is_err() {
plaintext.clear(); // mandatory when using an accumulating buffer
}Other security properties:
- Setup, session, and intermediate keys live in
secure-gatealiases and zeroize on drop. ThePasswordStringnever appears in plain form outside scoped reveals. - HMAC and PKCS#7 padding are compared in constant time
(
secure-gate’sConstantTimeEq). - Pre-authentication parsing is bounded: the header has fixed sizes,
extensions are capped at 256 entries, and the iteration count is clamped
to
PBKDF2_MAX_ITER.
§Compatibility — empty password
Unlike crate::encrypt(), this function does not reject an empty
password. An empty password against a file encrypted with a non-empty
password will fail at HMAC verification. This asymmetry is intentional:
third-party AES Crypt tools may produce files encrypted with an empty
password, and decrypt must be able to handle them.
§Thread Safety
decrypt is Send whenever its R/W are. There is no shared mutable
state, so multiple threads may call decrypt concurrently on independent
inputs/outputs.
§Examples
use aescrypt_rs::{decrypt, PasswordString};
use std::io::Cursor;
let password = PasswordString::new("secret".to_string());
let ciphertext: &[u8] = b""; // contents of a .aes file
let mut plaintext = Vec::new();
match decrypt(Cursor::new(ciphertext), &mut plaintext, &password) {
Ok(()) => { /* plaintext is now authenticated */ }
Err(_) => plaintext.clear(),
}Threaded usage:
use aescrypt_rs::{decrypt, PasswordString};
use std::io::Cursor;
use std::thread;
let password = PasswordString::new("secret".to_string());
let encrypted = b"encrypted data...";
let handle = thread::spawn(move || {
let mut plaintext = Vec::new();
decrypt(Cursor::new(encrypted), &mut plaintext, &password)
});
let _result = handle.join().unwrap();§See also
crate::encrypt()— inverse operation.crate::read_version— header-only version triage.