identity_jose/jwk/
key_params.rs

1// Copyright 2020-2025 IOTA Stiftung, Fondazione LINKS
2// SPDX-License-Identifier: Apache-2.0
3
4use zeroize::Zeroize;
5
6use super::BlsCurve;
7use super::JwkParamsAkp;
8use crate::error::Error;
9use crate::error::Result;
10use crate::jwk::EcCurve;
11use crate::jwk::EcxCurve;
12use crate::jwk::EdCurve;
13use crate::jwk::JwkType;
14
15/// Algorithm-specific parameters for JSON Web Keys.
16///
17/// [More Info](https://tools.ietf.org/html/rfc7518#section-6)
18#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, serde::Deserialize, serde::Serialize)]
19#[serde(untagged)]
20#[derive(Zeroize)]
21#[zeroize(drop)]
22pub enum JwkParams {
23  /// Elliptic Curve parameters.
24  Ec(JwkParamsEc),
25  /// RSA parameters.
26  Rsa(JwkParamsRsa),
27  /// Octet Sequence parameters used to represent symmetric keys.
28  Oct(JwkParamsOct),
29  /// Octet Key Pairs parameters.
30  Okp(JwkParamsOkp),
31  /// Algorithm Key Pair Type parameters
32  Akp(JwkParamsAkp),
33}
34
35impl JwkParams {
36  /// Creates new `JwkParams` with the given `kty` parameter.
37  pub const fn new(kty: JwkType) -> Self {
38    match kty {
39      JwkType::Ec => Self::Ec(JwkParamsEc::new()),
40      JwkType::Rsa => Self::Rsa(JwkParamsRsa::new()),
41      JwkType::Oct => Self::Oct(JwkParamsOct::new()),
42      JwkType::Okp => Self::Okp(JwkParamsOkp::new()),
43      JwkType::Akp => Self::Akp(JwkParamsAkp::new()),
44    }
45  }
46
47  /// Returns the key type `kty`.
48  pub const fn kty(&self) -> JwkType {
49    match self {
50      Self::Ec(inner) => inner.kty(),
51      Self::Rsa(inner) => inner.kty(),
52      Self::Oct(inner) => inner.kty(),
53      Self::Okp(inner) => inner.kty(),
54      Self::Akp(_) => JwkType::Akp,
55    }
56  }
57
58  /// Returns a clone with _all_ private key components unset. The `None` variant is returned
59  /// in the case of [`JwkParams::Oct`] as such keys are not considered public by
60  /// this library.
61  pub fn to_public(&self) -> Option<Self> {
62    match self {
63      Self::Okp(inner) => Some(Self::Okp(inner.to_public())),
64      Self::Ec(inner) => Some(Self::Ec(inner.to_public())),
65      Self::Rsa(inner) => Some(Self::Rsa(inner.to_public())),
66      Self::Oct(_) => None,
67      Self::Akp(inner) => Some(Self::Akp(inner.to_public())),
68    }
69  }
70
71  /// Removes all private key components.
72  /// In the case of [JwkParams::Oct], this method does nothing.
73  pub fn strip_private(&mut self) {
74    match self {
75      Self::Okp(inner) => inner.strip_private(),
76      Self::Ec(inner) => inner.strip_private(),
77      Self::Rsa(inner) => inner.strip_private(),
78      Self::Oct(_) => (),
79      Self::Akp(inner) => inner.strip_private(),
80    }
81  }
82
83  /// Returns this key with _all_ private key components unset.
84  /// In the case of [JwkParams::Oct], this method returns [None].
85  pub fn into_public(mut self) -> Option<Self> {
86    if matches!(self, JwkParams::Oct(_)) {
87      None
88    } else {
89      self.strip_private();
90      Some(self)
91    }
92  }
93
94  /// Returns `true` if _all_ private key components are unset, `false` otherwise.
95  pub fn is_public(&self) -> bool {
96    match self {
97      Self::Okp(value) => value.is_public(),
98      Self::Ec(value) => value.is_public(),
99      Self::Rsa(value) => value.is_public(),
100      Self::Oct(value) => value.is_public(),
101      Self::Akp(value) => value.is_public(),
102    }
103  }
104}
105
106// =============================================================================
107// Jwk Params Ec
108// =============================================================================
109
110/// Parameters for Elliptic Curve Keys.
111///
112/// [More Info](https://tools.ietf.org/html/rfc7518#section-6.2)
113#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, serde::Deserialize, serde::Serialize, Zeroize)]
114#[zeroize(drop)]
115pub struct JwkParamsEc {
116  /// Identifies the cryptographic curve used with the key.
117  ///
118  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.2.1.1)
119  pub crv: String, // Curve
120  /// The `x` coordinate for the Elliptic Curve point as a base64url-encoded
121  /// value.
122  ///
123  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.2.1.2)
124  pub x: String, // X Coordinate
125  /// The `y` coordinate for the Elliptic Curve point as a base64url-encoded
126  /// value.
127  ///
128  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.2.1.3)
129  pub y: String, // Y Coordinate
130  /// The Elliptic Curve private key as a base64url-encoded value.
131  ///
132  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.2.2.1)
133  #[serde(skip_serializing_if = "Option::is_none")]
134  pub d: Option<String>, // ECC Private Key
135}
136
137impl Default for JwkParamsEc {
138  fn default() -> Self {
139    Self::new()
140  }
141}
142
143impl JwkParamsEc {
144  /// Creates new JWK EC Params.
145  pub const fn new() -> Self {
146    Self {
147      crv: String::new(),
148      x: String::new(),
149      y: String::new(),
150      d: None,
151    }
152  }
153
154  /// Returns the key type `kty`.
155  pub const fn kty(&self) -> JwkType {
156    JwkType::Ec
157  }
158
159  /// Returns a clone with _all_ private key components unset.
160  pub fn to_public(&self) -> Self {
161    Self {
162      crv: self.crv.clone(),
163      x: self.x.clone(),
164      y: self.y.clone(),
165      d: None,
166    }
167  }
168
169  /// Returns `true` if _all_ private key components of the key are unset, `false` otherwise.
170  pub fn is_public(&self) -> bool {
171    self.d.is_none()
172  }
173
174  /// Returns `true` if _all_ private key components of the key are set, `false` otherwise.
175  pub fn is_private(&self) -> bool {
176    self.d.is_some()
177  }
178
179  /// Unsets _all_ private key components.
180  pub fn strip_private(&mut self) {
181    self.d = None;
182  }
183
184  /// Returns this key with _all_ private key components unset.
185  pub fn into_public(mut self) -> Self {
186    self.strip_private();
187    self
188  }
189
190  /// Returns the [`EcCurve`] if it is of a supported type.
191  pub fn try_ec_curve(&self) -> Result<EcCurve> {
192    match &*self.crv {
193      "P-256" => Ok(EcCurve::P256),
194      "P-384" => Ok(EcCurve::P384),
195      "P-521" => Ok(EcCurve::P521),
196      "secp256k1" => Ok(EcCurve::Secp256K1),
197      _ => Err(Error::KeyError("Ec Curve")),
198    }
199  }
200
201  /// Returns the [`BlsCurve`] if it is of a supported type.
202  pub fn try_bls_curve(&self) -> Result<BlsCurve> {
203    match &*self.crv {
204      "BLS12381G1" => Ok(BlsCurve::BLS12381G1),
205      "BLS12381G2" => Ok(BlsCurve::BLS12381G2),
206      "BLS48581G1" => Ok(BlsCurve::BLS48581G1),
207      "BLS48581G2" => Ok(BlsCurve::BLS48581G2),
208      _ => Err(Error::KeyError("BLS Curve")),
209    }
210  }
211}
212
213impl From<JwkParamsEc> for JwkParams {
214  fn from(other: JwkParamsEc) -> Self {
215    Self::Ec(other)
216  }
217}
218
219// =============================================================================
220// Jwk Params Rsa
221// =============================================================================
222
223/// Parameters for RSA Keys.
224///
225/// [More Info](https://tools.ietf.org/html/rfc7518#section-6.3)
226#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, serde::Deserialize, serde::Serialize, Zeroize)]
227#[zeroize(drop)]
228pub struct JwkParamsRsa {
229  /// The modulus value for the RSA public key as a base64urlUInt-encoded value.
230  ///
231  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.3.1.1)
232  pub n: String, // Modulus
233  /// The exponent value for the RSA public key as a base64urlUInt-encoded
234  /// value.
235  ///
236  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.3.1.2)
237  pub e: String, // Exponent
238  /// The private exponent value for the RSA private key as a
239  /// base64urlUInt-encoded value.
240  ///
241  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.3.2.1)
242  #[serde(skip_serializing_if = "Option::is_none")]
243  pub d: Option<String>, // Private Exponent
244  /// The first prime factor as a base64urlUInt-encoded value.
245  ///
246  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.3.2.2)
247  #[serde(skip_serializing_if = "Option::is_none")]
248  pub p: Option<String>, // First Prime Factor
249  /// The second prime factor as a base64urlUInt-encoded value.
250  ///
251  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.3.2.3)
252  #[serde(skip_serializing_if = "Option::is_none")]
253  pub q: Option<String>, // Second Prime Factor
254  /// The Chinese Remainder Theorem (CRT) exponent of the first factor as a
255  /// base64urlUInt-encoded value.
256  ///
257  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.3.2.4)
258  #[serde(skip_serializing_if = "Option::is_none")]
259  pub dp: Option<String>, // First Factor CRT Exponent
260  /// The CRT exponent of the second factor as a base64urlUInt-encoded value.
261  ///
262  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.3.2.5)
263  #[serde(skip_serializing_if = "Option::is_none")]
264  pub dq: Option<String>, // Second Factor CRT Exponent
265  /// The CRT coefficient of the second factor as a base64urlUInt-encoded value.
266  ///
267  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.3.2.6)
268  #[serde(skip_serializing_if = "Option::is_none")]
269  pub qi: Option<String>, // First CRT Coefficient
270  /// An array of information about any third and subsequent primes, should they
271  /// exist.
272  ///
273  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.3.2.7)
274  #[serde(skip_serializing_if = "Option::is_none")]
275  pub oth: Option<Vec<JwkParamsRsaPrime>>, // Other Primes Info
276}
277
278/// Parameters for RSA Primes
279///
280/// [More Info](https://tools.ietf.org/html/rfc7518#section-6.3.2.7)
281#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, serde::Deserialize, serde::Serialize, Zeroize)]
282#[zeroize(drop)]
283pub struct JwkParamsRsaPrime {
284  /// The value of a subsequent prime factor as a base64urlUInt-encoded value.
285  ///
286  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.3.2.7.1)
287  pub r: String, // Prime Factor
288  /// The CRT exponent of the corresponding prime factor as a
289  /// base64urlUInt-encoded value.
290  ///
291  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.3.2.7.2)
292  pub d: String, // Factor CRT Exponent
293  /// The CRT coefficient of the corresponding prime factor as a
294  /// base64urlUInt-encoded value.
295  ///
296  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.3.2.7.3)
297  pub t: String, // Factor CRT Coefficient
298}
299
300impl Default for JwkParamsRsa {
301  fn default() -> Self {
302    Self::new()
303  }
304}
305
306impl JwkParamsRsa {
307  /// Creates new JWK RSA Params.
308  pub const fn new() -> Self {
309    Self {
310      n: String::new(),
311      e: String::new(),
312      d: None,
313      p: None,
314      q: None,
315      dp: None,
316      dq: None,
317      qi: None,
318      oth: None,
319    }
320  }
321
322  /// Returns the key type `kty`.
323  pub const fn kty(&self) -> JwkType {
324    JwkType::Rsa
325  }
326
327  /// Returns a clone with _all_ private key components unset.
328  pub fn to_public(&self) -> Self {
329    Self {
330      n: self.n.clone(),
331      e: self.e.clone(),
332      d: None,
333      p: None,
334      q: None,
335      dp: None,
336      dq: None,
337      qi: None,
338      oth: None,
339    }
340  }
341
342  /// Returns `true` if _all_ private key components of the key are unset, `false` otherwise.
343  pub fn is_public(&self) -> bool {
344    self.d.is_none()
345      && self.p.is_none()
346      && self.q.is_none()
347      && self.dp.is_none()
348      && self.dq.is_none()
349      && self.qi.is_none()
350      && self.oth.is_none()
351  }
352
353  /// Returns `true` if _all_ private key components of the key are set, `false` otherwise.
354  ///
355  /// Since the `oth` parameter is optional in a private key, its presence is not checked.
356  pub fn is_private(&self) -> bool {
357    self.d.is_some()
358      && self.p.is_some()
359      && self.q.is_some()
360      && self.dp.is_some()
361      && self.dq.is_some()
362      && self.qi.is_some()
363  }
364
365  /// Unsets _all_ private key components.
366  pub fn strip_private(&mut self) {
367    self.d = None;
368    self.p = None;
369    self.q = None;
370    self.dp = None;
371    self.dq = None;
372    self.qi = None;
373  }
374
375  /// Returns this key with _all_ private key components unset.
376  pub fn into_public(mut self) -> Self {
377    self.strip_private();
378    self
379  }
380}
381
382impl From<JwkParamsRsa> for JwkParams {
383  fn from(other: JwkParamsRsa) -> Self {
384    Self::Rsa(other)
385  }
386}
387
388// =============================================================================
389// Jwk Params Oct
390// =============================================================================
391
392/// Parameters for Symmetric Keys.
393///
394/// [More Info](https://tools.ietf.org/html/rfc7518#section-6.4)
395#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, serde::Deserialize, serde::Serialize, Zeroize)]
396#[zeroize(drop)]
397pub struct JwkParamsOct {
398  /// The symmetric key as a base64url-encoded value.
399  ///
400  /// [More Info](https://tools.ietf.org/html/rfc7518#section-6.4.1)
401  pub k: String, // Key Value
402}
403
404impl Default for JwkParamsOct {
405  fn default() -> Self {
406    Self::new()
407  }
408}
409
410impl JwkParamsOct {
411  /// Creates new JWK Oct Params.
412  pub const fn new() -> Self {
413    Self { k: String::new() }
414  }
415
416  /// Returns the key type `kty`.
417  pub const fn kty(&self) -> JwkType {
418    JwkType::Oct
419  }
420
421  /// Always returns `false`. Octet sequence keys
422  /// are not considered public by this library.
423  pub fn is_public(&self) -> bool {
424    false
425  }
426}
427
428impl From<JwkParamsOct> for JwkParams {
429  fn from(other: JwkParamsOct) -> Self {
430    Self::Oct(other)
431  }
432}
433
434// =============================================================================
435// Jwk Params Okp
436// =============================================================================
437
438/// Parameters for Octet Key Pairs.
439///
440/// [More Info](https://tools.ietf.org/html/rfc8037#section-2)
441#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, serde::Deserialize, serde::Serialize, Zeroize)]
442#[zeroize(drop)]
443pub struct JwkParamsOkp {
444  /// The subtype of the key pair.
445  ///
446  /// [More Info](https://tools.ietf.org/html/rfc8037#section-2)
447  pub crv: String, // Key SubType
448  /// The public key as a base64url-encoded value.
449  ///
450  /// [More Info](https://tools.ietf.org/html/rfc8037#section-2)
451  pub x: String, // Public Key
452  /// The private key as a base64url-encoded value.
453  ///
454  /// [More Info](https://tools.ietf.org/html/rfc8037#section-2)
455  #[serde(skip_serializing_if = "Option::is_none")]
456  pub d: Option<String>, // Private Key
457}
458
459impl Default for JwkParamsOkp {
460  fn default() -> Self {
461    Self::new()
462  }
463}
464
465impl JwkParamsOkp {
466  /// Creates new JWK OKP Params.
467  pub const fn new() -> Self {
468    Self {
469      crv: String::new(),
470      x: String::new(),
471      d: None,
472    }
473  }
474
475  /// Returns the key type `kty`.
476  pub const fn kty(&self) -> JwkType {
477    JwkType::Okp
478  }
479
480  /// Returns a clone with _all_ private key components unset.
481  pub fn to_public(&self) -> Self {
482    Self {
483      crv: self.crv.clone(),
484      x: self.x.clone(),
485      d: None,
486    }
487  }
488
489  /// Returns `true` if _all_ private key components of the key are unset, `false` otherwise.
490  pub fn is_public(&self) -> bool {
491    self.d.is_none()
492  }
493
494  /// Returns `true` if _all_ private key components of the key are set, `false` otherwise.
495  pub fn is_private(&self) -> bool {
496    self.d.is_some()
497  }
498
499  /// Unsets _all_ private key components.
500  pub fn strip_private(&mut self) {
501    self.d = None;
502  }
503
504  /// Returns this key with _all_ private key components unset.
505  pub fn into_public(mut self) -> Self {
506    self.strip_private();
507    self
508  }
509
510  /// Returns the [`EdCurve`] if it is of a supported type.
511  pub fn try_ed_curve(&self) -> Result<EdCurve> {
512    match &*self.crv {
513      "Ed25519" => Ok(EdCurve::Ed25519),
514      "Ed448" => Ok(EdCurve::Ed448),
515      _ => Err(Error::KeyError("Ed Curve")),
516    }
517  }
518
519  /// Returns the [`EcxCurve`] if it is of a supported type.
520  pub fn try_ecx_curve(&self) -> Result<EcxCurve> {
521    match &*self.crv {
522      "X25519" => Ok(EcxCurve::X25519),
523      "X448" => Ok(EcxCurve::X448),
524      _ => Err(Error::KeyError("Ecx Curve")),
525    }
526  }
527}
528
529impl From<JwkParamsOkp> for JwkParams {
530  fn from(other: JwkParamsOkp) -> Self {
531    Self::Okp(other)
532  }
533}