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
use crateResult;
use crateDecryptError;
use SecretString;
use Read;
/// Decrypts ciphertext that was encrypted using a passphrase.
///
/// This function recovers the original plaintext from a binary ciphertext
/// produced by [`encrypt_with_passphrase`] (or the age CLI with `-p`).
/// It requires the same passphrase that was used for encryption.
///
/// The passphrase is immediately wrapped in a [`SecretString`], which
/// zeroizes the underlying memory on drop. The original `&str` provided
/// by the caller is left untouched; callers should manage its lifetime
/// accordingly.
///
/// # Parameters
///
/// * `ciphertext` – The encrypted age binary data.
/// * `passphrase` – The passphrase that was used to encrypt the data.
///
/// # Returns
///
/// * `Ok(Vec<u8>)` – The decrypted plaintext bytes.
/// * `Err(Error::Decrypt(...))` – If the ciphertext is malformed, the
/// passphrase is wrong, the data has been tampered with, or an
/// internal I/O error occurs.
///
/// # Errors
///
/// | Condition | Error Variant |
/// |----------------------------------------------------|----------------------------------------|
/// | Ciphertext is not a valid age‑encrypted stream | [`DecryptError::InvalidCiphertext`] |
/// | Passphrase does not match or data is tampered | [`DecryptError::Failed`] |
/// | I/O error during decryption (extremely rare) | [`DecryptError::Io`] |
///
/// There is no `InvalidIdentity` variant because the identity is
/// derived internally from the passphrase.
///
/// # Security Considerations
///
/// * **AEAD** – age uses authenticated encryption. Any modification
/// to the ciphertext will cause decryption to fail.
/// * **scrypt KDF** – age derives a symmetric key from the passphrase
/// using scrypt, which makes brute‑force attacks computationally
/// expensive. However, weak passphrases can still be cracked.
/// * **Passphrase handling** – the passphrase is moved into a
/// `SecretString` inside the function; the original `&str` remains
/// the caller's responsibility. Avoid logging or storing the
/// passphrase unnecessarily.
/// * **Memory** – the plaintext is returned as a standard `Vec<u8>`.
/// If the plaintext is highly sensitive, consider zeroizing it after
/// use with the `zeroize` crate.
///
/// # Example
///
/// ```rust
/// # fn main() -> age_crypto::errors::Result<()> {
/// let plaintext = b"Super secret data";
/// let pass = "my-strong-passphrase";
///
/// // Encrypt first
/// let encrypted = age_crypto::encrypt_with_passphrase(plaintext, pass)?;
///
/// // Then decrypt
/// let decrypted = age_crypto::decrypt_with_passphrase(encrypted.as_bytes(), pass)?;
/// assert_eq!(decrypted, plaintext);
/// # Ok(())
/// # }
/// ```
///
/// # See Also
///
/// * [`decrypt_with_passphrase_armor`] – armored (PEM‑like) variant.
/// * [`decrypt`] – key‑based decryption (X25519 identities).