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>(
362 &self,
363 token: &str,
364 options: Option<DecryptionOptions>,
365 ) -> Result<JWTClaims<CustomClaims>, Error> {
366 JWEToken::decrypt(Self::ALG_NAME, token, options, |header, encrypted_key| {
367 let epk = header
368 .ephemeral_public_key
369 .as_ref()
370 .ok_or(JWTError::MissingEphemeralKey)?;
371 let ephemeral_pk = Self::parse_epk(epk)?;
372
373 let shared_secret =
374 p256::ecdh::diffie_hellman(self.sk.to_nonzero_scalar(), ephemeral_pk.as_affine());
375
376 let mut kek = concat_kdf(
377 shared_secret.raw_secret_bytes(),
378 Self::KEY_WRAP_SIZE,
379 Self::ALG_NAME,
380 None,
381 None,
382 );
383
384 let wrap_key = A256KWKey::from_bytes(&kek)?;
385 kek.zeroize();
386 wrap_key.unwrap_key(encrypted_key)
387 })
388 }
389
390 pub fn decode_metadata(token: &str) -> Result<JWETokenMetadata, Error> {
392 JWEToken::decode_metadata(token)
393 }
394}
395
396#[derive(Debug, Clone)]
398pub struct EcdhEsA128KWEncryptionKey {
399 pk: PublicKey,
400 key_id: Option<String>,
401}
402
403impl EcdhEsA128KWEncryptionKey {
404 const ALG_NAME: &'static str = "ECDH-ES+A128KW";
405 const KEY_WRAP_SIZE: usize = 16;
406
407 pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
409 let point = Sec1Point::from_bytes(bytes).map_err(|_| JWTError::InvalidPublicKey)?;
410 let pk = PublicKey::from_sec1_point(&point);
411 if pk.is_none().into() {
412 bail!(JWTError::InvalidPublicKey);
413 }
414 Ok(EcdhEsA128KWEncryptionKey {
415 pk: pk.unwrap(),
416 key_id: None,
417 })
418 }
419
420 pub fn from_der(der: &[u8]) -> Result<Self, Error> {
422 let pk = PublicKey::from_public_key_der(der).map_err(|_| JWTError::InvalidPublicKey)?;
423 Ok(EcdhEsA128KWEncryptionKey { pk, key_id: None })
424 }
425
426 pub fn from_pem(pem: &str) -> Result<Self, Error> {
428 let pk = PublicKey::from_public_key_pem(pem).map_err(|_| JWTError::InvalidPublicKey)?;
429 Ok(EcdhEsA128KWEncryptionKey { pk, key_id: None })
430 }
431
432 pub fn to_bytes(&self) -> Vec<u8> {
434 self.pk.to_sec1_point(true).as_bytes().to_vec()
435 }
436
437 pub fn to_der(&self) -> Result<Vec<u8>, Error> {
439 Ok(self
440 .pk
441 .to_public_key_der()
442 .map_err(|_| JWTError::InvalidPublicKey)?
443 .as_ref()
444 .to_vec())
445 }
446
447 pub fn to_pem(&self) -> Result<String, Error> {
449 Ok(self
450 .pk
451 .to_public_key_pem(Default::default())
452 .map_err(|_| JWTError::InvalidPublicKey)?)
453 }
454
455 pub fn with_key_id(mut self, key_id: impl Into<String>) -> Self {
457 self.key_id = Some(key_id.into());
458 self
459 }
460
461 pub fn key_id(&self) -> Option<&str> {
463 self.key_id.as_deref()
464 }
465
466 fn build_epk_jwk(&self, ephemeral_pk: &PublicKey) -> serde_json::Value {
467 let point = ephemeral_pk.to_sec1_point(false);
468 let x = Base64UrlSafeNoPadding::encode_to_string(point.x().unwrap()).unwrap();
469 let y = Base64UrlSafeNoPadding::encode_to_string(point.y().unwrap()).unwrap();
470 json!({
471 "kty": "EC",
472 "crv": "P-256",
473 "x": x,
474 "y": y
475 })
476 }
477
478 pub fn encrypt<CustomClaims: Serialize>(
480 &self,
481 claims: JWTClaims<CustomClaims>,
482 ) -> Result<String, Error> {
483 self.encrypt_with_options(claims, &EncryptionOptions::default())
484 }
485
486 pub fn encrypt_with_options<CustomClaims: Serialize>(
488 &self,
489 claims: JWTClaims<CustomClaims>,
490 options: &EncryptionOptions,
491 ) -> Result<String, Error> {
492 let content_encryption = options.content_encryption;
493
494 let ephemeral_secret = EphemeralSecret::generate_from_rng(&mut rng());
495 let ephemeral_pk = ephemeral_secret.public_key();
496
497 let shared_secret = ephemeral_secret.diffie_hellman(&self.pk);
498
499 let mut kek = concat_kdf(
500 shared_secret.raw_secret_bytes(),
501 Self::KEY_WRAP_SIZE,
502 Self::ALG_NAME,
503 None,
504 None,
505 );
506
507 let wrap_key = A128KWKey::from_bytes(&kek)?;
508 kek.zeroize();
509
510 let mut header = JWEHeader::new(Self::ALG_NAME, content_encryption.alg_name());
511 header.ephemeral_public_key = Some(self.build_epk_jwk(&ephemeral_pk));
512
513 if let Some(key_id) = &self.key_id {
514 header.key_id = Some(key_id.clone());
515 }
516 if let Some(key_id) = &options.key_id {
517 header.key_id = Some(key_id.clone());
518 }
519 if let Some(cty) = &options.content_type {
520 header.content_type = Some(cty.clone());
521 }
522
523 JWEToken::build_from_claims(&header, &claims, content_encryption, |cek| {
524 wrap_key.wrap_key(cek)
525 })
526 }
527}
528
529#[derive(Clone)]
531pub struct EcdhEsA128KWDecryptionKey {
532 sk: SecretKey,
533 key_id: Option<String>,
534}
535
536impl std::fmt::Debug for EcdhEsA128KWDecryptionKey {
537 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
538 f.debug_struct("EcdhEsA128KWDecryptionKey")
539 .field("key_id", &self.key_id)
540 .finish_non_exhaustive()
541 }
542}
543
544impl EcdhEsA128KWDecryptionKey {
545 const ALG_NAME: &'static str = "ECDH-ES+A128KW";
546 const KEY_WRAP_SIZE: usize = 16;
547
548 pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
550 let sk = SecretKey::from_slice(bytes).map_err(|_| JWTError::InvalidKeyPair)?;
551 Ok(EcdhEsA128KWDecryptionKey { sk, key_id: None })
552 }
553
554 pub fn from_der(der: &[u8]) -> Result<Self, Error> {
556 let sk = SecretKey::from_pkcs8_der(der).map_err(|_| JWTError::InvalidKeyPair)?;
557 Ok(EcdhEsA128KWDecryptionKey { sk, key_id: None })
558 }
559
560 pub fn from_pem(pem: &str) -> Result<Self, Error> {
562 let sk = SecretKey::from_pkcs8_pem(pem).map_err(|_| JWTError::InvalidKeyPair)?;
563 Ok(EcdhEsA128KWDecryptionKey { sk, key_id: None })
564 }
565
566 pub fn generate() -> Self {
568 let sk = SecretKey::generate_from_rng(&mut rng());
569 EcdhEsA128KWDecryptionKey { sk, key_id: None }
570 }
571
572 pub fn to_bytes(&self) -> Vec<u8> {
574 self.sk.to_bytes().to_vec()
575 }
576
577 pub fn to_der(&self) -> Result<Vec<u8>, Error> {
579 let scalar = NonZeroScalar::from_repr(self.sk.to_bytes());
580 if bool::from(scalar.is_none()) {
581 return Err(JWTError::InvalidKeyPair.into());
582 }
583 let sk = SecretKey::from(NonZeroScalar::from_repr(scalar.unwrap().into()).unwrap());
584 Ok(sk
585 .to_pkcs8_der()
586 .map_err(|_| JWTError::InvalidKeyPair)?
587 .as_bytes()
588 .to_vec())
589 }
590
591 pub fn to_pem(&self) -> Result<String, Error> {
593 let scalar = NonZeroScalar::from_repr(self.sk.to_bytes());
594 if bool::from(scalar.is_none()) {
595 return Err(JWTError::InvalidKeyPair.into());
596 }
597 let sk = SecretKey::from(NonZeroScalar::from_repr(scalar.unwrap().into()).unwrap());
598 Ok(sk
599 .to_pkcs8_pem(Default::default())
600 .map_err(|_| JWTError::InvalidKeyPair)?
601 .to_string())
602 }
603
604 pub fn encryption_key(&self) -> EcdhEsA128KWEncryptionKey {
606 EcdhEsA128KWEncryptionKey {
607 pk: self.sk.public_key(),
608 key_id: self.key_id.clone(),
609 }
610 }
611
612 pub fn with_key_id(mut self, key_id: impl Into<String>) -> Self {
614 self.key_id = Some(key_id.into());
615 self
616 }
617
618 pub fn key_id(&self) -> Option<&str> {
620 self.key_id.as_deref()
621 }
622
623 fn parse_epk(epk: &serde_json::Value) -> Result<PublicKey, Error> {
624 let kty = epk.get("kty").and_then(|v| v.as_str());
625 ensure!(kty == Some("EC"), JWTError::InvalidEphemeralKey);
626
627 let crv = epk.get("crv").and_then(|v| v.as_str());
628 ensure!(crv == Some("P-256"), JWTError::InvalidEphemeralKey);
629
630 let x = epk
631 .get("x")
632 .and_then(|v| v.as_str())
633 .ok_or(JWTError::InvalidEphemeralKey)?;
634 let y = epk
635 .get("y")
636 .and_then(|v| v.as_str())
637 .ok_or(JWTError::InvalidEphemeralKey)?;
638
639 let x_bytes = Base64UrlSafeNoPadding::decode_to_vec(x, None)
640 .map_err(|_| JWTError::InvalidEphemeralKey)?;
641 let y_bytes = Base64UrlSafeNoPadding::decode_to_vec(y, None)
642 .map_err(|_| JWTError::InvalidEphemeralKey)?;
643
644 let mut point_bytes = vec![0x04];
646 point_bytes.extend_from_slice(&x_bytes);
647 point_bytes.extend_from_slice(&y_bytes);
648
649 let point =
650 Sec1Point::from_bytes(&point_bytes).map_err(|_| JWTError::InvalidEphemeralKey)?;
651 let pk = PublicKey::from_sec1_point(&point);
652 if pk.is_none().into() {
653 bail!(JWTError::InvalidEphemeralKey);
654 }
655
656 Ok(pk.unwrap())
657 }
658
659 pub fn encrypt<CustomClaims: Serialize>(
661 &self,
662 claims: JWTClaims<CustomClaims>,
663 ) -> Result<String, Error> {
664 self.encryption_key().encrypt(claims)
665 }
666
667 pub fn encrypt_with_options<CustomClaims: Serialize>(
669 &self,
670 claims: JWTClaims<CustomClaims>,
671 options: &EncryptionOptions,
672 ) -> Result<String, Error> {
673 self.encryption_key().encrypt_with_options(claims, options)
674 }
675
676 pub fn decrypt_token<CustomClaims: DeserializeOwned>(
682 &self,
683 token: &str,
684 options: Option<DecryptionOptions>,
685 ) -> Result<JWTClaims<CustomClaims>, Error> {
686 JWEToken::decrypt(Self::ALG_NAME, token, options, |header, encrypted_key| {
687 let epk = header
688 .ephemeral_public_key
689 .as_ref()
690 .ok_or(JWTError::MissingEphemeralKey)?;
691 let ephemeral_pk = Self::parse_epk(epk)?;
692
693 let shared_secret =
694 p256::ecdh::diffie_hellman(self.sk.to_nonzero_scalar(), ephemeral_pk.as_affine());
695
696 let mut kek = concat_kdf(
697 shared_secret.raw_secret_bytes(),
698 Self::KEY_WRAP_SIZE,
699 Self::ALG_NAME,
700 None,
701 None,
702 );
703
704 let wrap_key = A128KWKey::from_bytes(&kek)?;
705 kek.zeroize();
706 wrap_key.unwrap_key(encrypted_key)
707 })
708 }
709
710 pub fn decode_metadata(token: &str) -> Result<JWETokenMetadata, Error> {
712 JWEToken::decode_metadata(token)
713 }
714}