mas_keystore/
lib.rs

1// Copyright 2024 New Vector Ltd.
2// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
3//
4// SPDX-License-Identifier: AGPL-3.0-only
5// Please see LICENSE in the repository root for full details.
6
7//! A crate to store keys which can then be used to sign and verify JWTs.
8
9use std::{ops::Deref, sync::Arc};
10
11use der::{Decode, Encode, EncodePem, zeroize::Zeroizing};
12use elliptic_curve::{pkcs8::EncodePrivateKey, sec1::ToEncodedPoint};
13use mas_iana::jose::{JsonWebKeyType, JsonWebSignatureAlg};
14pub use mas_jose::jwk::{JsonWebKey, JsonWebKeySet};
15use mas_jose::{
16    jwa::{AsymmetricSigningKey, AsymmetricVerifyingKey},
17    jwk::{JsonWebKeyPublicParameters, ParametersInfo, PublicJsonWebKeySet},
18};
19use pem_rfc7468::PemLabel;
20use pkcs1::EncodeRsaPrivateKey;
21use pkcs8::{AssociatedOid, PrivateKeyInfo};
22use rand::{CryptoRng, RngCore};
23use rsa::BigUint;
24use thiserror::Error;
25
26mod encrypter;
27
28pub use aead;
29
30pub use self::encrypter::{DecryptError, Encrypter};
31
32/// Error type used when a key could not be loaded
33#[derive(Debug, Error)]
34pub enum LoadError {
35    #[error("Failed to read PEM document")]
36    Pem {
37        #[from]
38        inner: pem_rfc7468::Error,
39    },
40
41    #[error("Invalid RSA private key")]
42    Rsa {
43        #[from]
44        inner: rsa::errors::Error,
45    },
46
47    #[error("Failed to decode PKCS1-encoded RSA key")]
48    Pkcs1 {
49        #[from]
50        inner: pkcs1::Error,
51    },
52
53    #[error("Failed to decode PKCS8-encoded key")]
54    Pkcs8 {
55        #[from]
56        inner: pkcs8::Error,
57    },
58
59    #[error(transparent)]
60    Der {
61        #[from]
62        inner: der::Error,
63    },
64
65    #[error(transparent)]
66    Spki {
67        #[from]
68        inner: spki::Error,
69    },
70
71    #[error("Unknown Elliptic Curve OID {oid}")]
72    UnknownEllipticCurveOid { oid: const_oid::ObjectIdentifier },
73
74    #[error("Unknown algorithm OID {oid}")]
75    UnknownAlgorithmOid { oid: const_oid::ObjectIdentifier },
76
77    #[error("Unsupported PEM label {label:?}")]
78    UnsupportedPemLabel { label: String },
79
80    #[error("Missing parameters in SEC1 key")]
81    MissingSec1Parameters,
82
83    #[error("Missing curve name in SEC1 parameters")]
84    MissingSec1CurveName,
85
86    #[error("Key is encrypted and no password was provided")]
87    Encrypted,
88
89    #[error("Key is not encrypted but a password was provided")]
90    Unencrypted,
91
92    #[error("Unsupported format")]
93    UnsupportedFormat,
94
95    #[error("Could not decode encrypted payload")]
96    InEncrypted {
97        #[source]
98        inner: Box<LoadError>,
99    },
100}
101
102impl LoadError {
103    /// Returns `true` if the load error is [`Encrypted`].
104    ///
105    /// [`Encrypted`]: LoadError::Encrypted
106    #[must_use]
107    pub fn is_encrypted(&self) -> bool {
108        matches!(self, Self::Encrypted)
109    }
110
111    /// Returns `true` if the load error is [`Unencrypted`].
112    ///
113    /// [`Unencrypted`]: LoadError::Unencrypted
114    #[must_use]
115    pub fn is_unencrypted(&self) -> bool {
116        matches!(self, Self::Unencrypted)
117    }
118}
119
120/// A single private key
121#[non_exhaustive]
122#[derive(Debug)]
123pub enum PrivateKey {
124    Rsa(Box<rsa::RsaPrivateKey>),
125    EcP256(Box<elliptic_curve::SecretKey<p256::NistP256>>),
126    EcP384(Box<elliptic_curve::SecretKey<p384::NistP384>>),
127    EcK256(Box<elliptic_curve::SecretKey<k256::Secp256k1>>),
128}
129
130/// Error returned when the key can't be used for the requested algorithm
131#[derive(Debug, Error)]
132#[error("Wrong algorithm for key")]
133pub struct WrongAlgorithmError;
134
135impl PrivateKey {
136    fn from_pkcs1_private_key(pkcs1_key: &pkcs1::RsaPrivateKey) -> Result<Self, LoadError> {
137        // Taken from `TryFrom<pkcs8::PrivateKeyInfo<'_>> for RsaPrivateKey`
138
139        // Multi-prime RSA keys not currently supported
140        if pkcs1_key.version() != pkcs1::Version::TwoPrime {
141            return Err(pkcs1::Error::Version.into());
142        }
143
144        let n = BigUint::from_bytes_be(pkcs1_key.modulus.as_bytes());
145        let e = BigUint::from_bytes_be(pkcs1_key.public_exponent.as_bytes());
146        let d = BigUint::from_bytes_be(pkcs1_key.private_exponent.as_bytes());
147        let first_prime = BigUint::from_bytes_be(pkcs1_key.prime1.as_bytes());
148        let second_prime = BigUint::from_bytes_be(pkcs1_key.prime2.as_bytes());
149        let primes = vec![first_prime, second_prime];
150        let key = rsa::RsaPrivateKey::from_components(n, e, d, primes)?;
151        Ok(Self::Rsa(Box::new(key)))
152    }
153
154    fn from_private_key_info(info: PrivateKeyInfo) -> Result<Self, LoadError> {
155        match info.algorithm.oid {
156            pkcs1::ALGORITHM_OID => Ok(Self::Rsa(Box::new(info.try_into()?))),
157            elliptic_curve::ALGORITHM_OID => match info.algorithm.parameters_oid()? {
158                p256::NistP256::OID => Ok(Self::EcP256(Box::new(info.try_into()?))),
159                p384::NistP384::OID => Ok(Self::EcP384(Box::new(info.try_into()?))),
160                k256::Secp256k1::OID => Ok(Self::EcK256(Box::new(info.try_into()?))),
161                oid => Err(LoadError::UnknownEllipticCurveOid { oid }),
162            },
163            oid => Err(LoadError::UnknownAlgorithmOid { oid }),
164        }
165    }
166
167    fn from_ec_private_key(key: sec1::EcPrivateKey) -> Result<Self, LoadError> {
168        let curve = key
169            .parameters
170            .ok_or(LoadError::MissingSec1Parameters)?
171            .named_curve()
172            .ok_or(LoadError::MissingSec1CurveName)?;
173
174        match curve {
175            p256::NistP256::OID => Ok(Self::EcP256(Box::new(key.try_into()?))),
176            p384::NistP384::OID => Ok(Self::EcP384(Box::new(key.try_into()?))),
177            k256::Secp256k1::OID => Ok(Self::EcK256(Box::new(key.try_into()?))),
178            oid => Err(LoadError::UnknownEllipticCurveOid { oid }),
179        }
180    }
181
182    /// Serialize the key as a DER document
183    ///
184    /// It will use the most common format depending on the key type: PKCS1 for
185    /// RSA keys and SEC1 for elliptic curve keys
186    ///
187    /// # Errors
188    ///
189    /// Returns an error if the encoding failed
190    pub fn to_der(&self) -> Result<Zeroizing<Vec<u8>>, pkcs1::Error> {
191        let der = match self {
192            PrivateKey::Rsa(key) => key.to_pkcs1_der()?.to_bytes(),
193            PrivateKey::EcP256(key) => to_sec1_der(key)?,
194            PrivateKey::EcP384(key) => to_sec1_der(key)?,
195            PrivateKey::EcK256(key) => to_sec1_der(key)?,
196        };
197
198        Ok(der)
199    }
200
201    /// Serialize the key as a PKCS8 DER document
202    ///
203    /// # Errors
204    ///
205    /// Returns an error if the encoding failed
206    pub fn to_pkcs8_der(&self) -> Result<Zeroizing<Vec<u8>>, pkcs8::Error> {
207        let der = match self {
208            PrivateKey::Rsa(key) => key.to_pkcs8_der()?,
209            PrivateKey::EcP256(key) => key.to_pkcs8_der()?,
210            PrivateKey::EcP384(key) => key.to_pkcs8_der()?,
211            PrivateKey::EcK256(key) => key.to_pkcs8_der()?,
212        };
213
214        Ok(der.to_bytes())
215    }
216
217    /// Serialize the key as a PEM document
218    ///
219    /// It will use the most common format depending on the key type: PKCS1 for
220    /// RSA keys and SEC1 for elliptic curve keys
221    ///
222    /// # Errors
223    ///
224    /// Returns an error if the encoding failed
225    pub fn to_pem(
226        &self,
227        line_ending: pem_rfc7468::LineEnding,
228    ) -> Result<Zeroizing<String>, pkcs1::Error> {
229        let pem = match self {
230            PrivateKey::Rsa(key) => key.to_pkcs1_pem(line_ending)?,
231            PrivateKey::EcP256(key) => to_sec1_pem(key, line_ending)?,
232            PrivateKey::EcP384(key) => to_sec1_pem(key, line_ending)?,
233            PrivateKey::EcK256(key) => to_sec1_pem(key, line_ending)?,
234        };
235
236        Ok(pem)
237    }
238
239    /// Load an unencrypted PEM or DER encoded key
240    ///
241    /// # Errors
242    ///
243    /// Returns the same kind of errors as [`Self::load_pem`] and
244    /// [`Self::load_der`].
245    pub fn load(bytes: &[u8]) -> Result<Self, LoadError> {
246        if let Ok(pem) = std::str::from_utf8(bytes) {
247            match Self::load_pem(pem) {
248                Ok(s) => return Ok(s),
249                // If there was an error loading the document as PEM, ignore it and continue by
250                // trying to load it as DER
251                Err(LoadError::Pem { .. }) => {}
252                Err(e) => return Err(e),
253            }
254        }
255
256        Self::load_der(bytes)
257    }
258
259    /// Load an encrypted PEM or DER encoded key, and decrypt it with the given
260    /// password
261    ///
262    /// # Errors
263    ///
264    /// Returns the same kind of errors as [`Self::load_encrypted_pem`] and
265    /// [`Self::load_encrypted_der`].
266    pub fn load_encrypted(bytes: &[u8], password: impl AsRef<[u8]>) -> Result<Self, LoadError> {
267        if let Ok(pem) = std::str::from_utf8(bytes) {
268            match Self::load_encrypted_pem(pem, password.as_ref()) {
269                Ok(s) => return Ok(s),
270                // If there was an error loading the document as PEM, ignore it and continue by
271                // trying to load it as DER
272                Err(LoadError::Pem { .. }) => {}
273                Err(e) => return Err(e),
274            }
275        }
276
277        Self::load_encrypted_der(bytes, password)
278    }
279
280    /// Load an encrypted key from DER-encoded bytes, and decrypt it with the
281    /// given password
282    ///
283    /// # Errors
284    ///
285    /// Returns an error if:
286    ///   - the key is in an non-encrypted format
287    ///   - the key could not be decrypted
288    ///   - the PKCS8 key could not be loaded
289    pub fn load_encrypted_der(der: &[u8], password: impl AsRef<[u8]>) -> Result<Self, LoadError> {
290        if let Ok(info) = pkcs8::EncryptedPrivateKeyInfo::from_der(der) {
291            let decrypted = info.decrypt(password)?;
292            return Self::load_der(decrypted.as_bytes()).map_err(|inner| LoadError::InEncrypted {
293                inner: Box::new(inner),
294            });
295        }
296
297        if pkcs8::PrivateKeyInfo::from_der(der).is_ok()
298            || sec1::EcPrivateKey::from_der(der).is_ok()
299            || pkcs1::RsaPrivateKey::from_der(der).is_ok()
300        {
301            return Err(LoadError::Unencrypted);
302        }
303
304        Err(LoadError::UnsupportedFormat)
305    }
306
307    /// Load an unencrypted key from DER-encoded bytes
308    ///
309    /// It tries to decode the bytes from the various known DER formats (PKCS8,
310    /// SEC1 and PKCS1, in that order), and return the first one that works.
311    ///
312    /// # Errors
313    ///
314    /// Returns an error if:
315    ///   - the PKCS8 key is encrypted
316    ///   - none of the formats could be decoded
317    ///   - the PKCS8/SEC1/PKCS1 key could not be loaded
318    pub fn load_der(der: &[u8]) -> Result<Self, LoadError> {
319        // Let's try evey known DER format one after the other
320        if pkcs8::EncryptedPrivateKeyInfo::from_der(der).is_ok() {
321            return Err(LoadError::Encrypted);
322        }
323
324        if let Ok(info) = pkcs8::PrivateKeyInfo::from_der(der) {
325            return Self::from_private_key_info(info);
326        }
327
328        if let Ok(info) = sec1::EcPrivateKey::from_der(der) {
329            return Self::from_ec_private_key(info);
330        }
331
332        if let Ok(pkcs1_key) = pkcs1::RsaPrivateKey::from_der(der) {
333            return Self::from_pkcs1_private_key(&pkcs1_key);
334        }
335
336        Err(LoadError::UnsupportedFormat)
337    }
338
339    /// Load an encrypted key from a PEM-encode string, and decrypt it with the
340    /// given password
341    ///
342    /// # Errors
343    ///
344    /// Returns an error if:
345    ///   - the file is not a signel PEM document
346    ///   - the PEM label is not a supported format
347    ///   - the underlying key is not encrypted (use [`Self::load`] instead)
348    ///   - the decryption failed
349    ///   - the pkcs8 key could not be loaded
350    pub fn load_encrypted_pem(pem: &str, password: impl AsRef<[u8]>) -> Result<Self, LoadError> {
351        let (label, doc) = pem_rfc7468::decode_vec(pem.as_bytes())?;
352
353        match label {
354            pkcs8::EncryptedPrivateKeyInfo::PEM_LABEL => {
355                let info = pkcs8::EncryptedPrivateKeyInfo::from_der(&doc)?;
356                let decrypted = info.decrypt(password)?;
357                Self::load_der(decrypted.as_bytes()).map_err(|inner| LoadError::InEncrypted {
358                    inner: Box::new(inner),
359                })
360            }
361
362            pkcs1::RsaPrivateKey::PEM_LABEL
363            | pkcs8::PrivateKeyInfo::PEM_LABEL
364            | sec1::EcPrivateKey::PEM_LABEL => Err(LoadError::Unencrypted),
365
366            label => Err(LoadError::UnsupportedPemLabel {
367                label: label.to_owned(),
368            }),
369        }
370    }
371
372    /// Load an unencrypted key from a PEM-encode string
373    ///
374    /// # Errors
375    ///
376    /// Returns an error if:
377    ///   - the file is not a signel PEM document
378    ///   - the PEM label is not a supported format
379    ///   - the underlying key is encrypted (use [`Self::load_encrypted`]
380    ///     instead)
381    ///   - the PKCS8/PKCS1/SEC1 key could not be loaded
382    pub fn load_pem(pem: &str) -> Result<Self, LoadError> {
383        let (label, doc) = pem_rfc7468::decode_vec(pem.as_bytes())?;
384
385        match label {
386            pkcs1::RsaPrivateKey::PEM_LABEL => {
387                let pkcs1_key = pkcs1::RsaPrivateKey::from_der(&doc)?;
388                Self::from_pkcs1_private_key(&pkcs1_key)
389            }
390
391            pkcs8::PrivateKeyInfo::PEM_LABEL => {
392                let info = pkcs8::PrivateKeyInfo::from_der(&doc)?;
393                Self::from_private_key_info(info)
394            }
395
396            sec1::EcPrivateKey::PEM_LABEL => {
397                let key = sec1::EcPrivateKey::from_der(&doc)?;
398                Self::from_ec_private_key(key)
399            }
400
401            pkcs8::EncryptedPrivateKeyInfo::PEM_LABEL => Err(LoadError::Encrypted),
402
403            label => Err(LoadError::UnsupportedPemLabel {
404                label: label.to_owned(),
405            }),
406        }
407    }
408
409    /// Get an [`AsymmetricVerifyingKey`] out of this key, for the specified
410    /// [`JsonWebSignatureAlg`]
411    ///
412    /// # Errors
413    ///
414    /// Returns an error if the key is not suited for the selected algorithm
415    pub fn verifying_key_for_alg(
416        &self,
417        alg: &JsonWebSignatureAlg,
418    ) -> Result<AsymmetricVerifyingKey, WrongAlgorithmError> {
419        let key = match (self, alg) {
420            (Self::Rsa(key), _) => {
421                let key: rsa::RsaPublicKey = key.to_public_key();
422                match alg {
423                    JsonWebSignatureAlg::Rs256 => AsymmetricVerifyingKey::rs256(key),
424                    JsonWebSignatureAlg::Rs384 => AsymmetricVerifyingKey::rs384(key),
425                    JsonWebSignatureAlg::Rs512 => AsymmetricVerifyingKey::rs512(key),
426                    JsonWebSignatureAlg::Ps256 => AsymmetricVerifyingKey::ps256(key),
427                    JsonWebSignatureAlg::Ps384 => AsymmetricVerifyingKey::ps384(key),
428                    JsonWebSignatureAlg::Ps512 => AsymmetricVerifyingKey::ps512(key),
429                    _ => return Err(WrongAlgorithmError),
430                }
431            }
432
433            (Self::EcP256(key), JsonWebSignatureAlg::Es256) => {
434                AsymmetricVerifyingKey::es256(key.public_key())
435            }
436
437            (Self::EcP384(key), JsonWebSignatureAlg::Es384) => {
438                AsymmetricVerifyingKey::es384(key.public_key())
439            }
440
441            (Self::EcK256(key), JsonWebSignatureAlg::Es256K) => {
442                AsymmetricVerifyingKey::es256k(key.public_key())
443            }
444
445            _ => return Err(WrongAlgorithmError),
446        };
447
448        Ok(key)
449    }
450
451    /// Get a [`AsymmetricSigningKey`] out of this key, for the specified
452    /// [`JsonWebSignatureAlg`]
453    ///
454    /// # Errors
455    ///
456    /// Returns an error if the key is not suited for the selected algorithm
457    pub fn signing_key_for_alg(
458        &self,
459        alg: &JsonWebSignatureAlg,
460    ) -> Result<AsymmetricSigningKey, WrongAlgorithmError> {
461        let key = match (self, alg) {
462            (Self::Rsa(key), _) => {
463                let key: rsa::RsaPrivateKey = *key.clone();
464                match alg {
465                    JsonWebSignatureAlg::Rs256 => AsymmetricSigningKey::rs256(key),
466                    JsonWebSignatureAlg::Rs384 => AsymmetricSigningKey::rs384(key),
467                    JsonWebSignatureAlg::Rs512 => AsymmetricSigningKey::rs512(key),
468                    JsonWebSignatureAlg::Ps256 => AsymmetricSigningKey::ps256(key),
469                    JsonWebSignatureAlg::Ps384 => AsymmetricSigningKey::ps384(key),
470                    JsonWebSignatureAlg::Ps512 => AsymmetricSigningKey::ps512(key),
471                    _ => return Err(WrongAlgorithmError),
472                }
473            }
474
475            (Self::EcP256(key), JsonWebSignatureAlg::Es256) => {
476                AsymmetricSigningKey::es256(*key.clone())
477            }
478
479            (Self::EcP384(key), JsonWebSignatureAlg::Es384) => {
480                AsymmetricSigningKey::es384(*key.clone())
481            }
482
483            (Self::EcK256(key), JsonWebSignatureAlg::Es256K) => {
484                AsymmetricSigningKey::es256k(*key.clone())
485            }
486
487            _ => return Err(WrongAlgorithmError),
488        };
489
490        Ok(key)
491    }
492
493    /// Generate a RSA key with 2048 bit size
494    ///
495    /// # Errors
496    ///
497    /// Returns any error from the underlying key generator
498    pub fn generate_rsa<R: RngCore + CryptoRng>(mut rng: R) -> Result<Self, rsa::errors::Error> {
499        let key = rsa::RsaPrivateKey::new(&mut rng, 2048)?;
500        Ok(Self::Rsa(Box::new(key)))
501    }
502
503    /// Generate an Elliptic Curve key for the P-256 curve
504    pub fn generate_ec_p256<R: RngCore + CryptoRng>(mut rng: R) -> Self {
505        let key = elliptic_curve::SecretKey::random(&mut rng);
506        Self::EcP256(Box::new(key))
507    }
508
509    /// Generate an Elliptic Curve key for the P-384 curve
510    pub fn generate_ec_p384<R: RngCore + CryptoRng>(mut rng: R) -> Self {
511        let key = elliptic_curve::SecretKey::random(&mut rng);
512        Self::EcP384(Box::new(key))
513    }
514
515    /// Generate an Elliptic Curve key for the secp256k1 curve
516    pub fn generate_ec_k256<R: RngCore + CryptoRng>(mut rng: R) -> Self {
517        let key = elliptic_curve::SecretKey::random(&mut rng);
518        Self::EcK256(Box::new(key))
519    }
520}
521
522// The default implementation of SecretKey::to_sec1_pem/der do not include the
523// named curve OID. This is a basic reimplementation of those two functions with
524// the OID included, so that it matches the implementation in OpenSSL.
525fn to_sec1_der<C>(key: &elliptic_curve::SecretKey<C>) -> Result<Zeroizing<Vec<u8>>, der::Error>
526where
527    C: elliptic_curve::Curve + elliptic_curve::CurveArithmetic + AssociatedOid,
528    elliptic_curve::PublicKey<C>: elliptic_curve::sec1::ToEncodedPoint<C>,
529    C::FieldBytesSize: elliptic_curve::sec1::ModulusSize,
530{
531    let private_key_bytes = Zeroizing::new(key.to_bytes());
532    let public_key_bytes = key.public_key().to_encoded_point(false);
533    Ok(Zeroizing::new(
534        sec1::EcPrivateKey {
535            private_key: &private_key_bytes,
536            parameters: Some(sec1::EcParameters::NamedCurve(C::OID)),
537            public_key: Some(public_key_bytes.as_bytes()),
538        }
539        .to_der()?,
540    ))
541}
542
543fn to_sec1_pem<C>(
544    key: &elliptic_curve::SecretKey<C>,
545    line_ending: pem_rfc7468::LineEnding,
546) -> Result<Zeroizing<String>, der::Error>
547where
548    C: elliptic_curve::Curve + elliptic_curve::CurveArithmetic + AssociatedOid,
549    elliptic_curve::PublicKey<C>: elliptic_curve::sec1::ToEncodedPoint<C>,
550    C::FieldBytesSize: elliptic_curve::sec1::ModulusSize,
551{
552    let private_key_bytes = Zeroizing::new(key.to_bytes());
553    let public_key_bytes = key.public_key().to_encoded_point(false);
554    Ok(Zeroizing::new(
555        sec1::EcPrivateKey {
556            private_key: &private_key_bytes,
557            parameters: Some(sec1::EcParameters::NamedCurve(C::OID)),
558            public_key: Some(public_key_bytes.as_bytes()),
559        }
560        .to_pem(line_ending)?,
561    ))
562}
563
564impl From<&PrivateKey> for JsonWebKeyPublicParameters {
565    fn from(val: &PrivateKey) -> Self {
566        match val {
567            PrivateKey::Rsa(key) => key.to_public_key().into(),
568            PrivateKey::EcP256(key) => key.public_key().into(),
569            PrivateKey::EcP384(key) => key.public_key().into(),
570            PrivateKey::EcK256(key) => key.public_key().into(),
571        }
572    }
573}
574
575impl ParametersInfo for PrivateKey {
576    fn kty(&self) -> JsonWebKeyType {
577        match self {
578            PrivateKey::Rsa(_) => JsonWebKeyType::Rsa,
579            PrivateKey::EcP256(_) | PrivateKey::EcP384(_) | PrivateKey::EcK256(_) => {
580                JsonWebKeyType::Ec
581            }
582        }
583    }
584
585    fn possible_algs(&self) -> &'static [JsonWebSignatureAlg] {
586        match self {
587            PrivateKey::Rsa(_) => &[
588                JsonWebSignatureAlg::Rs256,
589                JsonWebSignatureAlg::Rs384,
590                JsonWebSignatureAlg::Rs512,
591                JsonWebSignatureAlg::Ps256,
592                JsonWebSignatureAlg::Ps384,
593                JsonWebSignatureAlg::Ps512,
594            ],
595            PrivateKey::EcP256(_) => &[JsonWebSignatureAlg::Es256],
596            PrivateKey::EcP384(_) => &[JsonWebSignatureAlg::Es384],
597            PrivateKey::EcK256(_) => &[JsonWebSignatureAlg::Es256K],
598        }
599    }
600}
601
602/// A structure to store a list of [`PrivateKey`]. The keys are held in an
603/// [`Arc`] to ensure they are only loaded once in memory and allow cheap
604/// cloning
605#[derive(Clone, Default)]
606pub struct Keystore {
607    keys: Arc<JsonWebKeySet<PrivateKey>>,
608}
609
610impl Keystore {
611    /// Create a keystore out of a JSON Web Key Set
612    #[must_use]
613    pub fn new(keys: JsonWebKeySet<PrivateKey>) -> Self {
614        let keys = Arc::new(keys);
615        Self { keys }
616    }
617
618    /// Get the public JSON Web Key Set for the keys stored in this [`Keystore`]
619    #[must_use]
620    pub fn public_jwks(&self) -> PublicJsonWebKeySet {
621        self.keys
622            .iter()
623            .map(|key| {
624                key.cloned_map(|params: &PrivateKey| JsonWebKeyPublicParameters::from(params))
625            })
626            .collect()
627    }
628}
629
630impl Deref for Keystore {
631    type Target = JsonWebKeySet<PrivateKey>;
632
633    fn deref(&self) -> &Self::Target {
634        &self.keys
635    }
636}