Skip to main content

jsonwebtoken/
jwk.rs

1//! This crate contains types only for working JWK and JWK Sets
2//! This is only meant to be used to deal with public JWK, not generate ones.
3//! Most of the code in this file is taken from <https://github.com/lawliet89/biscuit> but
4//! tweaked to remove the private bits as it's not the goal for this crate currently.
5
6use std::collections::BTreeMap;
7use std::{fmt, str::FromStr};
8
9use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
10
11use crate::crypto::{CryptoProvider, ec_pub_components_from_public_key};
12use crate::errors::{self, Error, ErrorKind, new_error};
13use crate::serialization::b64_encode;
14use crate::{Algorithm, AlgorithmFamily, DecodingKey, EncodingKey, decoding::DecodingKeyKind};
15
16/// The intended usage of the public `KeyType`. This enum is serialized `untagged`
17#[derive(Clone, Debug, Eq, PartialEq, Hash)]
18pub enum PublicKeyUse {
19    /// Indicates a public key is meant for signature verification
20    Signature,
21    /// Indicates a public key is meant for encryption
22    Encryption,
23    /// Other usage
24    Other(String),
25}
26
27impl Serialize for PublicKeyUse {
28    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
29    where
30        S: Serializer,
31    {
32        let string = match self {
33            PublicKeyUse::Signature => "sig",
34            PublicKeyUse::Encryption => "enc",
35            PublicKeyUse::Other(other) => other,
36        };
37
38        serializer.serialize_str(string)
39    }
40}
41
42impl<'de> Deserialize<'de> for PublicKeyUse {
43    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
44    where
45        D: Deserializer<'de>,
46    {
47        struct PublicKeyUseVisitor;
48        impl de::Visitor<'_> for PublicKeyUseVisitor {
49            type Value = PublicKeyUse;
50
51            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
52                write!(formatter, "a string")
53            }
54
55            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
56            where
57                E: de::Error,
58            {
59                Ok(match v {
60                    "sig" => PublicKeyUse::Signature,
61                    "enc" => PublicKeyUse::Encryption,
62                    other => PublicKeyUse::Other(other.to_string()),
63                })
64            }
65        }
66
67        deserializer.deserialize_string(PublicKeyUseVisitor)
68    }
69}
70
71/// Operations that the key is intended to be used for. This enum is serialized `untagged`
72#[derive(Clone, Debug, Eq, PartialEq, Hash)]
73pub enum KeyOperations {
74    /// Computer digital signature or MAC
75    Sign,
76    /// Verify digital signature or MAC
77    Verify,
78    /// Encrypt content
79    Encrypt,
80    /// Decrypt content and validate decryption, if applicable
81    Decrypt,
82    /// Encrypt key
83    WrapKey,
84    /// Decrypt key and validate decryption, if applicable
85    UnwrapKey,
86    /// Derive key
87    DeriveKey,
88    /// Derive bits not to be used as a key
89    DeriveBits,
90    /// Other operation
91    Other(String),
92}
93
94impl Serialize for KeyOperations {
95    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
96    where
97        S: Serializer,
98    {
99        let string = match self {
100            KeyOperations::Sign => "sign",
101            KeyOperations::Verify => "verify",
102            KeyOperations::Encrypt => "encrypt",
103            KeyOperations::Decrypt => "decrypt",
104            KeyOperations::WrapKey => "wrapKey",
105            KeyOperations::UnwrapKey => "unwrapKey",
106            KeyOperations::DeriveKey => "deriveKey",
107            KeyOperations::DeriveBits => "deriveBits",
108            KeyOperations::Other(other) => other,
109        };
110
111        serializer.serialize_str(string)
112    }
113}
114
115impl<'de> Deserialize<'de> for KeyOperations {
116    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
117    where
118        D: Deserializer<'de>,
119    {
120        struct KeyOperationsVisitor;
121        impl de::Visitor<'_> for KeyOperationsVisitor {
122            type Value = KeyOperations;
123
124            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
125                write!(formatter, "a string")
126            }
127
128            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
129            where
130                E: de::Error,
131            {
132                Ok(match v {
133                    "sign" => KeyOperations::Sign,
134                    "verify" => KeyOperations::Verify,
135                    "encrypt" => KeyOperations::Encrypt,
136                    "decrypt" => KeyOperations::Decrypt,
137                    "wrapKey" => KeyOperations::WrapKey,
138                    "unwrapKey" => KeyOperations::UnwrapKey,
139                    "deriveKey" => KeyOperations::DeriveKey,
140                    "deriveBits" => KeyOperations::DeriveBits,
141                    other => KeyOperations::Other(other.to_string()),
142                })
143            }
144        }
145
146        deserializer.deserialize_string(KeyOperationsVisitor)
147    }
148}
149
150/// The algorithms of the keys
151#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
152#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize)]
153#[non_exhaustive]
154pub enum KeyAlgorithm {
155    /// HMAC using SHA-256
156    HS256,
157    /// HMAC using SHA-384
158    HS384,
159    /// HMAC using SHA-512
160    HS512,
161
162    /// ECDSA using SHA-256
163    ES256,
164    /// ECDSA using SHA-384
165    ES384,
166
167    /// RSASSA-PKCS1-v1_5 using SHA-256
168    RS256,
169    /// RSASSA-PKCS1-v1_5 using SHA-384
170    RS384,
171    /// RSASSA-PKCS1-v1_5 using SHA-512
172    RS512,
173
174    /// RSASSA-PSS using SHA-256
175    PS256,
176    /// RSASSA-PSS using SHA-384
177    PS384,
178    /// RSASSA-PSS using SHA-512
179    PS512,
180
181    /// Edwards-curve Digital Signature Algorithm (EdDSA)
182    EdDSA,
183
184    /// RSAES-PKCS1-V1_5
185    RSA1_5,
186
187    /// RSAES-OAEP using SHA-1
188    #[serde(rename = "RSA-OAEP")]
189    RSA_OAEP,
190
191    /// RSAES-OAEP-256 using SHA-2
192    #[serde(rename = "RSA-OAEP-256")]
193    RSA_OAEP_256,
194
195    /// Catch-All for when the key algorithm can not be determined or is not supported
196    #[serde(other)]
197    UNKNOWN_ALGORITHM,
198}
199
200impl FromStr for KeyAlgorithm {
201    type Err = Error;
202    fn from_str(s: &str) -> errors::Result<Self> {
203        match s {
204            "HS256" => Ok(KeyAlgorithm::HS256),
205            "HS384" => Ok(KeyAlgorithm::HS384),
206            "HS512" => Ok(KeyAlgorithm::HS512),
207            "ES256" => Ok(KeyAlgorithm::ES256),
208            "ES384" => Ok(KeyAlgorithm::ES384),
209            "RS256" => Ok(KeyAlgorithm::RS256),
210            "RS384" => Ok(KeyAlgorithm::RS384),
211            "PS256" => Ok(KeyAlgorithm::PS256),
212            "PS384" => Ok(KeyAlgorithm::PS384),
213            "PS512" => Ok(KeyAlgorithm::PS512),
214            "RS512" => Ok(KeyAlgorithm::RS512),
215            "EdDSA" => Ok(KeyAlgorithm::EdDSA),
216            "RSA1_5" => Ok(KeyAlgorithm::RSA1_5),
217            "RSA-OAEP" => Ok(KeyAlgorithm::RSA_OAEP),
218            "RSA-OAEP-256" => Ok(KeyAlgorithm::RSA_OAEP_256),
219            _ => Err(ErrorKind::InvalidAlgorithmName.into()),
220        }
221    }
222}
223
224impl From<Algorithm> for KeyAlgorithm {
225    fn from(alg: Algorithm) -> Self {
226        match alg {
227            Algorithm::HS256 => KeyAlgorithm::HS256,
228            Algorithm::HS384 => KeyAlgorithm::HS384,
229            Algorithm::HS512 => KeyAlgorithm::HS512,
230            Algorithm::ES256 => KeyAlgorithm::ES256,
231            Algorithm::ES384 => KeyAlgorithm::ES384,
232            Algorithm::RS256 => KeyAlgorithm::RS256,
233            Algorithm::RS384 => KeyAlgorithm::RS384,
234            Algorithm::RS512 => KeyAlgorithm::RS512,
235            Algorithm::PS256 => KeyAlgorithm::PS256,
236            Algorithm::PS384 => KeyAlgorithm::PS384,
237            Algorithm::PS512 => KeyAlgorithm::PS512,
238            Algorithm::EdDSA => KeyAlgorithm::EdDSA,
239        }
240    }
241}
242
243impl TryFrom<KeyAlgorithm> for Algorithm {
244    type Error = Error;
245
246    fn try_from(alg: KeyAlgorithm) -> Result<Self, Self::Error> {
247        match alg {
248            KeyAlgorithm::HS256 => Ok(Algorithm::HS256),
249            KeyAlgorithm::HS384 => Ok(Algorithm::HS384),
250            KeyAlgorithm::HS512 => Ok(Algorithm::HS512),
251            KeyAlgorithm::ES256 => Ok(Algorithm::ES256),
252            KeyAlgorithm::ES384 => Ok(Algorithm::ES384),
253            KeyAlgorithm::RS256 => Ok(Algorithm::RS256),
254            KeyAlgorithm::RS384 => Ok(Algorithm::RS384),
255            KeyAlgorithm::RS512 => Ok(Algorithm::RS512),
256            KeyAlgorithm::PS256 => Ok(Algorithm::PS256),
257            KeyAlgorithm::PS384 => Ok(Algorithm::PS384),
258            KeyAlgorithm::PS512 => Ok(Algorithm::PS512),
259            KeyAlgorithm::EdDSA => Ok(Algorithm::EdDSA),
260            _ => Err(new_error(ErrorKind::UnsupportedAlgorithm)),
261        }
262    }
263}
264
265impl fmt::Display for KeyAlgorithm {
266    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
267        write!(f, "{:?}", self)
268    }
269}
270
271impl KeyAlgorithm {
272    fn to_algorithm(self) -> errors::Result<Algorithm> {
273        Algorithm::from_str(self.to_string().as_str())
274    }
275}
276
277/// Common JWK parameters
278#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Default, Hash)]
279pub struct CommonParameters {
280    /// The intended use of the public key. Should not be specified with `key_operations`.
281    /// See sections 4.2 and 4.3 of [RFC7517](https://tools.ietf.org/html/rfc7517).
282    #[serde(rename = "use", skip_serializing_if = "Option::is_none", default)]
283    pub public_key_use: Option<PublicKeyUse>,
284
285    /// The `key_ops` (key operations) parameter identifies the operation(s)
286    /// for which the key is intended to be used.  The `key_ops` parameter is
287    /// intended for use cases in which public, private, or symmetric keys
288    /// may be present.
289    /// Should not be specified with `public_key_use`.
290    /// See sections 4.2 and 4.3 of [RFC7517](https://tools.ietf.org/html/rfc7517).
291    #[serde(rename = "key_ops", skip_serializing_if = "Option::is_none", default)]
292    pub key_operations: Option<Vec<KeyOperations>>,
293
294    /// The algorithm keys intended for use with the key.
295    #[serde(rename = "alg", skip_serializing_if = "Option::is_none", default)]
296    pub key_algorithm: Option<KeyAlgorithm>,
297
298    /// The case sensitive Key ID for the key
299    #[serde(rename = "kid", skip_serializing_if = "Option::is_none", default)]
300    pub key_id: Option<String>,
301
302    /// X.509 Public key certificate URL. This is currently not implemented (correctly).
303    ///
304    /// Serialized to `x5u`.
305    #[serde(rename = "x5u", skip_serializing_if = "Option::is_none")]
306    pub x509_url: Option<String>,
307
308    /// X.509 public key certificate chain. This is currently not implemented (correctly).
309    ///
310    /// Serialized to `x5c`.
311    #[serde(rename = "x5c", skip_serializing_if = "Option::is_none")]
312    pub x509_chain: Option<Vec<String>>,
313
314    /// X.509 Certificate SHA1 thumbprint. This is currently not implemented (correctly).
315    ///
316    /// Serialized to `x5t`.
317    #[serde(rename = "x5t", skip_serializing_if = "Option::is_none")]
318    pub x509_sha1_fingerprint: Option<String>,
319
320    /// X.509 Certificate SHA256 thumbprint. This is currently not implemented (correctly).
321    ///
322    /// Serialized to `x5t#S256`.
323    #[serde(rename = "x5t#S256", skip_serializing_if = "Option::is_none")]
324    pub x509_sha256_fingerprint: Option<String>,
325}
326
327/// Key type value for an Elliptic Curve Key.
328/// This single value enum is a workaround for Rust not supporting associated constants.
329#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Hash)]
330pub enum EllipticCurveKeyType {
331    /// Key type value for an Elliptic Curve Key.
332    #[default]
333    EC,
334}
335
336/// Type of cryptographic curve used by a key. This is defined in
337/// [RFC 7518 #7.6](https://tools.ietf.org/html/rfc7518#section-7.6)
338#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Hash)]
339#[non_exhaustive]
340pub enum EllipticCurve {
341    /// P-256 curve
342    #[serde(rename = "P-256")]
343    #[default]
344    P256,
345    /// P-384 curve
346    #[serde(rename = "P-384")]
347    P384,
348    /// P-521 curve -- unsupported by `ring`.
349    #[serde(rename = "P-521")]
350    P521,
351    /// Ed25519 curve
352    #[serde(rename = "Ed25519")]
353    Ed25519,
354}
355
356/// Parameters for an Elliptic Curve Key
357#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default, Hash)]
358pub struct EllipticCurveKeyParameters {
359    /// Key type value for an Elliptic Curve Key.
360    #[serde(rename = "kty")]
361    pub key_type: EllipticCurveKeyType,
362    /// The "crv" (curve) parameter identifies the cryptographic curve used
363    /// with the key.
364    #[serde(rename = "crv")]
365    pub curve: EllipticCurve,
366    /// The "x" (x coordinate) parameter contains the x coordinate for the
367    /// Elliptic Curve point.
368    pub x: String,
369    /// The "y" (y coordinate) parameter contains the y coordinate for the
370    /// Elliptic Curve point.
371    pub y: String,
372}
373
374/// Key type value for an RSA Key.
375/// This single value enum is a workaround for Rust not supporting associated constants.
376#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Hash)]
377pub enum RSAKeyType {
378    /// Key type value for an RSA Key.
379    #[default]
380    RSA,
381}
382
383/// Parameters for a RSA Key
384#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default, Hash)]
385pub struct RSAKeyParameters {
386    /// Key type value for a RSA Key
387    #[serde(rename = "kty")]
388    pub key_type: RSAKeyType,
389
390    /// The "n" (modulus) parameter contains the modulus value for the RSA
391    /// public key.
392    pub n: String,
393
394    /// The "e" (exponent) parameter contains the exponent value for the RSA
395    /// public key.
396    pub e: String,
397}
398
399/// Key type value for an Octet symmetric key.
400/// This single value enum is a workaround for Rust not supporting associated constants.
401#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Hash)]
402pub enum OctetKeyType {
403    /// Key type value for an Octet symmetric key.
404    #[serde(rename = "oct")]
405    #[default]
406    Octet,
407}
408
409/// Parameters for an Octet Key
410#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default, Hash)]
411pub struct OctetKeyParameters {
412    /// Key type value for an Octet Key
413    #[serde(rename = "kty")]
414    pub key_type: OctetKeyType,
415    /// The octet key value
416    #[serde(rename = "k")]
417    pub value: String,
418}
419
420/// Key type value for an Octet Key Pair.
421/// This single value enum is a workaround for Rust not supporting associated constants.
422#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Hash)]
423pub enum OctetKeyPairType {
424    /// Key type value for an Octet Key Pair.
425    #[serde(rename = "OKP")]
426    #[default]
427    OctetKeyPair,
428}
429
430/// Parameters for an Octet Key Pair
431#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default, Hash)]
432pub struct OctetKeyPairParameters {
433    /// Key type value for an Octet Key Pair
434    #[serde(rename = "kty")]
435    pub key_type: OctetKeyPairType,
436    /// The "crv" (curve) parameter identifies the cryptographic curve used
437    /// with the key.
438    #[serde(rename = "crv")]
439    pub curve: EllipticCurve,
440    /// The "x" parameter contains the base64 encoded public key
441    pub x: String,
442}
443
444/// Parameters for unknown keys
445#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default, Hash)]
446pub struct OtherKeyParameters {
447    #[serde(flatten)]
448    #[allow(missing_docs)]
449    pub fields: BTreeMap<String, serde_json::Value>,
450}
451
452/// Algorithm specific parameters
453#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)]
454#[serde(untagged)]
455#[allow(missing_docs)]
456#[non_exhaustive]
457pub enum AlgorithmParameters {
458    EllipticCurve(EllipticCurveKeyParameters),
459    RSA(RSAKeyParameters),
460    OctetKey(OctetKeyParameters),
461    OctetKeyPair(OctetKeyPairParameters),
462    Other(OtherKeyParameters),
463}
464
465/// The function to use to hash the intermediate thumbprint data.
466#[derive(Debug, Clone, Eq, PartialEq)]
467#[allow(missing_docs)]
468#[non_exhaustive]
469pub enum ThumbprintHash {
470    SHA256,
471    SHA384,
472    SHA512,
473}
474
475#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)]
476#[allow(missing_docs)]
477pub struct Jwk {
478    #[serde(flatten)]
479    pub common: CommonParameters,
480    /// Key algorithm specific parameters
481    #[serde(flatten)]
482    pub algorithm: AlgorithmParameters,
483}
484
485impl Jwk {
486    /// Find whether the Algorithm is implemented and supported
487    pub fn is_supported(&self) -> bool {
488        match self.common.key_algorithm {
489            Some(alg) => alg.to_algorithm().is_ok(),
490            _ => false,
491        }
492    }
493
494    /// Create a `JWK` from an `EncodingKey`.
495    pub fn from_encoding_key(key: &EncodingKey, alg: Algorithm) -> errors::Result<Self> {
496        Ok(Self {
497            common: CommonParameters { key_algorithm: Some(alg.into()), ..Default::default() },
498            algorithm: match key.family() {
499                AlgorithmFamily::Hmac => AlgorithmParameters::OctetKey(OctetKeyParameters {
500                    key_type: OctetKeyType::Octet,
501                    value: b64_encode(key.as_bytes()),
502                }),
503                AlgorithmFamily::Rsa => {
504                    let (n, e) = (CryptoProvider::get_default()
505                        .key_utils
506                        .rsa_pub_components_from_private_key)(
507                        key.as_bytes()
508                    )?;
509                    AlgorithmParameters::RSA(RSAKeyParameters {
510                        key_type: RSAKeyType::RSA,
511                        n: b64_encode(n),
512                        e: b64_encode(e),
513                    })
514                }
515                AlgorithmFamily::Ec => {
516                    let (curve, x, y) = (CryptoProvider::get_default()
517                        .key_utils
518                        .ec_pub_components_from_private_key)(
519                        key.as_bytes(), alg
520                    )?;
521                    AlgorithmParameters::EllipticCurve(EllipticCurveKeyParameters {
522                        key_type: EllipticCurveKeyType::EC,
523                        curve,
524                        x: b64_encode(x),
525                        y: b64_encode(y),
526                    })
527                }
528                AlgorithmFamily::Ed => {
529                    // Get the curve type based off the encoding key length
530                    // Note: here we will receive a DER key which contains a 16 byte ANS.1 header
531                    let curve_type: EllipticCurve = match key.as_bytes().len() {
532                        // 16 byte header + 32 byte Ed25519 key
533                        48 => Ok(EllipticCurve::Ed25519),
534                        _ => Err(Error::from(ErrorKind::InvalidEddsaKey)),
535                    }?;
536
537                    // Extract the public key from the encoding key
538                    let public_key_bytes = (CryptoProvider::get_default()
539                        .key_utils
540                        .ed_pub_components_from_private_key)(
541                        key.as_bytes(), &curve_type
542                    )?;
543
544                    AlgorithmParameters::OctetKeyPair(OctetKeyPairParameters {
545                        key_type: OctetKeyPairType::OctetKeyPair,
546                        curve: curve_type,
547                        x: b64_encode(public_key_bytes),
548                    })
549                }
550            },
551        })
552    }
553
554    /// Create a `JWK` from a `DecodingKey`.
555    pub fn from_decoding_key(
556        key: &DecodingKey,
557        alg: Option<Algorithm>,
558    ) -> crate::errors::Result<Self> {
559        Ok(Self {
560            common: CommonParameters { key_algorithm: alg.map(|a| a.into()), ..Default::default() },
561            algorithm: match key.family() {
562                crate::algorithms::AlgorithmFamily::Hmac => {
563                    AlgorithmParameters::OctetKey(OctetKeyParameters {
564                        key_type: OctetKeyType::Octet,
565                        value: b64_encode(key.try_get_as_bytes()?),
566                    })
567                }
568                crate::algorithms::AlgorithmFamily::Rsa => {
569                    let (n, e) = match &key.kind() {
570                        DecodingKeyKind::RsaModulusExponent { n, e } => {
571                            (b64_encode(n), b64_encode(e))
572                        }
573                        DecodingKeyKind::SecretOrDer(der) => {
574                            let (n, e) = (CryptoProvider::get_default()
575                                .key_utils
576                                .rsa_pub_components_from_public_key)(
577                                der
578                            )?;
579                            (b64_encode(n), b64_encode(e))
580                        }
581                    };
582
583                    AlgorithmParameters::RSA(RSAKeyParameters { key_type: RSAKeyType::RSA, n, e })
584                }
585                crate::algorithms::AlgorithmFamily::Ec => {
586                    let (curve, x, y) = ec_pub_components_from_public_key(key.try_get_as_bytes()?)?;
587                    AlgorithmParameters::EllipticCurve(EllipticCurveKeyParameters {
588                        key_type: EllipticCurveKeyType::EC,
589                        curve,
590                        x: b64_encode(x),
591                        y: b64_encode(y),
592                    })
593                }
594                crate::algorithms::AlgorithmFamily::Ed => {
595                    let pub_bytes = key.try_get_as_bytes()?;
596                    let (curve_type, x) = match pub_bytes.len() {
597                        // ED25519: https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5
598                        32 => (EllipticCurve::Ed25519, pub_bytes),
599                        _ => return Err(ErrorKind::InvalidEddsaKey.into()),
600                    };
601
602                    AlgorithmParameters::OctetKeyPair(OctetKeyPairParameters {
603                        key_type: OctetKeyPairType::OctetKeyPair,
604                        curve: curve_type,
605                        x: b64_encode(x),
606                    })
607                }
608            },
609        })
610    }
611
612    /// Compute the thumbprint of the JWK.
613    ///
614    /// Per [RFC-7638](https://datatracker.ietf.org/doc/html/rfc7638)
615    pub fn thumbprint(&self, hash_function: ThumbprintHash) -> errors::Result<String> {
616        let pre = match &self.algorithm {
617            AlgorithmParameters::EllipticCurve(a) => match a.curve {
618                EllipticCurve::P256 | EllipticCurve::P384 | EllipticCurve::P521 => {
619                    format!(
620                        r#"{{"crv":{},"kty":{},"x":"{}","y":"{}"}}"#,
621                        serde_json::to_string(&a.curve).unwrap(),
622                        serde_json::to_string(&a.key_type).unwrap(),
623                        a.x,
624                        a.y,
625                    )
626                }
627                EllipticCurve::Ed25519 => {
628                    return Err(ErrorKind::InvalidKeyFormat.into());
629                }
630            },
631            AlgorithmParameters::RSA(a) => {
632                format!(
633                    r#"{{"e":"{}","kty":{},"n":"{}"}}"#,
634                    a.e,
635                    serde_json::to_string(&a.key_type).unwrap(),
636                    a.n,
637                )
638            }
639            AlgorithmParameters::OctetKey(a) => {
640                format!(
641                    r#"{{"k":"{}","kty":{}}}"#,
642                    a.value,
643                    serde_json::to_string(&a.key_type).unwrap()
644                )
645            }
646            AlgorithmParameters::OctetKeyPair(a) => match a.curve {
647                EllipticCurve::P256 | EllipticCurve::P384 | EllipticCurve::P521 => {
648                    return Err(ErrorKind::InvalidKeyFormat.into());
649                }
650                EllipticCurve::Ed25519 => {
651                    format!(
652                        r#"{{"crv":{},"kty":{},"x":"{}"}}"#,
653                        serde_json::to_string(&a.curve).unwrap(),
654                        serde_json::to_string(&a.key_type).unwrap(),
655                        a.x,
656                    )
657                }
658            },
659            AlgorithmParameters::Other(_) => return Err(ErrorKind::UnsupportedAlgorithm.into()),
660        };
661
662        Ok(b64_encode((CryptoProvider::get_default().key_utils.compute_digest)(
663            pre.as_bytes(),
664            hash_function,
665        )?))
666    }
667}
668
669/// A JWK set
670#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, Hash)]
671#[allow(missing_docs)]
672pub struct JwkSet {
673    pub keys: Vec<Jwk>,
674}
675
676impl JwkSet {
677    /// Find the key in the set that matches the given key id, if any.
678    pub fn find(&self, kid: &str) -> Option<&Jwk> {
679        self.keys
680            .iter()
681            .find(|jwk| jwk.common.key_id.is_some() && jwk.common.key_id.as_ref().unwrap() == kid)
682    }
683}
684
685#[cfg(test)]
686mod tests {
687    use std::collections::BTreeMap;
688
689    use serde_json::json;
690    use wasm_bindgen_test::wasm_bindgen_test;
691
692    use crate::Algorithm;
693    use crate::errors::ErrorKind;
694    use crate::jwk::{
695        AlgorithmParameters, CommonParameters, EllipticCurve, Jwk, JwkSet, KeyAlgorithm,
696        OctetKeyPairParameters, OctetKeyPairType, OctetKeyType, RSAKeyParameters, ThumbprintHash,
697    };
698    use crate::serialization::b64_encode;
699    use crate::{DecodingKey, EncodingKey};
700
701    #[test]
702    #[wasm_bindgen_test]
703    fn check_hs256() {
704        let key = b64_encode("abcdefghijklmnopqrstuvwxyz012345");
705        let jwks_json = json!({
706            "keys": [
707                {
708                    "kty": "oct",
709                    "alg": "HS256",
710                    "kid": "abc123",
711                    "k": key
712                }
713            ]
714        });
715
716        let set: JwkSet = serde_json::from_value(jwks_json).expect("Failed HS256 check");
717        assert_eq!(set.keys.len(), 1);
718        let key = &set.keys[0];
719        assert_eq!(key.common.key_id, Some("abc123".to_string()));
720        let algorithm = key.common.key_algorithm.unwrap().to_algorithm().unwrap();
721        assert_eq!(algorithm, Algorithm::HS256);
722
723        match &key.algorithm {
724            AlgorithmParameters::OctetKey(key) => {
725                assert_eq!(key.key_type, OctetKeyType::Octet);
726                assert_eq!(key.value, key.value)
727            }
728            _ => panic!("Unexpected key algorithm"),
729        }
730    }
731
732    #[test]
733    fn deserialize_unknown_key_algorithm() {
734        let key_alg_json = json!("");
735        let key_alg_result: KeyAlgorithm =
736            serde_json::from_value(key_alg_json).expect("Could not deserialize json");
737        assert_eq!(key_alg_result, KeyAlgorithm::UNKNOWN_ALGORITHM);
738    }
739
740    #[test]
741    fn deserialize_unknown_kty() {
742        let parameters_json = json!({
743            "kty": "AKP",
744            "foo": "bar",
745            "solution": 42
746        });
747        let parameters_result: AlgorithmParameters =
748            serde_json::from_value(parameters_json).expect("Could not deserialize json");
749        match parameters_result {
750            AlgorithmParameters::Other(other_key_parameters) => {
751                let mut expected = BTreeMap::new();
752                expected.insert("kty".to_owned(), serde_json::to_value("AKP").unwrap());
753                expected.insert("foo".to_owned(), serde_json::to_value("bar").unwrap());
754                expected.insert("solution".to_owned(), serde_json::to_value(42).unwrap());
755                assert_eq!(other_key_parameters.fields, expected);
756            }
757            _ => {
758                panic!("Unexpected deserialization result");
759            }
760        }
761
762        // RFC 9964 Appendix A.1 JWK
763        let jwk: Jwk = serde_json::from_value(json!({
764            "kid": "T4xl70S7MT6Zeq6r9V9fPJGVn76wfnXJ21-gyo0Gu6o",
765            "kty": "AKP",
766            "alg": "ML-DSA-44",
767            "pub": "...",
768            "priv": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
769        }))
770        .expect("Could not deserialize json");
771
772        assert!(!jwk.is_supported());
773        assert!(matches!(jwk.algorithm, AlgorithmParameters::Other(_)));
774    }
775
776    #[test]
777    #[wasm_bindgen_test]
778    fn check_thumbprint() {
779        let tp = Jwk {
780            common: crate::jwk::CommonParameters { key_id: Some("2011-04-29".to_string()), ..Default::default() },
781            algorithm: AlgorithmParameters::RSA(RSAKeyParameters {
782                key_type: crate::jwk::RSAKeyType::RSA,
783                n: "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw".to_string(),
784                e: "AQAB".to_string(),
785            }),
786        }
787        .thumbprint(ThumbprintHash::SHA256)
788        .unwrap();
789
790        assert_eq!(tp.as_str(), "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs");
791    }
792
793    #[test]
794    fn check_thumbprint_bad_key() {
795        let jwk = Jwk {
796            common: CommonParameters {
797                key_algorithm: Some(KeyAlgorithm::ES256),
798                ..Default::default()
799            },
800            algorithm: AlgorithmParameters::OctetKeyPair(OctetKeyPairParameters {
801                key_type: OctetKeyPairType::OctetKeyPair,
802                curve: EllipticCurve::P256,
803                x: "".to_string(),
804            }),
805        };
806
807        assert_eq!(
808            jwk.thumbprint(ThumbprintHash::SHA256).unwrap_err().into_kind(),
809            ErrorKind::InvalidKeyFormat
810        );
811    }
812
813    #[test]
814    #[wasm_bindgen_test]
815    fn check_alg_key_alg_conversion() {
816        let pairs = [
817            (Algorithm::HS256, KeyAlgorithm::HS256),
818            (Algorithm::HS384, KeyAlgorithm::HS384),
819            (Algorithm::HS512, KeyAlgorithm::HS512),
820            (Algorithm::ES256, KeyAlgorithm::ES256),
821            (Algorithm::ES384, KeyAlgorithm::ES384),
822            (Algorithm::RS256, KeyAlgorithm::RS256),
823            (Algorithm::RS384, KeyAlgorithm::RS384),
824            (Algorithm::RS512, KeyAlgorithm::RS512),
825            (Algorithm::PS256, KeyAlgorithm::PS256),
826            (Algorithm::PS384, KeyAlgorithm::PS384),
827            (Algorithm::PS512, KeyAlgorithm::PS512),
828            (Algorithm::EdDSA, KeyAlgorithm::EdDSA),
829        ];
830
831        for (alg, k_alg) in pairs {
832            assert_eq!(KeyAlgorithm::from(alg), k_alg);
833            assert_eq!(Algorithm::try_from(k_alg), Ok(alg));
834        }
835
836        assert!(
837            Algorithm::try_from(KeyAlgorithm::RSA1_5)
838                .is_err_and(|e| *e.kind() == ErrorKind::UnsupportedAlgorithm)
839        );
840        assert!(
841            Algorithm::try_from(KeyAlgorithm::RSA_OAEP)
842                .is_err_and(|e| *e.kind() == ErrorKind::UnsupportedAlgorithm)
843        );
844        assert!(
845            Algorithm::try_from(KeyAlgorithm::RSA_OAEP_256)
846                .is_err_and(|e| *e.kind() == ErrorKind::UnsupportedAlgorithm)
847        );
848    }
849
850    #[test]
851    #[cfg(feature = "use_pem")]
852    fn check_jwk_from_decoding_key_rsa() {
853        let enc_key =
854            EncodingKey::from_rsa_pem(include_bytes!("../tests/rsa/private_rsa_key_pkcs8.pem"))
855                .unwrap();
856        let dec_key =
857            DecodingKey::from_rsa_pem(include_bytes!("../tests/rsa/public_rsa_key_pkcs8.pem"))
858                .unwrap();
859        let expected_jwk = Jwk::from_encoding_key(&enc_key, Algorithm::RS256).unwrap();
860        let jwk = Jwk::from_decoding_key(&dec_key, Some(Algorithm::RS256)).unwrap();
861        assert_eq!(jwk, expected_jwk);
862    }
863
864    #[test]
865    #[cfg(feature = "use_pem")]
866    fn check_jwk_from_decoding_key_ec() {
867        let enc_key =
868            EncodingKey::from_ec_pem(include_bytes!("../tests/ecdsa/private_ecdsa_key.pem"))
869                .unwrap();
870        let dec_key =
871            DecodingKey::from_ec_pem(include_bytes!("../tests/ecdsa/public_ecdsa_key.pem"))
872                .unwrap();
873        let expected_jwk = Jwk::from_encoding_key(&enc_key, Algorithm::ES256).unwrap();
874        let jwk = Jwk::from_decoding_key(&dec_key, Some(Algorithm::ES256)).unwrap();
875        assert_eq!(jwk, expected_jwk);
876    }
877
878    #[test]
879    #[cfg(feature = "use_pem")]
880    fn check_jwk_from_decoding_key_ed() {
881        let enc_key =
882            EncodingKey::from_ed_pem(include_bytes!("../tests/eddsa/private_ed25519_key.pem"))
883                .unwrap();
884        let dec_key =
885            DecodingKey::from_ed_pem(include_bytes!("../tests/eddsa/public_ed25519_key.pem"))
886                .unwrap();
887        let expected_jwk = Jwk::from_encoding_key(&enc_key, Algorithm::EdDSA).unwrap();
888        let jwk = Jwk::from_decoding_key(&dec_key, Some(Algorithm::EdDSA)).unwrap();
889        assert_eq!(jwk, expected_jwk);
890    }
891
892    #[test]
893    fn check_jwkset_default() {
894        #[derive(Default)]
895        struct Derived(JwkSet);
896
897        assert!(Derived::default().0.keys.is_empty());
898    }
899}