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}