1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//! src/kdf/ackdf.rs
//! AES Crypt Key Derivation Function (ACKDF) for v0–v2 files (read-only).
//!
//! ACKDF is the legacy KDF used by AES Crypt v0–v2: 8192 iterations of
//! SHA-256 over the previous hash and the UTF-16-LE-encoded password,
//! seeded with a 16-byte salt. It is exposed for callers that need to
//! decrypt legacy files; new files always use PBKDF2-HMAC-SHA512 (see
//! [`crate::kdf::pbkdf2`]) and are written by [`crate::encrypt()`].
//!
//! # Security
//!
//! - **Iteration count is fixed at 8192** by the AES Crypt v0–v2 spec; do not
//! reduce it. By modern standards 8192 SHA-256 iterations are weak; this
//! crate uses ACKDF only on the read path for legacy file compatibility.
//! - The intermediate `Sha256` hasher state lives on the stack and is reset
//! (but not explicitly zeroized) between iterations. The 32-byte hash state
//! is wrapped in [`crate::aliases::AckdfHashState32`] so it does zeroize on
//! drop. See the inline comment in the implementation.
use crate;
use crateutf8_to_utf16le;
use crateAescryptError;
use ;
use ;
/// Fixed ACKDF iteration count mandated by the AES Crypt v0–v2 file format
/// specification.
///
/// The unit is **iterations** (each iteration is a SHA-256 of the previous
/// 32-byte hash state followed by the UTF-16-LE password). This value is part
/// of the on-wire format and cannot be changed without breaking compatibility.
pub const ACKDF_ITERATIONS: u32 = 8192;
where
F1: FnOnce,
F2: FnOnce,
/// Derives the AES-256 setup key for AES Crypt v0–v2 files using ACKDF.
///
/// Performs [`ACKDF_ITERATIONS`] iterations of SHA-256 over the running
/// 32-byte hash state and the UTF-16-LE encoded password, writing the final
/// state into `out_key` directly (no return value, no intermediate
/// allocation).
///
/// # Format
///
/// `salt` is the 16-byte public IV from a v0/v1/v2 file header; the password
/// is re-encoded UTF-8 → UTF-16-LE because the AES Crypt v0–v2 spec hashes
/// passwords as UTF-16-LE little-endian code units.
///
/// # Errors
///
/// - [`AescryptError::Crypto`] — `password` is not valid UTF-8 (forwarded
/// from [`crate::utilities::utf8_to_utf16le`]).
///
/// # Panics
///
/// Never panics on valid input.
///
/// # Security
///
/// - Iteration count is fixed at 8192 by the AES Crypt v0–v2 spec. ACKDF is
/// weaker than PBKDF2-HMAC-SHA512; new files use
/// [`crate::derive_pbkdf2_key`] instead.
/// - `out_key` is a [`secure-gate`] alias and zeroizes on drop.
/// - The intermediate `Sha256` hasher state holds 8 × `u32` of derived data on
/// the stack and is `finalize_reset()`-ed between iterations, but is not
/// explicitly zeroized when the function returns. The intermediate hash
/// state is wrapped in [`crate::aliases::AckdfHashState32`] and does
/// zeroize on drop.
///
/// # Thread Safety
///
/// Pure function with no shared state; safe to call concurrently.
///
/// # See also
///
/// - [`crate::derive_pbkdf2_key`] — modern KDF used by v3 files.
///
/// [`secure-gate`]: https://github.com/Slurp9187/secure-gate