signstar_crypto/key/import/
mod.rs

1//! Functionality for importing of cryptographic key material.
2
3#[cfg(feature = "nethsm")]
4pub mod nethsm;
5
6use std::fmt::Debug;
7
8use rsa::{
9    RsaPrivateKey,
10    pkcs8::DecodePrivateKey,
11    traits::PrivateKeyParts,
12    traits::PublicKeyParts,
13};
14
15#[cfg(doc)]
16use crate::key::MIN_RSA_BIT_LENGTH;
17use crate::key::{Error, KeyType, key_type_matches_length};
18
19/// The data for private key import
20// Allow dead code here, as the variants of `PrivateKeyData` are only used with a backend, which
21// requires enabling a feature.
22pub enum PrivateKeyData {
23    /// Data for [`KeyType::Curve25519`]
24    Curve25519(Vec<u8>),
25    /// Data for [`KeyType::EcP256`]
26    EcP256(Vec<u8>),
27    /// Data for [`KeyType::EcP384`]
28    EcP384(Vec<u8>),
29    /// Data for [`KeyType::EcP521`]
30    EcP521(Vec<u8>),
31    /// Data for [`KeyType::Rsa`]
32    Rsa {
33        /// The prime number `p`.
34        prime_p: Vec<u8>,
35        /// The prime number `q`.
36        prime_q: Vec<u8>,
37        /// The public exponent `e`.
38        public_exponent: Vec<u8>,
39    },
40}
41
42impl Debug for PrivateKeyData {
43    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44        const REDACTED: &&str = &"[REDACTED]";
45        match self {
46            Self::Curve25519(_) => f.debug_tuple("Curve25519").field(REDACTED).finish(),
47            Self::EcP256(_) => f.debug_tuple("EcP256").field(REDACTED).finish(),
48            Self::EcP384(_) => f.debug_tuple("EcP384").field(REDACTED).finish(),
49            Self::EcP521(_) => f.debug_tuple("EcP521").field(REDACTED).finish(),
50            Self::Rsa {
51                public_exponent, ..
52            } => f
53                .debug_struct("Rsa")
54                .field("prime_p", REDACTED)
55                .field("prime_q", REDACTED)
56                .field("public_exponent", public_exponent)
57                .finish(),
58        }
59    }
60}
61
62/// The key data required when importing a secret key
63#[derive(Debug)]
64pub struct PrivateKeyImport {
65    key_data: PrivateKeyData,
66}
67
68/// Creates a new vector with bytes in `buf`, left-padded with zeros so
69/// that the result is exactly `len` big.
70///
71/// # Errors
72///
73/// Returns an an error, if the input buffer `buf` is longer than the targeted `len`.
74///
75/// # Examples
76///
77/// ```no_compile
78/// let input = vec![1, 2, 3];
79/// let output = pad(&input, 4)?;
80/// assert_eq!(output, vec![0, 1, 2, 3]);
81/// ```
82fn pad(buf: &[u8], len: usize) -> Result<Vec<u8>, Error> {
83    let buffer_len = buf.len();
84    if len < buf.len() {
85        return Err(Error::PaddingInputTooLong {
86            buffer_len,
87            pad_len: len,
88        });
89    }
90    let mut v = vec![0; len];
91    v[len - buf.len()..].copy_from_slice(buf);
92    Ok(v)
93}
94
95impl PrivateKeyImport {
96    /// Creates a new [`PrivateKeyImport`]
97    ///
98    /// Accepts a [`KeyType`] (all except [`KeyType::Generic`]) and a bytes array representing a
99    /// matching PKCS#8 private key in ASN.1 DER-encoded format.
100    ///
101    /// # Errors
102    ///
103    /// Returns an error if
104    ///
105    /// - `key_data` can not be deserialized to a respective private key format.
106    /// - an RSA private key does not have prime P or prime Q.
107    /// - an RSA private key is shorter than [`MIN_RSA_BIT_LENGTH`].
108    /// - `key_type` is the unsupported [`KeyType::Generic`].
109    ///
110    /// # Examples
111    ///
112    /// ```
113    /// # use testresult::TestResult;
114    /// use ed25519_dalek::{SigningKey, pkcs8::EncodePrivateKey};
115    /// use rand::rngs::OsRng;
116    /// use signstar_crypto::key::{KeyType, PrivateKeyImport};
117    /// # fn main() -> TestResult {
118    ///
119    /// let key_data = {
120    ///     let mut csprng = OsRng;
121    ///     let signing_key: SigningKey = SigningKey::generate(&mut csprng);
122    ///     signing_key.to_pkcs8_der()?.as_bytes().to_vec()
123    /// };
124    ///
125    /// assert!(PrivateKeyImport::new(KeyType::Curve25519, &key_data).is_ok());
126    /// # Ok(())
127    /// # }
128    /// ```
129    pub fn new(key_type: KeyType, key_data: &[u8]) -> Result<Self, Error> {
130        Ok(match key_type {
131            KeyType::Curve25519 => {
132                let key_pair = ed25519_dalek::pkcs8::KeypairBytes::from_pkcs8_der(key_data)?;
133                Self {
134                    key_data: PrivateKeyData::Curve25519(key_pair.secret_key.to_vec()),
135                }
136            }
137            KeyType::EcP256 => {
138                let private_key = p256::SecretKey::from_pkcs8_der(key_data)?;
139                Self {
140                    key_data: PrivateKeyData::EcP256(private_key.to_bytes().as_slice().to_owned()),
141                }
142            }
143            KeyType::EcP384 => {
144                let private_key = p384::SecretKey::from_pkcs8_der(key_data)?;
145                Self {
146                    key_data: PrivateKeyData::EcP384(private_key.to_bytes().as_slice().to_owned()),
147                }
148            }
149            KeyType::EcP521 => {
150                let private_key = p521::SecretKey::from_pkcs8_der(key_data)?;
151                Self {
152                    key_data: PrivateKeyData::EcP521(private_key.to_bytes().as_slice().to_owned()),
153                }
154            }
155            KeyType::Generic => return Err(Error::UnsupportedKeyType(KeyType::Generic)),
156            KeyType::Rsa => {
157                let private_key = RsaPrivateKey::from_pkcs8_der(key_data)?;
158                // ensure, that we have sufficient bit length
159                key_type_matches_length(key_type, Some(private_key.size() as u32 * 8))?;
160                Self {
161                    key_data: PrivateKeyData::Rsa {
162                        prime_p: private_key
163                            .primes()
164                            .first()
165                            .ok_or(Error::NoPrimes)?
166                            .to_bytes_be(),
167                        prime_q: private_key
168                            .primes()
169                            .get(1)
170                            .ok_or(Error::NoPrimes)?
171                            .to_bytes_be(),
172                        public_exponent: private_key.e().to_bytes_be(),
173                    },
174                }
175            }
176        })
177    }
178
179    /// Creates a new [`PrivateKeyImport`]
180    ///
181    /// Accepts a [`KeyType`] (all except [`KeyType::Generic`]) and a string slice representing a
182    /// matching PKCS#8 private key in PEM-encoded format.
183    ///
184    /// # Errors
185    ///
186    /// Returns an error if
187    ///
188    /// - `key_data` can not be deserialized to a respective private key format.
189    /// - an RSA private key does not have prime P or prime Q.
190    /// - an RSA private key is shorter than [`MIN_RSA_BIT_LENGTH`].
191    /// - `key_type` is the unsupported [`KeyType::Generic`].
192    ///
193    /// # Examples
194    ///
195    /// ```
196    /// # use testresult::TestResult;
197    /// use std::ops::Deref;
198    ///
199    /// use ed25519_dalek::{SigningKey, pkcs8::EncodePrivateKey, pkcs8::spki::der::pem::LineEnding};
200    /// use rand::rngs::OsRng;
201    /// use signstar_crypto::key::{KeyType, PrivateKeyImport};
202    /// # fn main() -> TestResult {
203    ///
204    /// let key_data = {
205    ///     let mut csprng = OsRng;
206    ///     let signing_key: SigningKey = SigningKey::generate(&mut csprng);
207    ///     signing_key.to_pkcs8_pem(LineEnding::default())?
208    /// };
209    ///
210    /// assert!(PrivateKeyImport::from_pkcs8_pem(KeyType::Curve25519, key_data.deref()).is_ok());
211    /// # Ok(())
212    /// # }
213    /// ```
214    pub fn from_pkcs8_pem(key_type: KeyType, key_data: &str) -> Result<Self, Error> {
215        Ok(match key_type {
216            KeyType::Curve25519 => {
217                let key_pair = ed25519_dalek::pkcs8::KeypairBytes::from_pkcs8_pem(key_data)?;
218                Self {
219                    key_data: PrivateKeyData::Curve25519(key_pair.secret_key.to_vec()),
220                }
221            }
222            KeyType::EcP256 => {
223                let private_key = p256::SecretKey::from_pkcs8_pem(key_data)?;
224                Self {
225                    key_data: PrivateKeyData::EcP256(private_key.to_bytes().as_slice().to_owned()),
226                }
227            }
228            KeyType::EcP384 => {
229                let private_key = p384::SecretKey::from_pkcs8_pem(key_data)?;
230                Self {
231                    key_data: PrivateKeyData::EcP384(private_key.to_bytes().as_slice().to_owned()),
232                }
233            }
234            KeyType::EcP521 => {
235                let private_key = p521::SecretKey::from_pkcs8_pem(key_data)?;
236                Self {
237                    key_data: PrivateKeyData::EcP521(private_key.to_bytes().as_slice().to_owned()),
238                }
239            }
240            KeyType::Generic => return Err(Error::UnsupportedKeyType(KeyType::Generic)),
241            KeyType::Rsa => {
242                let private_key = RsaPrivateKey::from_pkcs8_pem(key_data)?;
243                // ensure, that we have sufficient bit length
244                key_type_matches_length(key_type, Some(private_key.size() as u32 * 8))?;
245                Self {
246                    key_data: PrivateKeyData::Rsa {
247                        prime_p: private_key
248                            .primes()
249                            .first()
250                            .ok_or(Error::NoPrimes)?
251                            .to_bytes_be(),
252                        prime_q: private_key
253                            .primes()
254                            .get(1)
255                            .ok_or(Error::NoPrimes)?
256                            .to_bytes_be(),
257                        public_exponent: private_key.e().to_bytes_be(),
258                    },
259                }
260            }
261        })
262    }
263
264    /// Create [`PrivateKeyImport`] object from raw, private RSA key parts.
265    ///
266    /// The function takes two primes (*p* and *q*) and the public exponent,
267    /// which usually is 65537 (`[0x01, 0x00, 0x01]`).
268    ///
269    /// # Examples
270    ///
271    /// ```rust
272    /// use signstar_crypto::key::PrivateKeyImport;
273    ///
274    /// # fn main() -> testresult::TestResult {
275    /// let prime_p = vec![7];
276    /// let prime_q = vec![11];
277    /// let public_exponent = vec![1, 0, 1];
278    ///
279    /// let _import = PrivateKeyImport::from_rsa(prime_p, prime_q, public_exponent);
280    /// # Ok(()) }
281    /// ```
282    pub fn from_rsa(prime_p: Vec<u8>, prime_q: Vec<u8>, public_exponent: Vec<u8>) -> Self {
283        Self {
284            key_data: PrivateKeyData::Rsa {
285                prime_p,
286                prime_q,
287                public_exponent,
288            },
289        }
290    }
291
292    /// Create [`PrivateKeyImport`] object from raw, private Elliptic Curve bytes.
293    ///
294    /// The function takes two parameters:
295    /// - the type of elliptic curve,
296    /// - raw bytes in a curve-specific encoding
297    ///
298    /// Elliptic curve keys require the `bytes` to be zero-padded to be of correct size.
299    /// This function automatically applies padding accordingly.
300    ///
301    /// # Examples
302    ///
303    /// ```rust
304    /// use signstar_crypto::key::{KeyType, PrivateKeyImport};
305    ///
306    /// # fn main() -> testresult::TestResult {
307    /// let bytes = vec![0x00; 32];
308    ///
309    /// let _import = PrivateKeyImport::from_raw_bytes(KeyType::Curve25519, bytes)?;
310    /// # Ok(()) }
311    /// ```
312    pub fn from_raw_bytes(ec: KeyType, bytes: impl AsRef<[u8]>) -> Result<Self, Error> {
313        let bytes = bytes.as_ref();
314        Ok(Self {
315            key_data: match ec {
316                KeyType::EcP256 => PrivateKeyData::EcP256(pad(bytes, 32)?),
317                KeyType::EcP384 => PrivateKeyData::EcP384(pad(bytes, 48)?),
318                KeyType::EcP521 => PrivateKeyData::EcP521(pad(bytes, 66)?),
319                KeyType::Curve25519 => PrivateKeyData::Curve25519(pad(bytes, 32)?),
320                key_type => return Err(Error::UnsupportedKeyType(key_type)),
321            },
322        })
323    }
324
325    /// Get the matching [`KeyType`] for the data contained in the [`PrivateKeyImport`]
326    pub fn key_type(&self) -> KeyType {
327        match &self.key_data {
328            PrivateKeyData::Curve25519(_) => KeyType::Curve25519,
329            PrivateKeyData::EcP256(_) => KeyType::EcP256,
330            PrivateKeyData::EcP384(_) => KeyType::EcP384,
331            PrivateKeyData::EcP521(_) => KeyType::EcP521,
332            PrivateKeyData::Rsa {
333                prime_p: _,
334                prime_q: _,
335                public_exponent: _,
336            } => KeyType::Rsa,
337        }
338    }
339}
340
341#[cfg(test)]
342mod tests {
343    use rsa::RsaPrivateKey;
344    use rsa::pkcs8::EncodePrivateKey;
345    use rstest::{fixture, rstest};
346    use testresult::TestResult;
347
348    use super::*;
349
350    #[fixture]
351    fn ed25519_private_key() -> TestResult<Vec<u8>> {
352        use ed25519_dalek::SigningKey;
353        use rand::rngs::OsRng;
354        let mut csprng = OsRng;
355        let signing_key: SigningKey = SigningKey::generate(&mut csprng);
356        Ok(signing_key.to_pkcs8_der()?.as_bytes().to_vec())
357    }
358
359    #[fixture]
360    fn p256_private_key() -> TestResult<Vec<u8>> {
361        use p256::elliptic_curve::rand_core::OsRng;
362        let private_key = p256::SecretKey::random(&mut OsRng);
363        Ok(private_key.to_pkcs8_der()?.as_bytes().to_vec())
364    }
365
366    #[fixture]
367    fn p384_private_key() -> TestResult<Vec<u8>> {
368        use p384::elliptic_curve::rand_core::OsRng;
369        let private_key = p384::SecretKey::random(&mut OsRng);
370        Ok(private_key.to_pkcs8_der()?.as_bytes().to_vec())
371    }
372
373    #[fixture]
374    fn p521_private_key() -> TestResult<Vec<u8>> {
375        use p521::elliptic_curve::rand_core::OsRng;
376        let private_key = p521::SecretKey::random(&mut OsRng);
377        Ok(private_key.to_pkcs8_der()?.as_bytes().to_vec())
378    }
379
380    #[fixture]
381    fn rsa_private_key() -> TestResult<Vec<u8>> {
382        let mut rng = rand::thread_rng();
383        let private_key = RsaPrivateKey::new(&mut rng, 2048.try_into()?)?;
384        Ok(private_key.to_pkcs8_der()?.as_bytes().to_vec())
385    }
386
387    #[rstest]
388    fn key_data(
389        ed25519_private_key: TestResult<Vec<u8>>,
390        p256_private_key: TestResult<Vec<u8>>,
391        p384_private_key: TestResult<Vec<u8>>,
392        p521_private_key: TestResult<Vec<u8>>,
393        rsa_private_key: TestResult<Vec<u8>>,
394    ) -> TestResult {
395        let ed25519_private_key = ed25519_private_key?;
396        let p256_private_key = p256_private_key?;
397        let p384_private_key = p384_private_key?;
398        let p521_private_key = p521_private_key?;
399        let rsa_private_key = rsa_private_key?;
400
401        assert!(PrivateKeyImport::new(KeyType::Curve25519, &ed25519_private_key).is_ok());
402        assert!(PrivateKeyImport::new(KeyType::Curve25519, &p256_private_key).is_err());
403        assert!(PrivateKeyImport::new(KeyType::Curve25519, &p384_private_key).is_err());
404        assert!(PrivateKeyImport::new(KeyType::Curve25519, &p521_private_key).is_err());
405        assert!(PrivateKeyImport::new(KeyType::Curve25519, &rsa_private_key).is_err());
406
407        assert!(PrivateKeyImport::new(KeyType::EcP256, &ed25519_private_key).is_err());
408        assert!(PrivateKeyImport::new(KeyType::EcP256, &p256_private_key).is_ok());
409        assert!(PrivateKeyImport::new(KeyType::EcP256, &p384_private_key).is_err());
410        assert!(PrivateKeyImport::new(KeyType::EcP256, &p521_private_key).is_err());
411        assert!(PrivateKeyImport::new(KeyType::EcP256, &rsa_private_key).is_err());
412
413        assert!(PrivateKeyImport::new(KeyType::EcP384, &ed25519_private_key).is_err());
414        assert!(PrivateKeyImport::new(KeyType::EcP384, &p256_private_key).is_err());
415        assert!(PrivateKeyImport::new(KeyType::EcP384, &p384_private_key).is_ok());
416        assert!(PrivateKeyImport::new(KeyType::EcP384, &p521_private_key).is_err());
417        assert!(PrivateKeyImport::new(KeyType::EcP384, &rsa_private_key).is_err());
418
419        assert!(PrivateKeyImport::new(KeyType::EcP521, &ed25519_private_key).is_err());
420        assert!(PrivateKeyImport::new(KeyType::EcP521, &p256_private_key).is_err());
421        assert!(PrivateKeyImport::new(KeyType::EcP521, &p384_private_key).is_err());
422        assert!(PrivateKeyImport::new(KeyType::EcP521, &p521_private_key).is_ok());
423        assert!(PrivateKeyImport::new(KeyType::EcP521, &rsa_private_key).is_err());
424
425        assert!(PrivateKeyImport::new(KeyType::Rsa, &ed25519_private_key).is_err());
426        assert!(PrivateKeyImport::new(KeyType::Rsa, &p256_private_key).is_err());
427        assert!(PrivateKeyImport::new(KeyType::Rsa, &p384_private_key).is_err());
428        assert!(PrivateKeyImport::new(KeyType::Rsa, &p521_private_key).is_err());
429        assert!(PrivateKeyImport::new(KeyType::Rsa, &rsa_private_key).is_ok());
430
431        assert!(PrivateKeyImport::new(KeyType::Generic, &ed25519_private_key).is_err());
432        assert!(PrivateKeyImport::new(KeyType::Generic, &p256_private_key).is_err());
433        assert!(PrivateKeyImport::new(KeyType::Generic, &p384_private_key).is_err());
434        assert!(PrivateKeyImport::new(KeyType::Generic, &p521_private_key).is_err());
435        assert!(PrivateKeyImport::new(KeyType::Generic, &rsa_private_key).is_err());
436        Ok(())
437    }
438}