1use crypto::hashes::sha::SHA256;
5use crypto::hashes::sha::SHA256_LEN;
6use identity_core::common::Url;
7use zeroize::Zeroize;
8
9use crate::error::Error;
10use crate::error::Result;
11use crate::jwk::EcCurve;
12use crate::jwk::EcxCurve;
13use crate::jwk::EdCurve;
14use crate::jwk::JwkOperation;
15use crate::jwk::JwkParams;
16use crate::jwk::JwkParamsEc;
17use crate::jwk::JwkParamsOct;
18use crate::jwk::JwkParamsOkp;
19use crate::jwk::JwkParamsRsa;
20use crate::jwk::JwkType;
21use crate::jwk::JwkUse;
22use crate::jwu::encode_b64;
23
24pub type JwkThumbprintSha256 = [u8; SHA256_LEN];
26
27#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
31pub struct Jwk {
32 pub(super) kty: JwkType,
38 #[serde(rename = "use", skip_serializing_if = "Option::is_none")]
44 pub(super) use_: Option<JwkUse>,
45 #[serde(skip_serializing_if = "Option::is_none")]
51 pub(super) key_ops: Option<Vec<JwkOperation>>,
52 #[serde(skip_serializing_if = "Option::is_none")]
58 pub(super) alg: Option<String>,
59 #[serde(skip_serializing_if = "Option::is_none")]
65 pub(super) kid: Option<String>,
66 #[serde(skip_serializing_if = "Option::is_none")]
73 pub(super) x5u: Option<Url>,
74 #[serde(skip_serializing_if = "Option::is_none")]
80 pub(super) x5c: Option<Vec<String>>,
81 #[serde(skip_serializing_if = "Option::is_none")]
88 pub(super) x5t: Option<String>,
89 #[serde(rename = "x5t#S256", skip_serializing_if = "Option::is_none")]
96 pub(super) x5t_s256: Option<String>,
97 #[serde(flatten)]
101 pub(super) params: JwkParams,
102}
103
104impl Jwk {
105 pub const fn new(kty: JwkType) -> Self {
107 Self {
108 kty,
109 use_: None,
110 key_ops: None,
111 alg: None,
112 kid: None,
113 x5u: None,
114 x5c: None,
115 x5t: None,
116 x5t_s256: None,
117 params: JwkParams::new(kty),
118 }
119 }
120
121 pub fn from_params(params: impl Into<JwkParams>) -> Self {
123 let params: JwkParams = params.into();
124
125 Self {
126 kty: params.kty(),
127 use_: None,
128 key_ops: None,
129 alg: None,
130 kid: None,
131 x5u: None,
132 x5c: None,
133 x5t: None,
134 x5t_s256: None,
135 params,
136 }
137 }
138
139 pub fn kty(&self) -> JwkType {
141 self.kty
142 }
143
144 pub fn set_kty(&mut self, value: impl Into<JwkType>) {
148 self.kty = value.into();
149 self.params = JwkParams::new(self.kty);
150 }
151
152 pub fn use_(&self) -> Option<JwkUse> {
154 self.use_
155 }
156
157 pub fn set_use(&mut self, value: impl Into<JwkUse>) {
159 self.use_ = Some(value.into());
160 }
161
162 pub fn key_ops(&self) -> Option<&[JwkOperation]> {
164 self.key_ops.as_deref()
165 }
166
167 pub fn set_key_ops(&mut self, value: impl IntoIterator<Item = impl Into<JwkOperation>>) {
169 self.key_ops = Some(value.into_iter().map(Into::into).collect());
170 }
171
172 pub fn alg(&self) -> Option<&str> {
174 self.alg.as_deref()
175 }
176
177 pub fn set_alg(&mut self, value: impl Into<String>) {
179 self.alg = Some(value.into());
180 }
181
182 pub fn kid(&self) -> Option<&str> {
184 self.kid.as_deref()
185 }
186
187 pub fn set_kid(&mut self, value: impl Into<String>) {
189 self.kid = Some(value.into());
190 }
191
192 pub fn x5u(&self) -> Option<&Url> {
194 self.x5u.as_ref()
195 }
196
197 pub fn set_x5u(&mut self, value: impl Into<Url>) {
199 self.x5u = Some(value.into());
200 }
201
202 pub fn x5c(&self) -> Option<&[String]> {
204 self.x5c.as_deref()
205 }
206
207 pub fn set_x5c(&mut self, value: impl IntoIterator<Item = impl Into<String>>) {
209 self.x5c = Some(value.into_iter().map(Into::into).collect());
210 }
211
212 pub fn x5t(&self) -> Option<&str> {
215 self.x5t.as_deref()
216 }
217
218 pub fn set_x5t(&mut self, value: impl Into<String>) {
220 self.x5t = Some(value.into());
221 }
222
223 pub fn x5t_s256(&self) -> Option<&str> {
226 self.x5t_s256.as_deref()
227 }
228
229 pub fn set_x5t_s256(&mut self, value: impl Into<String>) {
232 self.x5t_s256 = Some(value.into());
233 }
234
235 pub fn params(&self) -> &JwkParams {
237 &self.params
238 }
239
240 pub fn params_mut(&mut self) -> &mut JwkParams {
242 &mut self.params
243 }
244
245 pub fn set_params(&mut self, params: impl Into<JwkParams>) -> Result<()> {
251 match (self.kty, params.into()) {
252 (JwkType::Ec, value @ JwkParams::Ec(_)) => {
253 self.set_params_unchecked(value);
254 }
255 (JwkType::Rsa, value @ JwkParams::Rsa(_)) => {
256 self.set_params_unchecked(value);
257 }
258 (JwkType::Oct, value @ JwkParams::Oct(_)) => {
259 self.set_params_unchecked(value);
260 }
261 (JwkType::Okp, value @ JwkParams::Okp(_)) => {
262 self.set_params_unchecked(value);
263 }
264 (_, _) => {
265 return Err(Error::InvalidParam("`params` type does not match `kty`"));
266 }
267 }
268 Ok(())
269 }
270
271 pub fn set_params_unchecked(&mut self, value: impl Into<JwkParams>) {
275 self.params = value.into();
276 }
277
278 pub fn try_ec_params(&self) -> Result<&JwkParamsEc> {
280 match self.params() {
281 JwkParams::Ec(params) => Ok(params),
282 _ => Err(Error::KeyError("Ec")),
283 }
284 }
285
286 pub fn try_ec_params_mut(&mut self) -> Result<&mut JwkParamsEc> {
288 match self.params_mut() {
289 JwkParams::Ec(params) => Ok(params),
290 _ => Err(Error::KeyError("Ec")),
291 }
292 }
293
294 pub fn try_rsa_params(&self) -> Result<&JwkParamsRsa> {
296 match self.params() {
297 JwkParams::Rsa(params) => Ok(params),
298 _ => Err(Error::KeyError("Rsa")),
299 }
300 }
301
302 pub fn try_rsa_params_mut(&mut self) -> Result<&mut JwkParamsRsa> {
304 match self.params_mut() {
305 JwkParams::Rsa(params) => Ok(params),
306 _ => Err(Error::KeyError("Rsa")),
307 }
308 }
309
310 pub fn try_oct_params(&self) -> Result<&JwkParamsOct> {
312 match self.params() {
313 JwkParams::Oct(params) => Ok(params),
314 _ => Err(Error::KeyError("Oct")),
315 }
316 }
317
318 pub fn try_oct_params_mut(&mut self) -> Result<&mut JwkParamsOct> {
320 match self.params_mut() {
321 JwkParams::Oct(params) => Ok(params),
322 _ => Err(Error::KeyError("Oct")),
323 }
324 }
325
326 pub fn try_okp_params(&self) -> Result<&JwkParamsOkp> {
328 match self.params() {
329 JwkParams::Okp(params) => Ok(params),
330 _ => Err(Error::KeyError("Okp")),
331 }
332 }
333
334 pub fn try_okp_params_mut(&mut self) -> Result<&mut JwkParamsOkp> {
336 match self.params_mut() {
337 JwkParams::Okp(params) => Ok(params),
338 _ => Err(Error::KeyError("Okp")),
339 }
340 }
341
342 pub fn thumbprint_sha256_b64(&self) -> String {
352 encode_b64(self.thumbprint_sha256())
353 }
354
355 pub fn thumbprint_sha256(&self) -> JwkThumbprintSha256 {
361 let json: String = self.thumbprint_hash_input();
362
363 let mut out: JwkThumbprintSha256 = Default::default();
364
365 SHA256(json.as_bytes(), &mut out);
366
367 out
368 }
369
370 pub fn thumbprint_hash_input(&self) -> String {
374 let kty: &str = self.kty.name();
375
376 match self.params() {
377 JwkParams::Ec(JwkParamsEc { crv, x, y, .. }) => {
378 format!(r#"{{"crv":"{crv}","kty":"{kty}","x":"{x}","y":"{y}"}}"#)
379 }
380 JwkParams::Rsa(JwkParamsRsa { e, n, .. }) => {
381 format!(r#"{{"e":"{e}","kty":"{kty}","n":"{n}"}}"#)
382 }
383 JwkParams::Oct(JwkParamsOct { k }) => {
384 format!(r#"{{"k":"{k}","kty":"{kty}"}}"#)
385 }
386 JwkParams::Okp(JwkParamsOkp { crv, x, .. }) => {
388 format!(r#"{{"crv":"{crv}","kty":"{kty}","x":"{x}"}}"#)
389 }
390 }
391 }
392
393 pub fn check_alg(&self, expected: impl AsRef<str>) -> Result<()> {
399 match self.alg() {
400 Some(value) if value == expected.as_ref() => Ok(()),
401 Some(_) => Err(Error::InvalidClaim("alg")),
402 None => Ok(()),
403 }
404 }
405
406 pub fn try_ec_curve(&self) -> Result<EcCurve> {
408 match self.params() {
409 JwkParams::Ec(inner) => inner.try_ec_curve(),
410 _ => Err(Error::KeyError("Ec Curve")),
411 }
412 }
413
414 pub fn try_ed_curve(&self) -> Result<EdCurve> {
416 match self.params() {
417 JwkParams::Okp(inner) => inner.try_ed_curve(),
418 _ => Err(Error::KeyError("Ed Curve")),
419 }
420 }
421
422 pub fn try_ecx_curve(&self) -> Result<EcxCurve> {
424 match self.params() {
425 JwkParams::Okp(inner) => inner.try_ecx_curve(),
426 _ => Err(Error::KeyError("Ecx Curve")),
427 }
428 }
429
430 pub fn is_public(&self) -> bool {
432 self.params.is_public()
433 }
434
435 pub fn is_private(&self) -> bool {
437 match self.params() {
438 JwkParams::Ec(params) => params.is_private(),
439 JwkParams::Rsa(params) => params.is_private(),
440 JwkParams::Oct(_) => true,
441 JwkParams::Okp(params) => params.is_private(),
442 }
443 }
444
445 pub fn to_public(&self) -> Option<Jwk> {
449 let mut public: Jwk = Jwk::from_params(self.params().to_public()?);
450
451 if let Some(value) = self.use_() {
452 public.set_use(value);
453 }
454
455 if let Some(value) = self.key_ops() {
456 public.set_key_ops(value.iter().map(|op| op.invert()));
457 }
458
459 if let Some(value) = self.alg() {
460 public.set_alg(value);
461 }
462
463 if let Some(value) = self.kid() {
464 public.set_kid(value);
465 }
466
467 Some(public)
468 }
469}
470
471impl Zeroize for Jwk {
472 fn zeroize(&mut self) {
473 self.params.zeroize();
474 }
475}
476
477impl Drop for Jwk {
478 fn drop(&mut self) {
479 self.zeroize();
480 }
481}