identity_jose/jwk/
key_params.rs

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