aescrypt_rs/decryptor/
decrypt.rs

1//! src/core/decryptor/decrypt.rs
2//! Aescrypt decryption — secure-gate v0.5.5+ perfection (2025)
3
4use secure_gate::secure;
5
6use crate::decryptor::read::{
7    consume_all_extensions, read_exact_span, read_file_version, read_kdf_iterations,
8    read_reserved_modulo_byte,
9};
10use crate::decryptor::session::extract_session_data;
11use crate::decryptor::stream::{decrypt_ciphertext_stream, StreamConfig};
12
13use crate::aliases::{Aes256Key, Iv16, PasswordString};
14use crate::error::AescryptError;
15use crate::{derive_secure_ackdf_key, derive_secure_pbkdf2_key};
16use std::io::{Read, Write};
17
18/// Decrypt an Aescrypt file (v0–v3) — zero secret exposure, maximum security
19#[inline(always)]
20pub fn decrypt<R, W>(mut input: R, mut output: W, password: &PasswordString) -> Result<(), AescryptError>
21where
22    R: Read,
23    W: Write,
24{
25    let file_version = read_file_version(&mut input)?;
26    let reserved_modulo = read_reserved_modulo_byte(&mut input)?;
27    consume_all_extensions(&mut input, file_version)?;
28
29    let kdf_iterations = read_kdf_iterations(&mut input, file_version)?;
30
31    // Public IV — secure from the start
32    let public_iv: Iv16 = Iv16::from(read_exact_span(&mut input)?);
33
34    // Setup key — secure buffer from birth
35    let mut setup_key = secure!(Aes256Key, [0u8; 32].into());
36
37    if file_version <= 2 {
38        derive_secure_ackdf_key(password, &public_iv, &mut setup_key)?;
39    } else {
40        derive_secure_pbkdf2_key(password, &public_iv, kdf_iterations, &mut setup_key)?;
41    }
42
43    // Session key/IV — secure buffers from birth
44    let mut session_iv = Iv16::new([0u8; 16]);
45    let mut session_key = Aes256Key::new([0u8; 32]);
46
47    extract_session_data(
48        &mut input,
49        file_version,
50        &public_iv,
51        &setup_key,
52        &mut session_iv,
53        &mut session_key,
54    )?;
55
56    let stream_config = match file_version {
57        0 => StreamConfig::V0 { reserved_modulo },
58        1 => StreamConfig::V1,
59        2 => StreamConfig::V2,
60        3 => StreamConfig::V3,
61        _ => unreachable!("file_version validated in read_file_version"),
62    };
63
64    decrypt_ciphertext_stream(
65        &mut input,
66        &mut output,
67        &session_iv,
68        &session_key,
69        stream_config,
70    )?;
71
72    Ok(())
73}