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
//! Key pair generation.
//!
//! This module provides [`build_keypair`], the primary function for generating
//! a fresh X25519 key pair suitable for use with the `age` encryption tool.
//! The generation uses cryptographically secure randomness provided by the
//! operating system.
use crateResult;
use crateKeyPair;
use cratePublicKey;
use crateSecretKey;
use ExposeSecret;
use Identity;
/// Generates a new age X25519 key pair.
///
/// This is the recommended way to create a [`KeyPair`]. It performs the following
/// steps **securely and automatically**:
///
/// 1. **Generate a fresh identity** using the `age` crate. The identity is
/// created with randomness sourced from the operating system's secure
/// random number generator (e.g. `/dev/urandom` on Linux, `getrandom`).
/// 2. **Extract the public and secret halves** from the identity. The secret
/// is temporarily exposed in a local variable which is immediately moved
/// into a [`SecretKey`] that guarantees zeroization on drop.
/// 3. **Validate both keys** – the public key is checked for the `"age1"`
/// prefix, the secret key for `"AGE-SECRET-KEY-1"`. This step acts as a
/// safety net; because the strings originate from the `age` crate they are
/// expected to be valid, but the check catches potential internal bugs
/// early.
/// 4. **Assemble the [`KeyPair`]** and return it to the caller.
///
/// The entire operation is **infallible** in practice – [`Identity::generate`]
/// does not return a `Result`. The only possible failures are the validation
/// steps, which would indicate a serious bug in the `age` library or this
/// crate.
///
/// # Returns
///
/// * `Ok(KeyPair)` – a newly generated key pair ready for encryption and
/// decryption.
/// * `Err(Error::Validation(...))` – if the generated key strings fail the
/// prefix checks (should never happen in practice).
///
/// # Security properties
///
/// * The secret key is automatically **zeroized** when the `KeyPair` (or its
/// `SecretKey` field) is dropped. No additional cleanup is needed.
/// * The function itself holds the raw secret string for a minimal amount of
/// time; it is moved directly into a [`Zeroizing`]-backed container.
/// * The randomness source is the same as the one used by the `age` CLI tool
/// and is suitable for production use.
///
/// # Examples
///
/// ```rust
/// use age_setup::build_keypair;
///
/// let kp = build_keypair()?;
/// assert!(kp.public.expose().starts_with("age1"));
/// assert!(kp.secret.expose_secret().starts_with("AGE-SECRET-KEY-1"));
/// # Ok::<(), age_setup::Error>(())
/// ```