Skip to main content

mas_jose/jwa/
asymmetric.rs

1// Copyright 2025, 2026 Element Creations Ltd.
2// Copyright 2024, 2025 New Vector Ltd.
3// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
4//
5// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
6// Please see LICENSE files in the repository root for full details.
7
8use digest::Digest;
9use mas_iana::jose::{JsonWebKeyEcEllipticCurve, JsonWebSignatureAlg};
10use sha2::{Sha256, Sha384, Sha512};
11use signature::rand_core::TryCryptoRng;
12use thiserror::Error;
13
14use super::signature::Signature;
15use crate::jwk::{JsonWebKeyPrivateParameters, JsonWebKeyPublicParameters};
16
17#[derive(Debug, Error)]
18pub enum AsymmetricKeyFromJwkError {
19    #[error("Invalid RSA parameters")]
20    Rsa {
21        #[from]
22        inner: rsa::errors::Error,
23    },
24
25    #[error("Invalid Elliptic Curve parameters")]
26    EllipticCurve {
27        #[from]
28        inner: elliptic_curve::Error,
29    },
30
31    #[error("Unsupported algorithm {alg}")]
32    UnsupportedAlgorithm { alg: JsonWebSignatureAlg },
33
34    #[error("Key not suitable for algorithm {alg}")]
35    KeyNotSuitable { alg: JsonWebSignatureAlg },
36}
37
38/// An enum of all supported asymmetric signature algorithms verifying keys
39#[non_exhaustive]
40pub enum AsymmetricSigningKey {
41    Rs256(super::Rs256SigningKey),
42    Rs384(super::Rs384SigningKey),
43    Rs512(super::Rs512SigningKey),
44    Ps256(super::Ps256SigningKey),
45    Ps384(super::Ps384SigningKey),
46    Ps512(super::Ps512SigningKey),
47    Es256(super::Es256SigningKey),
48    Es384(super::Es384SigningKey),
49    Es256K(super::Es256KSigningKey),
50}
51
52impl AsymmetricSigningKey {
53    /// Create a new signing key with the RS256 algorithm from the given RSA
54    /// private key.
55    #[must_use]
56    pub fn rs256(key: rsa::RsaPrivateKey) -> Self {
57        Self::Rs256(rsa::pkcs1v15::SigningKey::new(key))
58    }
59
60    /// Create a new signing key with the RS384 algorithm from the given RSA
61    /// private key.
62    #[must_use]
63    pub fn rs384(key: rsa::RsaPrivateKey) -> Self {
64        Self::Rs384(rsa::pkcs1v15::SigningKey::new(key))
65    }
66
67    /// Create a new signing key with the RS512 algorithm from the given RSA
68    /// private key.
69    #[must_use]
70    pub fn rs512(key: rsa::RsaPrivateKey) -> Self {
71        Self::Rs512(rsa::pkcs1v15::SigningKey::new(key))
72    }
73
74    /// Create a new signing key with the PS256 algorithm from the given RSA
75    /// private key.
76    #[must_use]
77    pub fn ps256(key: rsa::RsaPrivateKey) -> Self {
78        Self::Ps256(rsa::pss::SigningKey::new_with_salt_len(
79            key,
80            Sha256::output_size(),
81        ))
82    }
83
84    /// Create a new signing key with the PS384 algorithm from the given RSA
85    /// private key.
86    #[must_use]
87    pub fn ps384(key: rsa::RsaPrivateKey) -> Self {
88        Self::Ps384(rsa::pss::SigningKey::new_with_salt_len(
89            key,
90            Sha384::output_size(),
91        ))
92    }
93
94    /// Create a new signing key with the PS512 algorithm from the given RSA
95    /// private key.
96    #[must_use]
97    pub fn ps512(key: rsa::RsaPrivateKey) -> Self {
98        Self::Ps512(rsa::pss::SigningKey::new_with_salt_len(
99            key,
100            Sha512::output_size(),
101        ))
102    }
103
104    /// Create a new signing key with the ES256 algorithm from the given ECDSA
105    /// private key.
106    #[must_use]
107    pub fn es256(key: elliptic_curve::SecretKey<p256::NistP256>) -> Self {
108        Self::Es256(ecdsa::SigningKey::from(key))
109    }
110
111    /// Create a new signing key with the ES384 algorithm from the given ECDSA
112    /// private key.
113    #[must_use]
114    pub fn es384(key: elliptic_curve::SecretKey<p384::NistP384>) -> Self {
115        Self::Es384(ecdsa::SigningKey::from(key))
116    }
117
118    /// Create a new signing key with the ES256K algorithm from the given ECDSA
119    /// private key.
120    #[must_use]
121    pub fn es256k(key: elliptic_curve::SecretKey<k256::Secp256k1>) -> Self {
122        Self::Es256K(ecdsa::SigningKey::from(key))
123    }
124
125    /// Create a new signing key for the given algorithm from the given private
126    /// JWK parameters.
127    ///
128    /// # Errors
129    ///
130    /// Returns an error if the key parameters are not suitable for the given
131    /// algorithm.
132    pub fn from_jwk_and_alg(
133        params: &JsonWebKeyPrivateParameters,
134        alg: &JsonWebSignatureAlg,
135    ) -> Result<Self, AsymmetricKeyFromJwkError> {
136        match (params, alg) {
137            (JsonWebKeyPrivateParameters::Rsa(params), alg) => match alg {
138                JsonWebSignatureAlg::Rs256 => Ok(Self::rs256(params.try_into()?)),
139                JsonWebSignatureAlg::Rs384 => Ok(Self::rs384(params.try_into()?)),
140                JsonWebSignatureAlg::Rs512 => Ok(Self::rs512(params.try_into()?)),
141                JsonWebSignatureAlg::Ps256 => Ok(Self::ps256(params.try_into()?)),
142                JsonWebSignatureAlg::Ps384 => Ok(Self::ps384(params.try_into()?)),
143                JsonWebSignatureAlg::Ps512 => Ok(Self::ps512(params.try_into()?)),
144                _ => Err(AsymmetricKeyFromJwkError::KeyNotSuitable { alg: alg.clone() }),
145            },
146
147            (JsonWebKeyPrivateParameters::Ec(params), JsonWebSignatureAlg::Es256)
148                if params.crv == JsonWebKeyEcEllipticCurve::P256 =>
149            {
150                Ok(Self::es256(params.try_into()?))
151            }
152
153            (JsonWebKeyPrivateParameters::Ec(params), JsonWebSignatureAlg::Es384)
154                if params.crv == JsonWebKeyEcEllipticCurve::P384 =>
155            {
156                Ok(Self::es384(params.try_into()?))
157            }
158
159            (JsonWebKeyPrivateParameters::Ec(params), JsonWebSignatureAlg::Es512)
160                if params.crv == JsonWebKeyEcEllipticCurve::P521 =>
161            {
162                Err(AsymmetricKeyFromJwkError::UnsupportedAlgorithm { alg: alg.clone() })
163            }
164
165            (JsonWebKeyPrivateParameters::Ec(params), JsonWebSignatureAlg::Es256K)
166                if params.crv == JsonWebKeyEcEllipticCurve::Secp256K1 =>
167            {
168                Ok(Self::es256k(params.try_into()?))
169            }
170
171            (JsonWebKeyPrivateParameters::Okp(_params), _) => {
172                Err(AsymmetricKeyFromJwkError::UnsupportedAlgorithm { alg: alg.clone() })
173            }
174
175            _ => Err(AsymmetricKeyFromJwkError::KeyNotSuitable { alg: alg.clone() }),
176        }
177    }
178}
179
180impl From<super::Rs256SigningKey> for AsymmetricSigningKey {
181    fn from(key: super::Rs256SigningKey) -> Self {
182        Self::Rs256(key)
183    }
184}
185
186impl From<super::Rs384SigningKey> for AsymmetricSigningKey {
187    fn from(key: super::Rs384SigningKey) -> Self {
188        Self::Rs384(key)
189    }
190}
191
192impl From<super::Rs512SigningKey> for AsymmetricSigningKey {
193    fn from(key: super::Rs512SigningKey) -> Self {
194        Self::Rs512(key)
195    }
196}
197
198impl From<super::Ps256SigningKey> for AsymmetricSigningKey {
199    fn from(key: super::Ps256SigningKey) -> Self {
200        Self::Ps256(key)
201    }
202}
203
204impl From<super::Ps384SigningKey> for AsymmetricSigningKey {
205    fn from(key: super::Ps384SigningKey) -> Self {
206        Self::Ps384(key)
207    }
208}
209
210impl From<super::Ps512SigningKey> for AsymmetricSigningKey {
211    fn from(key: super::Ps512SigningKey) -> Self {
212        Self::Ps512(key)
213    }
214}
215
216impl From<super::Es256SigningKey> for AsymmetricSigningKey {
217    fn from(key: super::Es256SigningKey) -> Self {
218        Self::Es256(key)
219    }
220}
221
222impl From<super::Es384SigningKey> for AsymmetricSigningKey {
223    fn from(key: super::Es384SigningKey) -> Self {
224        Self::Es384(key)
225    }
226}
227
228impl From<super::Es256KSigningKey> for AsymmetricSigningKey {
229    fn from(key: super::Es256KSigningKey) -> Self {
230        Self::Es256K(key)
231    }
232}
233
234impl signature::RandomizedSigner<Signature> for AsymmetricSigningKey {
235    fn try_sign_with_rng<R: TryCryptoRng + ?Sized>(
236        &self,
237        rng: &mut R,
238        msg: &[u8],
239    ) -> Result<Signature, signature::Error> {
240        match self {
241            Self::Rs256(key) => {
242                let signature = key.try_sign_with_rng(rng, msg)?;
243                Ok(Signature::from_signature(&signature))
244            }
245            Self::Rs384(key) => {
246                let signature = key.try_sign_with_rng(rng, msg)?;
247                Ok(Signature::from_signature(&signature))
248            }
249            Self::Rs512(key) => {
250                let signature = key.try_sign_with_rng(rng, msg)?;
251                Ok(Signature::from_signature(&signature))
252            }
253            Self::Ps256(key) => {
254                let signature = key.try_sign_with_rng(rng, msg)?;
255                Ok(Signature::from_signature(&signature))
256            }
257            Self::Ps384(key) => {
258                let signature = key.try_sign_with_rng(rng, msg)?;
259                Ok(Signature::from_signature(&signature))
260            }
261            Self::Ps512(key) => {
262                let signature = key.try_sign_with_rng(rng, msg)?;
263                Ok(Signature::from_signature(&signature))
264            }
265            Self::Es256(key) => {
266                let signature: ecdsa::Signature<_> = key.try_sign_with_rng(rng, msg)?;
267                Ok(Signature::from_signature(&signature))
268            }
269            Self::Es384(key) => {
270                let signature: ecdsa::Signature<_> = key.try_sign_with_rng(rng, msg)?;
271                Ok(Signature::from_signature(&signature))
272            }
273            Self::Es256K(key) => {
274                let signature: ecdsa::Signature<_> = key.try_sign_with_rng(rng, msg)?;
275                Ok(Signature::from_signature(&signature))
276            }
277        }
278    }
279}
280
281/// An enum of all supported asymmetric signature algorithms signing keys
282#[non_exhaustive]
283pub enum AsymmetricVerifyingKey {
284    Rs256(super::Rs256VerifyingKey),
285    Rs384(super::Rs384VerifyingKey),
286    Rs512(super::Rs512VerifyingKey),
287    Ps256(super::Ps256VerifyingKey),
288    Ps384(super::Ps384VerifyingKey),
289    Ps512(super::Ps512VerifyingKey),
290    Es256(super::Es256VerifyingKey),
291    Es384(super::Es384VerifyingKey),
292    Es256K(super::Es256KVerifyingKey),
293}
294
295impl AsymmetricVerifyingKey {
296    /// Create a new verifying key with the RS256 algorithm from the given RSA
297    /// public key.
298    #[must_use]
299    pub fn rs256(key: rsa::RsaPublicKey) -> Self {
300        Self::Rs256(rsa::pkcs1v15::VerifyingKey::new(key))
301    }
302
303    /// Create a new verifying key with the RS384 algorithm from the given RSA
304    /// public key.
305    #[must_use]
306    pub fn rs384(key: rsa::RsaPublicKey) -> Self {
307        Self::Rs384(rsa::pkcs1v15::VerifyingKey::new(key))
308    }
309
310    /// Create a new verifying key with the RS512 algorithm from the given RSA
311    /// public key.
312    #[must_use]
313    pub fn rs512(key: rsa::RsaPublicKey) -> Self {
314        Self::Rs512(rsa::pkcs1v15::VerifyingKey::new(key))
315    }
316
317    /// Create a new verifying key with the PS256 algorithm from the given RSA
318    /// public key.
319    #[must_use]
320    pub fn ps256(key: rsa::RsaPublicKey) -> Self {
321        Self::Ps256(rsa::pss::VerifyingKey::new(key))
322    }
323
324    /// Create a new verifying key with the PS384 algorithm from the given RSA
325    /// public key.
326    #[must_use]
327    pub fn ps384(key: rsa::RsaPublicKey) -> Self {
328        Self::Ps384(rsa::pss::VerifyingKey::new(key))
329    }
330
331    /// Create a new verifying key with the PS512 algorithm from the given RSA
332    /// public key.
333    #[must_use]
334    pub fn ps512(key: rsa::RsaPublicKey) -> Self {
335        Self::Ps512(rsa::pss::VerifyingKey::new(key))
336    }
337
338    /// Create a new verifying key with the ES256 algorithm from the given ECDSA
339    /// public key.
340    #[must_use]
341    pub fn es256(key: elliptic_curve::PublicKey<p256::NistP256>) -> Self {
342        Self::Es256(ecdsa::VerifyingKey::from(key))
343    }
344
345    /// Create a new verifying key with the ES384 algorithm from the given ECDSA
346    /// public key.
347    #[must_use]
348    pub fn es384(key: elliptic_curve::PublicKey<p384::NistP384>) -> Self {
349        Self::Es384(ecdsa::VerifyingKey::from(key))
350    }
351
352    /// Create a new verifying key with the ES256K algorithm from the given
353    /// ECDSA public key.
354    #[must_use]
355    pub fn es256k(key: elliptic_curve::PublicKey<k256::Secp256k1>) -> Self {
356        Self::Es256K(ecdsa::VerifyingKey::from(key))
357    }
358
359    /// Create a new verifying key for the given algorithm from the given public
360    /// JWK parameters.
361    ///
362    /// # Errors
363    ///
364    /// Returns an error if the key parameters are not suitable for the given
365    /// algorithm.
366    pub fn from_jwk_and_alg(
367        params: &JsonWebKeyPublicParameters,
368        alg: &JsonWebSignatureAlg,
369    ) -> Result<Self, AsymmetricKeyFromJwkError> {
370        match (params, alg) {
371            (JsonWebKeyPublicParameters::Rsa(params), alg) => match alg {
372                JsonWebSignatureAlg::Rs256 => Ok(Self::rs256(params.try_into()?)),
373                JsonWebSignatureAlg::Rs384 => Ok(Self::rs384(params.try_into()?)),
374                JsonWebSignatureAlg::Rs512 => Ok(Self::rs512(params.try_into()?)),
375                JsonWebSignatureAlg::Ps256 => Ok(Self::ps256(params.try_into()?)),
376                JsonWebSignatureAlg::Ps384 => Ok(Self::ps384(params.try_into()?)),
377                JsonWebSignatureAlg::Ps512 => Ok(Self::ps512(params.try_into()?)),
378                _ => Err(AsymmetricKeyFromJwkError::KeyNotSuitable { alg: alg.clone() }),
379            },
380
381            (JsonWebKeyPublicParameters::Ec(params), JsonWebSignatureAlg::Es256)
382                if params.crv == JsonWebKeyEcEllipticCurve::P256 =>
383            {
384                Ok(Self::es256(params.try_into()?))
385            }
386
387            (JsonWebKeyPublicParameters::Ec(params), JsonWebSignatureAlg::Es384)
388                if params.crv == JsonWebKeyEcEllipticCurve::P384 =>
389            {
390                Ok(Self::es384(params.try_into()?))
391            }
392
393            (JsonWebKeyPublicParameters::Ec(params), JsonWebSignatureAlg::Es512)
394                if params.crv == JsonWebKeyEcEllipticCurve::P521 =>
395            {
396                Err(AsymmetricKeyFromJwkError::UnsupportedAlgorithm { alg: alg.clone() })
397            }
398
399            (JsonWebKeyPublicParameters::Ec(params), JsonWebSignatureAlg::Es256K)
400                if params.crv == JsonWebKeyEcEllipticCurve::Secp256K1 =>
401            {
402                Ok(Self::es256k(params.try_into()?))
403            }
404
405            (JsonWebKeyPublicParameters::Okp(_params), _) => {
406                Err(AsymmetricKeyFromJwkError::UnsupportedAlgorithm { alg: alg.clone() })
407            }
408
409            _ => Err(AsymmetricKeyFromJwkError::KeyNotSuitable { alg: alg.clone() }),
410        }
411    }
412}
413
414impl From<super::Rs256VerifyingKey> for AsymmetricVerifyingKey {
415    fn from(key: super::Rs256VerifyingKey) -> Self {
416        Self::Rs256(key)
417    }
418}
419
420impl From<super::Rs384VerifyingKey> for AsymmetricVerifyingKey {
421    fn from(key: super::Rs384VerifyingKey) -> Self {
422        Self::Rs384(key)
423    }
424}
425
426impl From<super::Rs512VerifyingKey> for AsymmetricVerifyingKey {
427    fn from(key: super::Rs512VerifyingKey) -> Self {
428        Self::Rs512(key)
429    }
430}
431
432impl From<super::Ps256VerifyingKey> for AsymmetricVerifyingKey {
433    fn from(key: super::Ps256VerifyingKey) -> Self {
434        Self::Ps256(key)
435    }
436}
437
438impl From<super::Ps384VerifyingKey> for AsymmetricVerifyingKey {
439    fn from(key: super::Ps384VerifyingKey) -> Self {
440        Self::Ps384(key)
441    }
442}
443
444impl From<super::Ps512VerifyingKey> for AsymmetricVerifyingKey {
445    fn from(key: super::Ps512VerifyingKey) -> Self {
446        Self::Ps512(key)
447    }
448}
449
450impl From<super::Es256VerifyingKey> for AsymmetricVerifyingKey {
451    fn from(key: super::Es256VerifyingKey) -> Self {
452        Self::Es256(key)
453    }
454}
455
456impl From<super::Es384VerifyingKey> for AsymmetricVerifyingKey {
457    fn from(key: super::Es384VerifyingKey) -> Self {
458        Self::Es384(key)
459    }
460}
461
462impl From<super::Es256KVerifyingKey> for AsymmetricVerifyingKey {
463    fn from(key: super::Es256KVerifyingKey) -> Self {
464        Self::Es256K(key)
465    }
466}
467
468impl signature::Verifier<Signature> for AsymmetricVerifyingKey {
469    fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), ecdsa::Error> {
470        match self {
471            Self::Rs256(key) => {
472                let signature = signature.to_signature()?;
473                key.verify(msg, &signature)
474            }
475            Self::Rs384(key) => {
476                let signature = signature.to_signature()?;
477                key.verify(msg, &signature)
478            }
479            Self::Rs512(key) => {
480                let signature = signature.to_signature()?;
481                key.verify(msg, &signature)
482            }
483            Self::Ps256(key) => {
484                let signature = signature.to_signature()?;
485                key.verify(msg, &signature)
486            }
487            Self::Ps384(key) => {
488                let signature = signature.to_signature()?;
489                key.verify(msg, &signature)
490            }
491            Self::Ps512(key) => {
492                let signature = signature.to_signature()?;
493                key.verify(msg, &signature)
494            }
495            Self::Es256(key) => {
496                let signature: ecdsa::Signature<_> = signature.to_signature()?;
497                key.verify(msg, &signature)
498            }
499            Self::Es384(key) => {
500                let signature: ecdsa::Signature<_> = signature.to_signature()?;
501                key.verify(msg, &signature)
502            }
503            Self::Es256K(key) => {
504                let signature: ecdsa::Signature<_> = signature.to_signature()?;
505                key.verify(msg, &signature)
506            }
507        }
508    }
509}