jsonwebtoken/
jwk.rs

1#![allow(missing_docs)]
2//! This crate contains types only for working JWK and JWK Sets
3//! This is only meant to be used to deal with public JWK, not generate ones.
4//! Most of the code in this file is taken from <https://github.com/lawliet89/biscuit> but
5//! tweaked to remove the private bits as it's not the goal for this crate currently.
6
7use std::{fmt, str::FromStr};
8
9use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
10
11use crate::serialization::b64_encode;
12use crate::{
13    Algorithm, EncodingKey,
14    errors::{self, Error, ErrorKind},
15};
16
17#[cfg(feature = "aws_lc_rs")]
18use aws_lc_rs::{digest, signature as aws_sig};
19#[cfg(feature = "aws_lc_rs")]
20use aws_sig::KeyPair;
21#[cfg(feature = "rust_crypto")]
22use p256::{ecdsa::SigningKey as P256SigningKey, pkcs8::DecodePrivateKey};
23#[cfg(feature = "rust_crypto")]
24use p384::ecdsa::SigningKey as P384SigningKey;
25#[cfg(feature = "rust_crypto")]
26use rsa::{RsaPrivateKey, pkcs1::DecodeRsaPrivateKey, traits::PublicKeyParts};
27#[cfg(feature = "rust_crypto")]
28use sha2::{Digest, Sha256, Sha384, Sha512};
29
30/// The intended usage of the public `KeyType`. This enum is serialized `untagged`
31#[derive(Clone, Debug, Eq, PartialEq, Hash)]
32pub enum PublicKeyUse {
33    /// Indicates a public key is meant for signature verification
34    Signature,
35    /// Indicates a public key is meant for encryption
36    Encryption,
37    /// Other usage
38    Other(String),
39}
40
41impl Serialize for PublicKeyUse {
42    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
43    where
44        S: Serializer,
45    {
46        let string = match self {
47            PublicKeyUse::Signature => "sig",
48            PublicKeyUse::Encryption => "enc",
49            PublicKeyUse::Other(other) => other,
50        };
51
52        serializer.serialize_str(string)
53    }
54}
55
56impl<'de> Deserialize<'de> for PublicKeyUse {
57    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
58    where
59        D: Deserializer<'de>,
60    {
61        struct PublicKeyUseVisitor;
62        impl de::Visitor<'_> for PublicKeyUseVisitor {
63            type Value = PublicKeyUse;
64
65            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
66                write!(formatter, "a string")
67            }
68
69            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
70            where
71                E: de::Error,
72            {
73                Ok(match v {
74                    "sig" => PublicKeyUse::Signature,
75                    "enc" => PublicKeyUse::Encryption,
76                    other => PublicKeyUse::Other(other.to_string()),
77                })
78            }
79        }
80
81        deserializer.deserialize_string(PublicKeyUseVisitor)
82    }
83}
84
85/// Operations that the key is intended to be used for. This enum is serialized `untagged`
86#[derive(Clone, Debug, Eq, PartialEq, Hash)]
87pub enum KeyOperations {
88    /// Computer digital signature or MAC
89    Sign,
90    /// Verify digital signature or MAC
91    Verify,
92    /// Encrypt content
93    Encrypt,
94    /// Decrypt content and validate decryption, if applicable
95    Decrypt,
96    /// Encrypt key
97    WrapKey,
98    /// Decrypt key and validate decryption, if applicable
99    UnwrapKey,
100    /// Derive key
101    DeriveKey,
102    /// Derive bits not to be used as a key
103    DeriveBits,
104    /// Other operation
105    Other(String),
106}
107
108impl Serialize for KeyOperations {
109    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
110    where
111        S: Serializer,
112    {
113        let string = match self {
114            KeyOperations::Sign => "sign",
115            KeyOperations::Verify => "verify",
116            KeyOperations::Encrypt => "encrypt",
117            KeyOperations::Decrypt => "decrypt",
118            KeyOperations::WrapKey => "wrapKey",
119            KeyOperations::UnwrapKey => "unwrapKey",
120            KeyOperations::DeriveKey => "deriveKey",
121            KeyOperations::DeriveBits => "deriveBits",
122            KeyOperations::Other(other) => other,
123        };
124
125        serializer.serialize_str(string)
126    }
127}
128
129impl<'de> Deserialize<'de> for KeyOperations {
130    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
131    where
132        D: Deserializer<'de>,
133    {
134        struct KeyOperationsVisitor;
135        impl de::Visitor<'_> for KeyOperationsVisitor {
136            type Value = KeyOperations;
137
138            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
139                write!(formatter, "a string")
140            }
141
142            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
143            where
144                E: de::Error,
145            {
146                Ok(match v {
147                    "sign" => KeyOperations::Sign,
148                    "verify" => KeyOperations::Verify,
149                    "encrypt" => KeyOperations::Encrypt,
150                    "decrypt" => KeyOperations::Decrypt,
151                    "wrapKey" => KeyOperations::WrapKey,
152                    "unwrapKey" => KeyOperations::UnwrapKey,
153                    "deriveKey" => KeyOperations::DeriveKey,
154                    "deriveBits" => KeyOperations::DeriveBits,
155                    other => KeyOperations::Other(other.to_string()),
156                })
157            }
158        }
159
160        deserializer.deserialize_string(KeyOperationsVisitor)
161    }
162}
163
164/// The algorithms of the keys
165#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
166#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize)]
167pub enum KeyAlgorithm {
168    /// HMAC using SHA-256
169    HS256,
170    /// HMAC using SHA-384
171    HS384,
172    /// HMAC using SHA-512
173    HS512,
174
175    /// ECDSA using SHA-256
176    ES256,
177    /// ECDSA using SHA-384
178    ES384,
179
180    /// RSASSA-PKCS1-v1_5 using SHA-256
181    RS256,
182    /// RSASSA-PKCS1-v1_5 using SHA-384
183    RS384,
184    /// RSASSA-PKCS1-v1_5 using SHA-512
185    RS512,
186
187    /// RSASSA-PSS using SHA-256
188    PS256,
189    /// RSASSA-PSS using SHA-384
190    PS384,
191    /// RSASSA-PSS using SHA-512
192    PS512,
193
194    /// Edwards-curve Digital Signature Algorithm (EdDSA)
195    EdDSA,
196
197    /// RSAES-PKCS1-V1_5
198    RSA1_5,
199
200    /// RSAES-OAEP using SHA-1
201    #[serde(rename = "RSA-OAEP")]
202    RSA_OAEP,
203
204    /// RSAES-OAEP-256 using SHA-2
205    #[serde(rename = "RSA-OAEP-256")]
206    RSA_OAEP_256,
207
208    /// Catch-All for when the key algorithm can not be determined or is not supported
209    #[serde(other)]
210    UNKNOWN_ALGORITHM,
211}
212
213impl FromStr for KeyAlgorithm {
214    type Err = Error;
215    fn from_str(s: &str) -> errors::Result<Self> {
216        match s {
217            "HS256" => Ok(KeyAlgorithm::HS256),
218            "HS384" => Ok(KeyAlgorithm::HS384),
219            "HS512" => Ok(KeyAlgorithm::HS512),
220            "ES256" => Ok(KeyAlgorithm::ES256),
221            "ES384" => Ok(KeyAlgorithm::ES384),
222            "RS256" => Ok(KeyAlgorithm::RS256),
223            "RS384" => Ok(KeyAlgorithm::RS384),
224            "PS256" => Ok(KeyAlgorithm::PS256),
225            "PS384" => Ok(KeyAlgorithm::PS384),
226            "PS512" => Ok(KeyAlgorithm::PS512),
227            "RS512" => Ok(KeyAlgorithm::RS512),
228            "EdDSA" => Ok(KeyAlgorithm::EdDSA),
229            "RSA1_5" => Ok(KeyAlgorithm::RSA1_5),
230            "RSA-OAEP" => Ok(KeyAlgorithm::RSA_OAEP),
231            "RSA-OAEP-256" => Ok(KeyAlgorithm::RSA_OAEP_256),
232            _ => Err(ErrorKind::InvalidAlgorithmName.into()),
233        }
234    }
235}
236
237impl fmt::Display for KeyAlgorithm {
238    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
239        write!(f, "{:?}", self)
240    }
241}
242
243impl KeyAlgorithm {
244    fn to_algorithm(self) -> errors::Result<Algorithm> {
245        Algorithm::from_str(self.to_string().as_str())
246    }
247}
248
249/// Common JWK parameters
250#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Default, Hash)]
251pub struct CommonParameters {
252    /// The intended use of the public key. Should not be specified with `key_operations`.
253    /// See sections 4.2 and 4.3 of [RFC7517](https://tools.ietf.org/html/rfc7517).
254    #[serde(rename = "use", skip_serializing_if = "Option::is_none", default)]
255    pub public_key_use: Option<PublicKeyUse>,
256
257    /// The "key_ops" (key operations) parameter identifies the operation(s)
258    /// for which the key is intended to be used.  The "key_ops" parameter is
259    /// intended for use cases in which public, private, or symmetric keys
260    /// may be present.
261    /// Should not be specified with `public_key_use`.
262    /// See sections 4.2 and 4.3 of [RFC7517](https://tools.ietf.org/html/rfc7517).
263    #[serde(rename = "key_ops", skip_serializing_if = "Option::is_none", default)]
264    pub key_operations: Option<Vec<KeyOperations>>,
265
266    /// The algorithm keys intended for use with the key.
267    #[serde(rename = "alg", skip_serializing_if = "Option::is_none", default)]
268    pub key_algorithm: Option<KeyAlgorithm>,
269
270    /// The case sensitive Key ID for the key
271    #[serde(rename = "kid", skip_serializing_if = "Option::is_none", default)]
272    pub key_id: Option<String>,
273
274    /// X.509 Public key certificate URL. This is currently not implemented (correctly).
275    ///
276    /// Serialized to `x5u`.
277    #[serde(rename = "x5u", skip_serializing_if = "Option::is_none")]
278    pub x509_url: Option<String>,
279
280    /// X.509 public key certificate chain. This is currently not implemented (correctly).
281    ///
282    /// Serialized to `x5c`.
283    #[serde(rename = "x5c", skip_serializing_if = "Option::is_none")]
284    pub x509_chain: Option<Vec<String>>,
285
286    /// X.509 Certificate SHA1 thumbprint. This is currently not implemented (correctly).
287    ///
288    /// Serialized to `x5t`.
289    #[serde(rename = "x5t", skip_serializing_if = "Option::is_none")]
290    pub x509_sha1_fingerprint: Option<String>,
291
292    /// X.509 Certificate SHA256 thumbprint. This is currently not implemented (correctly).
293    ///
294    /// Serialized to `x5t#S256`.
295    #[serde(rename = "x5t#S256", skip_serializing_if = "Option::is_none")]
296    pub x509_sha256_fingerprint: Option<String>,
297}
298
299/// Key type value for an Elliptic Curve Key.
300/// This single value enum is a workaround for Rust not supporting associated constants.
301#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Hash)]
302pub enum EllipticCurveKeyType {
303    /// Key type value for an Elliptic Curve Key.
304    #[default]
305    EC,
306}
307
308/// Type of cryptographic curve used by a key. This is defined in
309/// [RFC 7518 #7.6](https://tools.ietf.org/html/rfc7518#section-7.6)
310#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Hash)]
311pub enum EllipticCurve {
312    /// P-256 curve
313    #[serde(rename = "P-256")]
314    #[default]
315    P256,
316    /// P-384 curve
317    #[serde(rename = "P-384")]
318    P384,
319    /// P-521 curve -- unsupported by `ring`.
320    #[serde(rename = "P-521")]
321    P521,
322    /// Ed25519 curve
323    #[serde(rename = "Ed25519")]
324    Ed25519,
325}
326
327/// Parameters for an Elliptic Curve Key
328#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default, Hash)]
329pub struct EllipticCurveKeyParameters {
330    /// Key type value for an Elliptic Curve Key.
331    #[serde(rename = "kty")]
332    pub key_type: EllipticCurveKeyType,
333    /// The "crv" (curve) parameter identifies the cryptographic curve used
334    /// with the key.
335    #[serde(rename = "crv")]
336    pub curve: EllipticCurve,
337    /// The "x" (x coordinate) parameter contains the x coordinate for the
338    /// Elliptic Curve point.
339    pub x: String,
340    /// The "y" (y coordinate) parameter contains the y coordinate for the
341    /// Elliptic Curve point.
342    pub y: String,
343}
344
345/// Key type value for an RSA Key.
346/// This single value enum is a workaround for Rust not supporting associated constants.
347#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Hash)]
348pub enum RSAKeyType {
349    /// Key type value for an RSA Key.
350    #[default]
351    RSA,
352}
353
354/// Parameters for a RSA Key
355#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default, Hash)]
356pub struct RSAKeyParameters {
357    /// Key type value for a RSA Key
358    #[serde(rename = "kty")]
359    pub key_type: RSAKeyType,
360
361    /// The "n" (modulus) parameter contains the modulus value for the RSA
362    /// public key.
363    pub n: String,
364
365    /// The "e" (exponent) parameter contains the exponent value for the RSA
366    /// public key.
367    pub e: String,
368}
369
370/// Key type value for an Octet symmetric key.
371/// This single value enum is a workaround for Rust not supporting associated constants.
372#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Hash)]
373pub enum OctetKeyType {
374    /// Key type value for an Octet symmetric key.
375    #[serde(rename = "oct")]
376    #[default]
377    Octet,
378}
379
380/// Parameters for an Octet Key
381#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default, Hash)]
382pub struct OctetKeyParameters {
383    /// Key type value for an Octet Key
384    #[serde(rename = "kty")]
385    pub key_type: OctetKeyType,
386    /// The octet key value
387    #[serde(rename = "k")]
388    pub value: String,
389}
390
391/// Key type value for an Octet Key Pair.
392/// This single value enum is a workaround for Rust not supporting associated constants.
393#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Hash)]
394pub enum OctetKeyPairType {
395    /// Key type value for an Octet Key Pair.
396    #[serde(rename = "OKP")]
397    #[default]
398    OctetKeyPair,
399}
400
401/// Parameters for an Octet Key Pair
402#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default, Hash)]
403pub struct OctetKeyPairParameters {
404    /// Key type value for an Octet Key Pair
405    #[serde(rename = "kty")]
406    pub key_type: OctetKeyPairType,
407    /// The "crv" (curve) parameter identifies the cryptographic curve used
408    /// with the key.
409    #[serde(rename = "crv")]
410    pub curve: EllipticCurve,
411    /// The "x" parameter contains the base64 encoded public key
412    pub x: String,
413}
414
415/// Algorithm specific parameters
416#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)]
417#[serde(untagged)]
418pub enum AlgorithmParameters {
419    EllipticCurve(EllipticCurveKeyParameters),
420    RSA(RSAKeyParameters),
421    OctetKey(OctetKeyParameters),
422    OctetKeyPair(OctetKeyPairParameters),
423}
424
425/// The function to use to hash the intermediate thumbprint data.
426#[derive(Debug, Clone, Eq, PartialEq)]
427pub enum ThumbprintHash {
428    SHA256,
429    SHA384,
430    SHA512,
431}
432
433#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)]
434pub struct Jwk {
435    #[serde(flatten)]
436    pub common: CommonParameters,
437    /// Key algorithm specific parameters
438    #[serde(flatten)]
439    pub algorithm: AlgorithmParameters,
440}
441
442#[cfg(feature = "aws_lc_rs")]
443fn extract_rsa_public_key_components(key_content: &[u8]) -> errors::Result<(Vec<u8>, Vec<u8>)> {
444    let key_pair = aws_sig::RsaKeyPair::from_der(key_content)
445        .map_err(|e| ErrorKind::InvalidRsaKey(e.to_string()))?;
446    let public = key_pair.public_key();
447    let components = aws_sig::RsaPublicKeyComponents::<Vec<u8>>::from(public);
448    Ok((components.n, components.e))
449}
450
451#[cfg(feature = "rust_crypto")]
452fn extract_rsa_public_key_components(key_content: &[u8]) -> errors::Result<(Vec<u8>, Vec<u8>)> {
453    let private_key = RsaPrivateKey::from_pkcs1_der(key_content)
454        .map_err(|e| ErrorKind::InvalidRsaKey(e.to_string()))?;
455    let public_key = private_key.to_public_key();
456    Ok((public_key.n().to_bytes_be(), public_key.e().to_bytes_be()))
457}
458
459#[cfg(feature = "aws_lc_rs")]
460fn extract_ec_public_key_coordinates(
461    key_content: &[u8],
462    alg: Algorithm,
463) -> errors::Result<(EllipticCurve, Vec<u8>, Vec<u8>)> {
464    use aws_lc_rs::signature::{
465        ECDSA_P256_SHA256_FIXED_SIGNING, ECDSA_P384_SHA384_FIXED_SIGNING, EcdsaKeyPair,
466    };
467
468    let (signing_alg, curve, pub_elem_bytes) = match alg {
469        Algorithm::ES256 => (&ECDSA_P256_SHA256_FIXED_SIGNING, EllipticCurve::P256, 32),
470        Algorithm::ES384 => (&ECDSA_P384_SHA384_FIXED_SIGNING, EllipticCurve::P384, 48),
471        _ => return Err(ErrorKind::InvalidEcdsaKey.into()),
472    };
473
474    let key_pair = EcdsaKeyPair::from_pkcs8(signing_alg, key_content)
475        .map_err(|_| ErrorKind::InvalidEcdsaKey)?;
476
477    let pub_bytes = key_pair.public_key().as_ref();
478    if pub_bytes[0] != 4 {
479        return Err(ErrorKind::InvalidEcdsaKey.into());
480    }
481
482    let (x, y) = pub_bytes[1..].split_at(pub_elem_bytes);
483    Ok((curve, x.to_vec(), y.to_vec()))
484}
485
486#[cfg(feature = "rust_crypto")]
487fn extract_ec_public_key_coordinates(
488    key_content: &[u8],
489    alg: Algorithm,
490) -> errors::Result<(EllipticCurve, Vec<u8>, Vec<u8>)> {
491    match alg {
492        Algorithm::ES256 => {
493            let signing_key = P256SigningKey::from_pkcs8_der(key_content)
494                .map_err(|_| ErrorKind::InvalidEcdsaKey)?;
495            let public_key = signing_key.verifying_key();
496            let encoded = public_key.to_encoded_point(false);
497            match encoded.coordinates() {
498                p256::elliptic_curve::sec1::Coordinates::Uncompressed { x, y } => {
499                    Ok((EllipticCurve::P256, x.to_vec(), y.to_vec()))
500                }
501                _ => Err(ErrorKind::InvalidEcdsaKey.into()),
502            }
503        }
504        Algorithm::ES384 => {
505            let signing_key = P384SigningKey::from_pkcs8_der(key_content)
506                .map_err(|_| ErrorKind::InvalidEcdsaKey)?;
507            let public_key = signing_key.verifying_key();
508            let encoded = public_key.to_encoded_point(false);
509            match encoded.coordinates() {
510                p384::elliptic_curve::sec1::Coordinates::Uncompressed { x, y } => {
511                    Ok((EllipticCurve::P384, x.to_vec(), y.to_vec()))
512                }
513                _ => Err(ErrorKind::InvalidEcdsaKey.into()),
514            }
515        }
516        _ => Err(ErrorKind::InvalidEcdsaKey.into()),
517    }
518}
519
520#[cfg(feature = "aws_lc_rs")]
521fn compute_digest(data: &[u8], hash_function: ThumbprintHash) -> Vec<u8> {
522    let algorithm = match hash_function {
523        ThumbprintHash::SHA256 => &digest::SHA256,
524        ThumbprintHash::SHA384 => &digest::SHA384,
525        ThumbprintHash::SHA512 => &digest::SHA512,
526    };
527    digest::digest(algorithm, data).as_ref().to_vec()
528}
529
530#[cfg(feature = "rust_crypto")]
531fn compute_digest(data: &[u8], hash_function: ThumbprintHash) -> Vec<u8> {
532    match hash_function {
533        ThumbprintHash::SHA256 => Sha256::digest(data).to_vec(),
534        ThumbprintHash::SHA384 => Sha384::digest(data).to_vec(),
535        ThumbprintHash::SHA512 => Sha512::digest(data).to_vec(),
536    }
537}
538
539impl Jwk {
540    /// Find whether the Algorithm is implemented and supported
541    pub fn is_supported(&self) -> bool {
542        match self.common.key_algorithm {
543            Some(alg) => alg.to_algorithm().is_ok(),
544            _ => false,
545        }
546    }
547    pub fn from_encoding_key(key: &EncodingKey, alg: Algorithm) -> crate::errors::Result<Self> {
548        Ok(Self {
549            common: CommonParameters {
550                key_algorithm: Some(match alg {
551                    Algorithm::HS256 => KeyAlgorithm::HS256,
552                    Algorithm::HS384 => KeyAlgorithm::HS384,
553                    Algorithm::HS512 => KeyAlgorithm::HS512,
554                    Algorithm::ES256 => KeyAlgorithm::ES256,
555                    Algorithm::ES384 => KeyAlgorithm::ES384,
556                    Algorithm::RS256 => KeyAlgorithm::RS256,
557                    Algorithm::RS384 => KeyAlgorithm::RS384,
558                    Algorithm::RS512 => KeyAlgorithm::RS512,
559                    Algorithm::PS256 => KeyAlgorithm::PS256,
560                    Algorithm::PS384 => KeyAlgorithm::PS384,
561                    Algorithm::PS512 => KeyAlgorithm::PS512,
562                    Algorithm::EdDSA => KeyAlgorithm::EdDSA,
563                }),
564                ..Default::default()
565            },
566            algorithm: match key.family {
567                crate::algorithms::AlgorithmFamily::Hmac => {
568                    AlgorithmParameters::OctetKey(OctetKeyParameters {
569                        key_type: OctetKeyType::Octet,
570                        value: b64_encode(&key.content),
571                    })
572                }
573                crate::algorithms::AlgorithmFamily::Rsa => {
574                    let (n, e) = extract_rsa_public_key_components(&key.content)?;
575                    AlgorithmParameters::RSA(RSAKeyParameters {
576                        key_type: RSAKeyType::RSA,
577                        n: b64_encode(n),
578                        e: b64_encode(e),
579                    })
580                }
581                crate::algorithms::AlgorithmFamily::Ec => {
582                    let (curve, x, y) = extract_ec_public_key_coordinates(&key.content, alg)?;
583                    AlgorithmParameters::EllipticCurve(EllipticCurveKeyParameters {
584                        key_type: EllipticCurveKeyType::EC,
585                        curve,
586                        x: b64_encode(x),
587                        y: b64_encode(y),
588                    })
589                }
590                crate::algorithms::AlgorithmFamily::Ed => {
591                    unimplemented!();
592                }
593            },
594        })
595    }
596
597    /// Compute the thumbprint of the JWK.
598    ///
599    /// Per [RFC-7638](https://datatracker.ietf.org/doc/html/rfc7638)
600    pub fn thumbprint(&self, hash_function: ThumbprintHash) -> String {
601        let pre = match &self.algorithm {
602            AlgorithmParameters::EllipticCurve(a) => match a.curve {
603                EllipticCurve::P256 | EllipticCurve::P384 | EllipticCurve::P521 => {
604                    format!(
605                        r#"{{"crv":{},"kty":{},"x":"{}","y":"{}"}}"#,
606                        serde_json::to_string(&a.curve).unwrap(),
607                        serde_json::to_string(&a.key_type).unwrap(),
608                        a.x,
609                        a.y,
610                    )
611                }
612                EllipticCurve::Ed25519 => panic!("EllipticCurve can't contain this curve type"),
613            },
614            AlgorithmParameters::RSA(a) => {
615                format!(
616                    r#"{{"e":"{}","kty":{},"n":"{}"}}"#,
617                    a.e,
618                    serde_json::to_string(&a.key_type).unwrap(),
619                    a.n,
620                )
621            }
622            AlgorithmParameters::OctetKey(a) => {
623                format!(
624                    r#"{{"k":"{}","kty":{}}}"#,
625                    a.value,
626                    serde_json::to_string(&a.key_type).unwrap()
627                )
628            }
629            AlgorithmParameters::OctetKeyPair(a) => match a.curve {
630                EllipticCurve::P256 | EllipticCurve::P384 | EllipticCurve::P521 => {
631                    panic!("OctetKeyPair can't contain this curve type")
632                }
633                EllipticCurve::Ed25519 => {
634                    format!(
635                        r#"{{crv:{},"kty":{},"x":"{}"}}"#,
636                        serde_json::to_string(&a.curve).unwrap(),
637                        serde_json::to_string(&a.key_type).unwrap(),
638                        a.x,
639                    )
640                }
641            },
642        };
643        b64_encode(compute_digest(pre.as_bytes(), hash_function))
644    }
645}
646
647/// A JWK set
648#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
649pub struct JwkSet {
650    pub keys: Vec<Jwk>,
651}
652
653impl JwkSet {
654    /// Find the key in the set that matches the given key id, if any.
655    pub fn find(&self, kid: &str) -> Option<&Jwk> {
656        self.keys
657            .iter()
658            .find(|jwk| jwk.common.key_id.is_some() && jwk.common.key_id.as_ref().unwrap() == kid)
659    }
660}
661
662#[cfg(test)]
663mod tests {
664    use serde_json::json;
665    use wasm_bindgen_test::wasm_bindgen_test;
666
667    use crate::Algorithm;
668    use crate::jwk::{
669        AlgorithmParameters, Jwk, JwkSet, KeyAlgorithm, OctetKeyType, RSAKeyParameters,
670        ThumbprintHash,
671    };
672    use crate::serialization::b64_encode;
673
674    #[test]
675    #[wasm_bindgen_test]
676    fn check_hs256() {
677        let key = b64_encode("abcdefghijklmnopqrstuvwxyz012345");
678        let jwks_json = json!({
679            "keys": [
680                {
681                    "kty": "oct",
682                    "alg": "HS256",
683                    "kid": "abc123",
684                    "k": key
685                }
686            ]
687        });
688
689        let set: JwkSet = serde_json::from_value(jwks_json).expect("Failed HS256 check");
690        assert_eq!(set.keys.len(), 1);
691        let key = &set.keys[0];
692        assert_eq!(key.common.key_id, Some("abc123".to_string()));
693        let algorithm = key.common.key_algorithm.unwrap().to_algorithm().unwrap();
694        assert_eq!(algorithm, Algorithm::HS256);
695
696        match &key.algorithm {
697            AlgorithmParameters::OctetKey(key) => {
698                assert_eq!(key.key_type, OctetKeyType::Octet);
699                assert_eq!(key.value, key.value)
700            }
701            _ => panic!("Unexpected key algorithm"),
702        }
703    }
704
705    #[test]
706    fn deserialize_unknown_key_algorithm() {
707        let key_alg_json = json!("");
708        let key_alg_result: KeyAlgorithm =
709            serde_json::from_value(key_alg_json).expect("Could not deserialize json");
710        assert_eq!(key_alg_result, KeyAlgorithm::UNKNOWN_ALGORITHM);
711    }
712
713    #[test]
714    #[wasm_bindgen_test]
715    fn check_thumbprint() {
716        let tp = Jwk {
717            common: crate::jwk::CommonParameters { key_id: Some("2011-04-29".to_string()), ..Default::default() },
718            algorithm: AlgorithmParameters::RSA(RSAKeyParameters {
719                key_type: crate::jwk::RSAKeyType::RSA,
720                n: "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw".to_string(),
721                e: "AQAB".to_string(),
722            }),
723        }
724            .thumbprint(ThumbprintHash::SHA256);
725        assert_eq!(tp.as_str(), "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs");
726    }
727}