Skip to main content

age_setup/
keypair.rs

1use crate::public_key::PublicKey;
2use crate::secret_key::SecretKey;
3
4/// A cryptographic key pair for the age protocol.
5///
6/// Contains a [`PublicKey`] and a [`SecretKey`], both guaranteed to be valid
7/// age keys. The [`Debug`] implementation redacts the secret key value while
8/// displaying the public key in full.
9///
10/// # Obtaining a KeyPair
11///
12/// Use [`build_keypair`](crate::build_keypair) to generate a fresh key pair:
13///
14/// ```no_run
15/// use age_setup::build_keypair;
16///
17/// let kp = build_keypair()?;
18/// println!("Public: {}", kp.public);
19/// # Ok::<(), age_setup::Error>(())
20/// ```
21///
22/// # Debug Safety
23///
24/// The debug representation does **not** leak the secret key:
25///
26/// ```rust
27/// use age_setup::build_keypair;
28///
29/// let kp = build_keypair()?;
30/// let debug_str = format!("{:?}", kp);
31/// assert!(debug_str.contains(kp.public.expose()));
32/// assert!(!debug_str.contains(kp.secret.expose_secret()));
33/// # Ok::<(), age_setup::Error>(())
34/// ```
35///
36/// # See Also
37///
38/// * [`build_keypair`](crate::build_keypair) – Generates a new `KeyPair`.
39/// * [`SecretKey`](crate::SecretKey) – Zeroizing secret key wrapper.
40/// * [`PublicKey`](crate::PublicKey) – Validated public key wrapper.
41#[derive(Debug)]
42pub struct KeyPair {
43    /// The public key component.
44    pub public: PublicKey,
45    /// The secret key component (redacted in debug output).
46    pub secret: SecretKey,
47}
48
49impl KeyPair {
50    /// Creates a new `KeyPair` from existing keys.
51    ///
52    /// This constructor is crate-internal. External users should call
53    /// [`build_keypair`](crate::build_keypair) to generate a new pair.
54    ///
55    /// # Parameters
56    ///
57    /// * `public` – A validated [`PublicKey`].
58    /// * `secret` – A validated [`SecretKey`].
59    pub(crate) fn new(public: PublicKey, secret: SecretKey) -> Self {
60        Self { public, secret }
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use crate::build_keypair;
67
68    #[test]
69    fn generated_keypair_fields_are_valid() {
70        let kp = build_keypair().unwrap();
71        assert!(kp.public.expose().starts_with("age1"));
72        assert!(kp.secret.expose_secret().starts_with("AGE-SECRET-KEY-1"));
73    }
74
75    #[test]
76    fn generated_keypair_fields_are_non_empty() {
77        let kp = build_keypair().unwrap();
78        assert!(!kp.public.expose().is_empty());
79        assert!(!kp.secret.expose_secret().is_empty());
80    }
81
82    #[test]
83    fn debug_does_not_leak_secret() {
84        let kp = build_keypair().unwrap();
85        let debug_str = format!("{:?}", kp);
86        assert!(debug_str.contains(kp.public.expose()));
87        assert!(!debug_str.contains(kp.secret.expose_secret()));
88        assert!(debug_str.contains("[REDACTED]"));
89    }
90}