Skip to main content

age_setup/
security.rs

1//! Memory security utilities.
2//!
3//! This module provides functions for securely erasing sensitive data from memory,
4//! ensuring that secrets are not left behind after use. It wraps the [`zeroize`]
5//! crate to guarantee that overwrites are not optimized away by the compiler.
6
7use zeroize::Zeroize;
8
9/// Overwrites a byte buffer with zeros, preventing sensitive data from lingering
10/// in memory.
11///
12/// This is a thin wrapper around the [`Zeroize`] trait from the `zeroize` crate.
13/// It guarantees that the memory will be cleared even if the compiler would
14/// otherwise optimize away a simple assignment (e.g., a `memset` call that appears
15/// dead).
16///
17/// # Why is this important?
18///
19/// When secret keys, passwords, or other sensitive data are no longer needed, they
20/// should be explicitly erased from memory. Otherwise, they might remain in
21/// freed memory pages, swap space, or core dumps, where they could be recovered
22/// by an attacker.
23///
24/// # Example
25///
26/// ```rust
27/// use age_setup::security::wipe_memory;
28///
29/// let mut secret = vec![0x41, 0x42, 0x43]; // "ABC"
30/// wipe_memory(&mut secret);
31/// assert_eq!(secret, vec![0, 0, 0]);
32/// ```
33///
34/// # How it works
35///
36/// The `zeroize` crate implements the [`Zeroize`] trait for `u8` slices. When
37/// called, it writes zeros to every element, using a volatile write to prevent
38/// the compiler from optimizing the operation away. After this function returns,
39/// the original data is irreversibly gone from that mutable slice.
40///
41/// # Safety
42///
43/// This function is memory‑safe. It operates on a mutable reference and does not
44/// read or write beyond the bounds of the slice. It never panics.
45pub fn wipe_memory(data: &mut [u8]) {
46    data.zeroize();
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn wipe_non_empty_buffer() {
55        let mut v = vec![1, 2, 3];
56        wipe_memory(&mut v);
57        assert_eq!(v, vec![0, 0, 0]);
58    }
59
60    #[test]
61    fn wipe_empty_buffer() {
62        let mut v: Vec<u8> = vec![];
63        wipe_memory(&mut v);
64        assert_eq!(v, vec![]);
65    }
66
67    #[test]
68    fn wipe_sensitive_data() {
69        let mut secret_key = b"AGE-SECRET-KEY-1TEST".to_vec();
70        wipe_memory(&mut secret_key);
71        assert!(secret_key.iter().all(|&b| b == 0));
72    }
73}