1use ct_codecs::{Base64UrlSafeNoPadding, Decoder, Encoder};
7use p256::ecdh::EphemeralSecret;
8use p256::elliptic_curve::sec1::{FromSec1Point, ToSec1Point};
9use p256::elliptic_curve::Generate as _;
10use p256::pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePrivateKey, EncodePublicKey};
11use p256::{NonZeroScalar, PublicKey, Sec1Point, SecretKey};
12use rand::rng;
13use serde::{de::DeserializeOwned, Serialize};
14use serde_json::json;
15use zeroize::Zeroize;
16
17use crate::algorithms::jwe::aes_kw::{A128KWKey, A256KWKey};
18use crate::claims::*;
19use crate::error::*;
20use crate::jwe_header::JWEHeader;
21use crate::jwe_token::{DecryptionOptions, EncryptionOptions, JWEToken, JWETokenMetadata};
22
23fn concat_kdf(
25 shared_secret: &[u8],
26 key_len: usize,
27 alg: &str,
28 apu: Option<&[u8]>,
29 apv: Option<&[u8]>,
30) -> Vec<u8> {
31 use hmac_sha256::Hash as SHA256;
32
33 let apu = apu.unwrap_or(&[]);
34 let apv = apv.unwrap_or(&[]);
35
36 let alg_bytes = alg.as_bytes();
38 let alg_len = (alg_bytes.len() as u32).to_be_bytes();
39 let apu_len = (apu.len() as u32).to_be_bytes();
40 let apv_len = (apv.len() as u32).to_be_bytes();
41 let key_bits = ((key_len * 8) as u32).to_be_bytes();
42
43 let mut derived_key = Vec::with_capacity(key_len);
44 let mut counter: u32 = 1;
45
46 while derived_key.len() < key_len {
47 let counter_bytes = counter.to_be_bytes();
48
49 let mut hasher = SHA256::new();
51 hasher.update(counter_bytes);
52 hasher.update(shared_secret);
53 hasher.update(alg_len);
55 hasher.update(alg_bytes);
56 hasher.update(apu_len);
57 hasher.update(apu);
58 hasher.update(apv_len);
59 hasher.update(apv);
60 hasher.update(key_bits);
61
62 let hash = hasher.finalize();
63 derived_key.extend_from_slice(&hash);
64 counter += 1;
65 }
66
67 derived_key.truncate(key_len);
68 derived_key
69}
70
71#[derive(Debug, Clone)]
73pub struct EcdhEsA256KWEncryptionKey {
74 pk: PublicKey,
75 key_id: Option<String>,
76}
77
78impl EcdhEsA256KWEncryptionKey {
79 const ALG_NAME: &'static str = "ECDH-ES+A256KW";
80 const KEY_WRAP_SIZE: usize = 32;
81
82 pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
84 let point = Sec1Point::from_bytes(bytes).map_err(|_| JWTError::InvalidPublicKey)?;
85 let pk = PublicKey::from_sec1_point(&point);
86 if pk.is_none().into() {
87 bail!(JWTError::InvalidPublicKey);
88 }
89 Ok(EcdhEsA256KWEncryptionKey {
90 pk: pk.unwrap(),
91 key_id: None,
92 })
93 }
94
95 pub fn from_der(der: &[u8]) -> Result<Self, Error> {
97 let pk = PublicKey::from_public_key_der(der).map_err(|_| JWTError::InvalidPublicKey)?;
98 Ok(EcdhEsA256KWEncryptionKey { pk, key_id: None })
99 }
100
101 pub fn from_pem(pem: &str) -> Result<Self, Error> {
103 let pk = PublicKey::from_public_key_pem(pem).map_err(|_| JWTError::InvalidPublicKey)?;
104 Ok(EcdhEsA256KWEncryptionKey { pk, key_id: None })
105 }
106
107 pub fn to_bytes(&self) -> Vec<u8> {
109 self.pk.to_sec1_point(true).as_bytes().to_vec()
110 }
111
112 pub fn to_bytes_uncompressed(&self) -> Vec<u8> {
114 self.pk.to_sec1_point(false).as_bytes().to_vec()
115 }
116
117 pub fn to_der(&self) -> Result<Vec<u8>, Error> {
119 Ok(self
120 .pk
121 .to_public_key_der()
122 .map_err(|_| JWTError::InvalidPublicKey)?
123 .as_ref()
124 .to_vec())
125 }
126
127 pub fn to_pem(&self) -> Result<String, Error> {
129 Ok(self
130 .pk
131 .to_public_key_pem(Default::default())
132 .map_err(|_| JWTError::InvalidPublicKey)?)
133 }
134
135 pub fn with_key_id(mut self, key_id: impl Into<String>) -> Self {
137 self.key_id = Some(key_id.into());
138 self
139 }
140
141 pub fn key_id(&self) -> Option<&str> {
143 self.key_id.as_deref()
144 }
145
146 fn build_epk_jwk(&self, ephemeral_pk: &PublicKey) -> serde_json::Value {
147 let point = ephemeral_pk.to_sec1_point(false);
148 let x = Base64UrlSafeNoPadding::encode_to_string(point.x().unwrap()).unwrap();
149 let y = Base64UrlSafeNoPadding::encode_to_string(point.y().unwrap()).unwrap();
150 json!({
151 "kty": "EC",
152 "crv": "P-256",
153 "x": x,
154 "y": y
155 })
156 }
157
158 pub fn encrypt<CustomClaims: Serialize>(
160 &self,
161 claims: JWTClaims<CustomClaims>,
162 ) -> Result<String, Error> {
163 self.encrypt_with_options(claims, &EncryptionOptions::default())
164 }
165
166 pub fn encrypt_with_options<CustomClaims: Serialize>(
168 &self,
169 claims: JWTClaims<CustomClaims>,
170 options: &EncryptionOptions,
171 ) -> Result<String, Error> {
172 let content_encryption = options.content_encryption;
173
174 let ephemeral_secret = EphemeralSecret::generate_from_rng(&mut rng());
175 let ephemeral_pk = ephemeral_secret.public_key();
176
177 let shared_secret = ephemeral_secret.diffie_hellman(&self.pk);
178
179 let mut kek = concat_kdf(
180 shared_secret.raw_secret_bytes(),
181 Self::KEY_WRAP_SIZE,
182 Self::ALG_NAME,
183 None,
184 None,
185 );
186
187 let wrap_key = A256KWKey::from_bytes(&kek)?;
188 kek.zeroize();
189
190 let mut header = JWEHeader::new(Self::ALG_NAME, content_encryption.alg_name());
191 header.ephemeral_public_key = Some(self.build_epk_jwk(&ephemeral_pk));
192
193 if let Some(key_id) = &self.key_id {
194 header.key_id = Some(key_id.clone());
195 }
196 if let Some(key_id) = &options.key_id {
197 header.key_id = Some(key_id.clone());
198 }
199 if let Some(cty) = &options.content_type {
200 header.content_type = Some(cty.clone());
201 }
202
203 JWEToken::build_from_claims(&header, &claims, content_encryption, |cek| {
204 wrap_key.wrap_key(cek)
205 })
206 }
207}
208
209#[derive(Clone)]
211pub struct EcdhEsA256KWDecryptionKey {
212 sk: SecretKey,
213 key_id: Option<String>,
214}
215
216impl std::fmt::Debug for EcdhEsA256KWDecryptionKey {
217 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
218 f.debug_struct("EcdhEsA256KWDecryptionKey")
219 .field("key_id", &self.key_id)
220 .finish_non_exhaustive()
221 }
222}
223
224impl EcdhEsA256KWDecryptionKey {
225 const ALG_NAME: &'static str = "ECDH-ES+A256KW";
226 const KEY_WRAP_SIZE: usize = 32;
227
228 pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
230 let sk = SecretKey::from_slice(bytes).map_err(|_| JWTError::InvalidKeyPair)?;
231 Ok(EcdhEsA256KWDecryptionKey { sk, key_id: None })
232 }
233
234 pub fn from_der(der: &[u8]) -> Result<Self, Error> {
236 let sk = SecretKey::from_pkcs8_der(der).map_err(|_| JWTError::InvalidKeyPair)?;
237 Ok(EcdhEsA256KWDecryptionKey { sk, key_id: None })
238 }
239
240 pub fn from_pem(pem: &str) -> Result<Self, Error> {
242 let sk = SecretKey::from_pkcs8_pem(pem).map_err(|_| JWTError::InvalidKeyPair)?;
243 Ok(EcdhEsA256KWDecryptionKey { sk, key_id: None })
244 }
245
246 pub fn generate() -> Self {
248 let sk = SecretKey::generate_from_rng(&mut rng());
249 EcdhEsA256KWDecryptionKey { sk, key_id: None }
250 }
251
252 pub fn to_bytes(&self) -> Vec<u8> {
254 self.sk.to_bytes().to_vec()
255 }
256
257 pub fn to_der(&self) -> Result<Vec<u8>, Error> {
259 let scalar = NonZeroScalar::from_repr(self.sk.to_bytes());
260 if bool::from(scalar.is_none()) {
261 return Err(JWTError::InvalidKeyPair.into());
262 }
263 let sk = SecretKey::from(NonZeroScalar::from_repr(scalar.unwrap().into()).unwrap());
264 Ok(sk
265 .to_pkcs8_der()
266 .map_err(|_| JWTError::InvalidKeyPair)?
267 .as_bytes()
268 .to_vec())
269 }
270
271 pub fn to_pem(&self) -> Result<String, Error> {
273 let scalar = NonZeroScalar::from_repr(self.sk.to_bytes());
274 if bool::from(scalar.is_none()) {
275 return Err(JWTError::InvalidKeyPair.into());
276 }
277 let sk = SecretKey::from(NonZeroScalar::from_repr(scalar.unwrap().into()).unwrap());
278 Ok(sk
279 .to_pkcs8_pem(Default::default())
280 .map_err(|_| JWTError::InvalidKeyPair)?
281 .to_string())
282 }
283
284 pub fn encryption_key(&self) -> EcdhEsA256KWEncryptionKey {
286 EcdhEsA256KWEncryptionKey {
287 pk: self.sk.public_key(),
288 key_id: self.key_id.clone(),
289 }
290 }
291
292 pub fn with_key_id(mut self, key_id: impl Into<String>) -> Self {
294 self.key_id = Some(key_id.into());
295 self
296 }
297
298 pub fn key_id(&self) -> Option<&str> {
300 self.key_id.as_deref()
301 }
302
303 fn parse_epk(epk: &serde_json::Value) -> Result<PublicKey, Error> {
304 let kty = epk.get("kty").and_then(|v| v.as_str());
305 ensure!(kty == Some("EC"), JWTError::InvalidEphemeralKey);
306
307 let crv = epk.get("crv").and_then(|v| v.as_str());
308 ensure!(crv == Some("P-256"), JWTError::InvalidEphemeralKey);
309
310 let x = epk
311 .get("x")
312 .and_then(|v| v.as_str())
313 .ok_or(JWTError::InvalidEphemeralKey)?;
314 let y = epk
315 .get("y")
316 .and_then(|v| v.as_str())
317 .ok_or(JWTError::InvalidEphemeralKey)?;
318
319 let x_bytes = Base64UrlSafeNoPadding::decode_to_vec(x, None)
320 .map_err(|_| JWTError::InvalidEphemeralKey)?;
321 let y_bytes = Base64UrlSafeNoPadding::decode_to_vec(y, None)
322 .map_err(|_| JWTError::InvalidEphemeralKey)?;
323
324 let mut point_bytes = vec![0x04];
326 point_bytes.extend_from_slice(&x_bytes);
327 point_bytes.extend_from_slice(&y_bytes);
328
329 let point =
330 Sec1Point::from_bytes(&point_bytes).map_err(|_| JWTError::InvalidEphemeralKey)?;
331 let pk = PublicKey::from_sec1_point(&point);
332 if pk.is_none().into() {
333 bail!(JWTError::InvalidEphemeralKey);
334 }
335
336 Ok(pk.unwrap())
337 }
338
339 pub fn encrypt<CustomClaims: Serialize>(
341 &self,
342 claims: JWTClaims<CustomClaims>,
343 ) -> Result<String, Error> {
344 self.encryption_key().encrypt(claims)
345 }
346
347 pub fn encrypt_with_options<CustomClaims: Serialize>(
349 &self,
350 claims: JWTClaims<CustomClaims>,
351 options: &EncryptionOptions,
352 ) -> Result<String, Error> {
353 self.encryption_key().encrypt_with_options(claims, options)
354 }
355
356 pub fn decrypt_token<CustomClaims: DeserializeOwned>(
358 &self,
359 token: &str,
360 options: Option<DecryptionOptions>,
361 ) -> Result<JWTClaims<CustomClaims>, Error> {
362 JWEToken::decrypt(Self::ALG_NAME, token, options, |header, encrypted_key| {
363 let epk = header
364 .ephemeral_public_key
365 .as_ref()
366 .ok_or(JWTError::MissingEphemeralKey)?;
367 let ephemeral_pk = Self::parse_epk(epk)?;
368
369 let shared_secret =
370 p256::ecdh::diffie_hellman(self.sk.to_nonzero_scalar(), ephemeral_pk.as_affine());
371
372 let mut kek = concat_kdf(
373 shared_secret.raw_secret_bytes(),
374 Self::KEY_WRAP_SIZE,
375 Self::ALG_NAME,
376 None,
377 None,
378 );
379
380 let wrap_key = A256KWKey::from_bytes(&kek)?;
381 kek.zeroize();
382 wrap_key.unwrap_key(encrypted_key)
383 })
384 }
385
386 pub fn decode_metadata(token: &str) -> Result<JWETokenMetadata, Error> {
388 JWEToken::decode_metadata(token)
389 }
390}
391
392#[derive(Debug, Clone)]
394pub struct EcdhEsA128KWEncryptionKey {
395 pk: PublicKey,
396 key_id: Option<String>,
397}
398
399impl EcdhEsA128KWEncryptionKey {
400 const ALG_NAME: &'static str = "ECDH-ES+A128KW";
401 const KEY_WRAP_SIZE: usize = 16;
402
403 pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
405 let point = Sec1Point::from_bytes(bytes).map_err(|_| JWTError::InvalidPublicKey)?;
406 let pk = PublicKey::from_sec1_point(&point);
407 if pk.is_none().into() {
408 bail!(JWTError::InvalidPublicKey);
409 }
410 Ok(EcdhEsA128KWEncryptionKey {
411 pk: pk.unwrap(),
412 key_id: None,
413 })
414 }
415
416 pub fn from_der(der: &[u8]) -> Result<Self, Error> {
418 let pk = PublicKey::from_public_key_der(der).map_err(|_| JWTError::InvalidPublicKey)?;
419 Ok(EcdhEsA128KWEncryptionKey { pk, key_id: None })
420 }
421
422 pub fn from_pem(pem: &str) -> Result<Self, Error> {
424 let pk = PublicKey::from_public_key_pem(pem).map_err(|_| JWTError::InvalidPublicKey)?;
425 Ok(EcdhEsA128KWEncryptionKey { pk, key_id: None })
426 }
427
428 pub fn to_bytes(&self) -> Vec<u8> {
430 self.pk.to_sec1_point(true).as_bytes().to_vec()
431 }
432
433 pub fn to_der(&self) -> Result<Vec<u8>, Error> {
435 Ok(self
436 .pk
437 .to_public_key_der()
438 .map_err(|_| JWTError::InvalidPublicKey)?
439 .as_ref()
440 .to_vec())
441 }
442
443 pub fn to_pem(&self) -> Result<String, Error> {
445 Ok(self
446 .pk
447 .to_public_key_pem(Default::default())
448 .map_err(|_| JWTError::InvalidPublicKey)?)
449 }
450
451 pub fn with_key_id(mut self, key_id: impl Into<String>) -> Self {
453 self.key_id = Some(key_id.into());
454 self
455 }
456
457 pub fn key_id(&self) -> Option<&str> {
459 self.key_id.as_deref()
460 }
461
462 fn build_epk_jwk(&self, ephemeral_pk: &PublicKey) -> serde_json::Value {
463 let point = ephemeral_pk.to_sec1_point(false);
464 let x = Base64UrlSafeNoPadding::encode_to_string(point.x().unwrap()).unwrap();
465 let y = Base64UrlSafeNoPadding::encode_to_string(point.y().unwrap()).unwrap();
466 json!({
467 "kty": "EC",
468 "crv": "P-256",
469 "x": x,
470 "y": y
471 })
472 }
473
474 pub fn encrypt<CustomClaims: Serialize>(
476 &self,
477 claims: JWTClaims<CustomClaims>,
478 ) -> Result<String, Error> {
479 self.encrypt_with_options(claims, &EncryptionOptions::default())
480 }
481
482 pub fn encrypt_with_options<CustomClaims: Serialize>(
484 &self,
485 claims: JWTClaims<CustomClaims>,
486 options: &EncryptionOptions,
487 ) -> Result<String, Error> {
488 let content_encryption = options.content_encryption;
489
490 let ephemeral_secret = EphemeralSecret::generate_from_rng(&mut rng());
491 let ephemeral_pk = ephemeral_secret.public_key();
492
493 let shared_secret = ephemeral_secret.diffie_hellman(&self.pk);
494
495 let mut kek = concat_kdf(
496 shared_secret.raw_secret_bytes(),
497 Self::KEY_WRAP_SIZE,
498 Self::ALG_NAME,
499 None,
500 None,
501 );
502
503 let wrap_key = A128KWKey::from_bytes(&kek)?;
504 kek.zeroize();
505
506 let mut header = JWEHeader::new(Self::ALG_NAME, content_encryption.alg_name());
507 header.ephemeral_public_key = Some(self.build_epk_jwk(&ephemeral_pk));
508
509 if let Some(key_id) = &self.key_id {
510 header.key_id = Some(key_id.clone());
511 }
512 if let Some(key_id) = &options.key_id {
513 header.key_id = Some(key_id.clone());
514 }
515 if let Some(cty) = &options.content_type {
516 header.content_type = Some(cty.clone());
517 }
518
519 JWEToken::build_from_claims(&header, &claims, content_encryption, |cek| {
520 wrap_key.wrap_key(cek)
521 })
522 }
523}
524
525#[derive(Clone)]
527pub struct EcdhEsA128KWDecryptionKey {
528 sk: SecretKey,
529 key_id: Option<String>,
530}
531
532impl std::fmt::Debug for EcdhEsA128KWDecryptionKey {
533 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
534 f.debug_struct("EcdhEsA128KWDecryptionKey")
535 .field("key_id", &self.key_id)
536 .finish_non_exhaustive()
537 }
538}
539
540impl EcdhEsA128KWDecryptionKey {
541 const ALG_NAME: &'static str = "ECDH-ES+A128KW";
542 const KEY_WRAP_SIZE: usize = 16;
543
544 pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
546 let sk = SecretKey::from_slice(bytes).map_err(|_| JWTError::InvalidKeyPair)?;
547 Ok(EcdhEsA128KWDecryptionKey { sk, key_id: None })
548 }
549
550 pub fn from_der(der: &[u8]) -> Result<Self, Error> {
552 let sk = SecretKey::from_pkcs8_der(der).map_err(|_| JWTError::InvalidKeyPair)?;
553 Ok(EcdhEsA128KWDecryptionKey { sk, key_id: None })
554 }
555
556 pub fn from_pem(pem: &str) -> Result<Self, Error> {
558 let sk = SecretKey::from_pkcs8_pem(pem).map_err(|_| JWTError::InvalidKeyPair)?;
559 Ok(EcdhEsA128KWDecryptionKey { sk, key_id: None })
560 }
561
562 pub fn generate() -> Self {
564 let sk = SecretKey::generate_from_rng(&mut rng());
565 EcdhEsA128KWDecryptionKey { sk, key_id: None }
566 }
567
568 pub fn to_bytes(&self) -> Vec<u8> {
570 self.sk.to_bytes().to_vec()
571 }
572
573 pub fn to_der(&self) -> Result<Vec<u8>, Error> {
575 let scalar = NonZeroScalar::from_repr(self.sk.to_bytes());
576 if bool::from(scalar.is_none()) {
577 return Err(JWTError::InvalidKeyPair.into());
578 }
579 let sk = SecretKey::from(NonZeroScalar::from_repr(scalar.unwrap().into()).unwrap());
580 Ok(sk
581 .to_pkcs8_der()
582 .map_err(|_| JWTError::InvalidKeyPair)?
583 .as_bytes()
584 .to_vec())
585 }
586
587 pub fn to_pem(&self) -> Result<String, Error> {
589 let scalar = NonZeroScalar::from_repr(self.sk.to_bytes());
590 if bool::from(scalar.is_none()) {
591 return Err(JWTError::InvalidKeyPair.into());
592 }
593 let sk = SecretKey::from(NonZeroScalar::from_repr(scalar.unwrap().into()).unwrap());
594 Ok(sk
595 .to_pkcs8_pem(Default::default())
596 .map_err(|_| JWTError::InvalidKeyPair)?
597 .to_string())
598 }
599
600 pub fn encryption_key(&self) -> EcdhEsA128KWEncryptionKey {
602 EcdhEsA128KWEncryptionKey {
603 pk: self.sk.public_key(),
604 key_id: self.key_id.clone(),
605 }
606 }
607
608 pub fn with_key_id(mut self, key_id: impl Into<String>) -> Self {
610 self.key_id = Some(key_id.into());
611 self
612 }
613
614 pub fn key_id(&self) -> Option<&str> {
616 self.key_id.as_deref()
617 }
618
619 fn parse_epk(epk: &serde_json::Value) -> Result<PublicKey, Error> {
620 let kty = epk.get("kty").and_then(|v| v.as_str());
621 ensure!(kty == Some("EC"), JWTError::InvalidEphemeralKey);
622
623 let crv = epk.get("crv").and_then(|v| v.as_str());
624 ensure!(crv == Some("P-256"), JWTError::InvalidEphemeralKey);
625
626 let x = epk
627 .get("x")
628 .and_then(|v| v.as_str())
629 .ok_or(JWTError::InvalidEphemeralKey)?;
630 let y = epk
631 .get("y")
632 .and_then(|v| v.as_str())
633 .ok_or(JWTError::InvalidEphemeralKey)?;
634
635 let x_bytes = Base64UrlSafeNoPadding::decode_to_vec(x, None)
636 .map_err(|_| JWTError::InvalidEphemeralKey)?;
637 let y_bytes = Base64UrlSafeNoPadding::decode_to_vec(y, None)
638 .map_err(|_| JWTError::InvalidEphemeralKey)?;
639
640 let mut point_bytes = vec![0x04];
642 point_bytes.extend_from_slice(&x_bytes);
643 point_bytes.extend_from_slice(&y_bytes);
644
645 let point =
646 Sec1Point::from_bytes(&point_bytes).map_err(|_| JWTError::InvalidEphemeralKey)?;
647 let pk = PublicKey::from_sec1_point(&point);
648 if pk.is_none().into() {
649 bail!(JWTError::InvalidEphemeralKey);
650 }
651
652 Ok(pk.unwrap())
653 }
654
655 pub fn encrypt<CustomClaims: Serialize>(
657 &self,
658 claims: JWTClaims<CustomClaims>,
659 ) -> Result<String, Error> {
660 self.encryption_key().encrypt(claims)
661 }
662
663 pub fn encrypt_with_options<CustomClaims: Serialize>(
665 &self,
666 claims: JWTClaims<CustomClaims>,
667 options: &EncryptionOptions,
668 ) -> Result<String, Error> {
669 self.encryption_key().encrypt_with_options(claims, options)
670 }
671
672 pub fn decrypt_token<CustomClaims: DeserializeOwned>(
674 &self,
675 token: &str,
676 options: Option<DecryptionOptions>,
677 ) -> Result<JWTClaims<CustomClaims>, Error> {
678 JWEToken::decrypt(Self::ALG_NAME, token, options, |header, encrypted_key| {
679 let epk = header
680 .ephemeral_public_key
681 .as_ref()
682 .ok_or(JWTError::MissingEphemeralKey)?;
683 let ephemeral_pk = Self::parse_epk(epk)?;
684
685 let shared_secret =
686 p256::ecdh::diffie_hellman(self.sk.to_nonzero_scalar(), ephemeral_pk.as_affine());
687
688 let mut kek = concat_kdf(
689 shared_secret.raw_secret_bytes(),
690 Self::KEY_WRAP_SIZE,
691 Self::ALG_NAME,
692 None,
693 None,
694 );
695
696 let wrap_key = A128KWKey::from_bytes(&kek)?;
697 kek.zeroize();
698 wrap_key.unwrap_key(encrypted_key)
699 })
700 }
701
702 pub fn decode_metadata(token: &str) -> Result<JWETokenMetadata, Error> {
704 JWEToken::decode_metadata(token)
705 }
706}