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