Skip to main content

sequoia_openpgp/crypto/
key.rs

1//! Common secret key related operations.
2
3use std::time::SystemTime;
4
5use crate::{
6    Result,
7    crypto::{
8        PublicKeyAlgorithm,
9        backend::{Backend, interface::Asymmetric},
10        mpi,
11    },
12    packet::key::{self, Key4, Key6, SecretParts},
13    types::Curve,
14};
15
16impl<R> Key6<SecretParts, R>
17    where R: key::KeyRole,
18{
19    /// Generates a new X25519 key.
20    pub fn generate_x25519() -> Result<Self> {
21        Key4::generate_x25519().map(Key6::from_common)
22    }
23
24    /// Generates a new X448 key.
25    pub fn generate_x448() -> Result<Self> {
26        Key4::generate_x448().map(Key6::from_common)
27    }
28
29    /// Generates a new Ed25519 key.
30    pub fn generate_ed25519() -> Result<Self> {
31        Key4::generate_ed25519().map(Key6::from_common)
32    }
33
34    /// Generates a new Ed448 key.
35    pub fn generate_ed448() -> Result<Self> {
36        Key4::generate_ed448().map(Key6::from_common)
37    }
38
39    /// Generates a new MLDSA65+Ed25519 key.
40    pub fn generate_mldsa65_ed25519() -> Result<Self> {
41        let (eddsa_secret, eddsa_public) = Backend::ed25519_generate_key()?;
42        let (mldsa_secret, mldsa_public) = Backend::mldsa65_generate_key()?;
43
44        Self::with_secret(
45            crate::now(),
46            PublicKeyAlgorithm::MLDSA65_Ed25519,
47            mpi::PublicKey::MLDSA65_Ed25519 {
48                eddsa: Box::new(eddsa_public),
49                mldsa: mldsa_public,
50            },
51            mpi::SecretKeyMaterial::MLDSA65_Ed25519 {
52                eddsa: eddsa_secret,
53                mldsa: mldsa_secret,
54            }.into())
55    }
56
57    /// Generates a new MLDSA87+Ed448 key.
58    pub fn generate_mldsa87_ed448() -> Result<Self> {
59        let (eddsa_secret, eddsa_public) = Backend::ed448_generate_key()?;
60        let (mldsa_secret, mldsa_public) = Backend::mldsa87_generate_key()?;
61
62        Self::with_secret(
63            crate::now(),
64            PublicKeyAlgorithm::MLDSA87_Ed448,
65            mpi::PublicKey::MLDSA87_Ed448 {
66                eddsa: Box::new(eddsa_public),
67                mldsa: mldsa_public,
68            },
69            mpi::SecretKeyMaterial::MLDSA87_Ed448 {
70                eddsa: eddsa_secret,
71                mldsa: mldsa_secret,
72            }.into())
73    }
74
75    /// Generates a new SLH-DSA-SHAKE-128s key.
76    ///
77    /// Note: [RFC 9980 only specifies the SHAKE variant of the
78    /// SLH-DSA
79    /// algorithm](https://www.rfc-editor.org/rfc/rfc9980.html#name-supported-public-key-algori).
80    pub fn generate_slhdsa128s() -> Result<Self> {
81        let (secret, public) = Backend::slhdsa128s_generate_key()?;
82
83        Self::with_secret(
84            crate::now(),
85            PublicKeyAlgorithm::SLHDSA128s,
86            mpi::PublicKey::SLHDSA128s { public },
87            mpi::SecretKeyMaterial::SLHDSA128s { secret }.into())
88    }
89
90    /// Generates a new SLH-DSA-SHAKE-128f key.
91    ///
92    /// Note: [RFC 9980 only specifies the SHAKE variant of the
93    /// SLH-DSA
94    /// algorithm](https://www.rfc-editor.org/rfc/rfc9980.html#name-supported-public-key-algori).
95    pub fn generate_slhdsa128f() -> Result<Self> {
96        let (secret, public) = Backend::slhdsa128f_generate_key()?;
97
98        Self::with_secret(
99            crate::now(),
100            PublicKeyAlgorithm::SLHDSA128f,
101            mpi::PublicKey::SLHDSA128f { public },
102            mpi::SecretKeyMaterial::SLHDSA128f { secret }.into())
103    }
104
105    /// Generates a new SLH-DSA-SHAKE-256s key.
106    ///
107    /// Note: [RFC 9980 only specifies the SHAKE variant of the
108    /// SLH-DSA
109    /// algorithm](https://www.rfc-editor.org/rfc/rfc9980.html#name-supported-public-key-algori).
110    pub fn generate_slhdsa256s() -> Result<Self> {
111        let (secret, public) = Backend::slhdsa256s_generate_key()?;
112
113        Self::with_secret(
114            crate::now(),
115            PublicKeyAlgorithm::SLHDSA256s,
116            mpi::PublicKey::SLHDSA256s { public },
117            mpi::SecretKeyMaterial::SLHDSA256s { secret }.into())
118    }
119
120    /// Generates a new MLKEM768+X25519 key.
121    pub fn generate_mlkem768_x25519() -> Result<Self> {
122        Key4::generate_mlkem768_x25519()
123            .map(Key6::from_common)
124    }
125
126    /// Generates a new MLKEM1024+X448 key.
127    pub fn generate_mlkem1024_x448() -> Result<Self> {
128        let (ecdh_secret, ecdh_public) = Backend::x448_generate_key()?;
129        let (mlkem_secret, mlkem_public) = Backend::mlkem1024_generate_key()?;
130
131        Self::with_secret(
132            crate::now(),
133            PublicKeyAlgorithm::MLKEM1024_X448,
134            mpi::PublicKey::MLKEM1024_X448 {
135                ecdh: Box::new(ecdh_public),
136                mlkem: mlkem_public,
137            },
138            mpi::SecretKeyMaterial::MLKEM1024_X448 {
139                ecdh: ecdh_secret,
140                mlkem: mlkem_secret,
141            }.into())
142    }
143
144    /// Generates a new RSA key with a public modulos of size `bits`.
145    pub fn generate_rsa(bits: usize) -> Result<Self> {
146        Key4::generate_rsa(bits)
147            .map(Key6::from_common)
148    }
149
150    /// Creates a new OpenPGP public key packet for an existing RSA key.
151    ///
152    /// The RSA key will use public exponent `e` and modulo `n`. The key will
153    /// have its creation date set to `ctime` or the current time if `None`
154    /// is given.
155    #[allow(clippy::many_single_char_names)]
156    pub fn import_secret_rsa<T>(d: &[u8], p: &[u8], q: &[u8], ctime: T)
157        -> Result<Self> where T: Into<Option<SystemTime>>
158    {
159        Key4::import_secret_rsa(d, p, q, ctime)
160            .map(Key6::from_common)
161    }
162
163    /// Generates a new ECC key over `curve`.
164    ///
165    /// If `for_signing` is false a ECDH key, if it's true either a
166    /// EdDSA or ECDSA key is generated.  Giving `for_signing == true` and
167    /// `curve == Cv25519` will produce an error. Likewise
168    /// `for_signing == false` and `curve == Ed25519` will produce an error.
169    pub fn generate_ecc(for_signing: bool, curve: Curve) -> Result<Self> {
170        match (for_signing, curve) {
171            (true, Curve::Ed25519) => Self::generate_ed25519(),
172            (false, Curve::Cv25519) => Self::generate_x25519(),
173            (s, c) => Key4::generate_ecc(s, c).map(Key6::from_common),
174        }
175    }
176}