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
//! # PBKDF2-HMAC-SHA512 Key Derivation
//!
//! This module provides PBKDF2-HMAC-SHA512 key derivation for AES Crypt v3 files.
//! PBKDF2 (Password-Based Key Derivation Function 2) is used to derive encryption
//! keys from passwords with a configurable iteration count for security.
use crate;
use crateAescryptError;
use Hmac;
use pbkdf2;
use ;
use Sha512;
/// Derive PBKDF2-HMAC-SHA512 key directly into a secure buffer.
///
/// This function performs PBKDF2 key derivation using HMAC-SHA512 as the underlying
/// pseudorandom function. The derived key is written directly into the provided output
/// buffer, avoiding unnecessary allocations and copies.
///
/// # Thread Safety
///
/// This function is **thread-safe** and can be called concurrently from multiple threads.
/// All operations are pure (no shared mutable state).
///
/// # Arguments
///
/// * `password` - The password to derive the key from (wrapped in `PasswordString` for security)
/// * `salt` - 16-byte salt value (should be random and unique per encryption)
/// * `iterations` - Number of PBKDF2 iterations (must be ≥ 1, typically 100,000-500,000)
/// * `out_key` - Output buffer where the 32-byte derived key will be written
///
/// # Returns
///
/// Returns `Ok(())` if key derivation succeeds, or an error if:
/// - `iterations` is 0
/// - PBKDF2 computation fails
///
/// # Security
///
/// - Uses secure-gate types throughout for automatic zeroization
/// - Output buffer is zeroized on drop
/// - Password never exposed in plain form (scoped access via `.with_secret()`)
/// - Salt and key are protected by secure-gate wrappers
///
/// # Errors
///
/// - [`AescryptError::Crypto`] - If iterations is 0 or PBKDF2 computation fails
///
/// # Example
///
/// ```
/// use aescrypt_rs::kdf::pbkdf2::derive_pbkdf2_key;
/// use aescrypt_rs::aliases::{PasswordString, Salt16, Aes256Key32};
///
/// let password = PasswordString::new("my-secret-password".to_string());
/// let salt = Salt16::from([0x42; 16]); // In production, use a random salt (e.g. `Salt16::from_random()` or `Pbkdf2Builder`)
/// let mut key = Aes256Key32::new([0u8; 32]);
///
/// derive_pbkdf2_key(&password, &salt, 300_000, &mut key)?;
/// // Key is now derived and stored securely in `key`
/// # Ok::<(), aescrypt_rs::AescryptError>(())
/// ```