1use crate::error::KeyError;
2use crate::generate::generate;
3use crate::{Algorithm, Claims};
4use base64::Engine;
5use elliptic_curve::SecretKey;
6use elliptic_curve::pkcs8::EncodePrivateKey;
7use jsonwebtoken::{DecodingKey, EncodingKey, Header};
8use rsa::BigUint;
9use rsa::pkcs1::EncodeRsaPrivateKey;
10use serde::{Deserialize, Deserializer, Serialize, Serializer};
11use std::sync::OnceLock;
12use std::{collections::HashSet, fmt, path::Path as StdPath};
13
14#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)]
16#[serde(rename_all = "camelCase")]
17pub enum KeyOperation {
18 Sign,
19 Verify,
20 Decrypt,
21 Encrypt,
22}
23
24#[derive(Clone, Serialize, Deserialize)]
26#[serde(tag = "kty")]
27pub enum KeyType {
28 EC {
30 #[serde(rename = "crv")]
31 curve: EllipticCurve,
32 #[serde(serialize_with = "serialize_base64url", deserialize_with = "deserialize_base64url")]
34 x: Vec<u8>,
35 #[serde(serialize_with = "serialize_base64url", deserialize_with = "deserialize_base64url")]
37 y: Vec<u8>,
38 #[serde(
40 default,
41 skip_serializing_if = "Option::is_none",
42 serialize_with = "serialize_base64url_optional",
43 deserialize_with = "deserialize_base64url_optional"
44 )]
45 d: Option<Vec<u8>>,
46 },
47 RSA {
49 #[serde(flatten)]
50 public: RsaPublicKey,
51 #[serde(flatten, skip_serializing_if = "Option::is_none")]
52 private: Option<RsaPrivateKey>,
53 },
54 #[serde(rename = "oct")]
56 OCT {
57 #[serde(
59 rename = "k",
60 default,
61 serialize_with = "serialize_base64url",
62 deserialize_with = "deserialize_base64url"
63 )]
64 secret: Vec<u8>,
65 },
66 OKP {
68 #[serde(rename = "crv")]
69 curve: EllipticCurve,
70 #[serde(serialize_with = "serialize_base64url", deserialize_with = "deserialize_base64url")]
71 x: Vec<u8>,
72 #[serde(
73 rename = "d",
74 default,
75 skip_serializing_if = "Option::is_none",
76 serialize_with = "serialize_base64url_optional",
77 deserialize_with = "deserialize_base64url_optional"
78 )]
79 d: Option<Vec<u8>>,
80 },
81}
82
83#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Debug)]
87pub enum EllipticCurve {
88 #[serde(rename = "P-256")]
89 P256,
90 #[serde(rename = "P-384")]
91 P384,
92 #[serde(rename = "Ed25519")]
96 Ed25519,
97}
98
99#[derive(Clone, Serialize, Deserialize)]
103pub struct RsaPublicKey {
104 #[serde(serialize_with = "serialize_base64url", deserialize_with = "deserialize_base64url")]
105 pub n: Vec<u8>,
106 #[serde(serialize_with = "serialize_base64url", deserialize_with = "deserialize_base64url")]
107 pub e: Vec<u8>,
108}
109
110#[derive(Clone, Serialize, Deserialize)]
114pub struct RsaPrivateKey {
115 #[serde(serialize_with = "serialize_base64url", deserialize_with = "deserialize_base64url")]
116 pub d: Vec<u8>,
117 #[serde(serialize_with = "serialize_base64url", deserialize_with = "deserialize_base64url")]
118 pub p: Vec<u8>,
119 #[serde(serialize_with = "serialize_base64url", deserialize_with = "deserialize_base64url")]
120 pub q: Vec<u8>,
121 #[serde(serialize_with = "serialize_base64url", deserialize_with = "deserialize_base64url")]
122 pub dp: Vec<u8>,
123 #[serde(serialize_with = "serialize_base64url", deserialize_with = "deserialize_base64url")]
124 pub dq: Vec<u8>,
125 #[serde(serialize_with = "serialize_base64url", deserialize_with = "deserialize_base64url")]
126 pub qi: Vec<u8>,
127 #[serde(skip_serializing_if = "Option::is_none")]
128 pub oth: Option<Vec<RsaAdditionalPrime>>,
129}
130
131#[derive(Clone, Serialize, Deserialize)]
133pub struct RsaAdditionalPrime {
134 #[serde(serialize_with = "serialize_base64url", deserialize_with = "deserialize_base64url")]
135 pub r: Vec<u8>,
136 #[serde(serialize_with = "serialize_base64url", deserialize_with = "deserialize_base64url")]
137 pub d: Vec<u8>,
138 #[serde(serialize_with = "serialize_base64url", deserialize_with = "deserialize_base64url")]
139 pub t: Vec<u8>,
140}
141
142#[derive(Clone, Serialize, Deserialize)]
145#[serde(remote = "Self")]
146pub struct Key {
147 #[serde(rename = "alg")]
149 pub algorithm: Algorithm,
150
151 #[serde(rename = "key_ops")]
153 pub operations: HashSet<KeyOperation>,
154
155 #[serde(flatten)]
157 pub key: KeyType,
158
159 #[serde(skip_serializing_if = "Option::is_none")]
161 pub kid: Option<crate::KeyId>,
162
163 #[serde(skip)]
165 pub(crate) decode: OnceLock<DecodingKey>,
166
167 #[serde(skip)]
168 pub(crate) encode: OnceLock<EncodingKey>,
169}
170
171impl<'de> Deserialize<'de> for Key {
172 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
173 where
174 D: Deserializer<'de>,
175 {
176 let mut value = serde_json::Value::deserialize(deserializer)?;
177
178 if let Some(obj) = value.as_object_mut()
182 && !obj.contains_key("kty")
183 {
184 obj.insert("kty".to_string(), serde_json::Value::String("oct".to_string()));
185 }
186
187 Self::deserialize(value).map_err(serde::de::Error::custom)
188 }
189}
190
191impl Serialize for Key {
192 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
193 where
194 S: Serializer,
195 {
196 Self::serialize(self, serializer)
197 }
198}
199
200impl fmt::Debug for Key {
201 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202 f.debug_struct("Key")
203 .field("algorithm", &self.algorithm)
204 .field("operations", &self.operations)
205 .field("kid", &self.kid)
206 .finish()
207 }
208}
209
210impl Key {
211 #[allow(clippy::should_implement_trait)]
213 pub fn from_str(s: &str) -> crate::Result<Self> {
214 let s = s.trim();
215 if s.starts_with('{') {
216 Ok(serde_json::from_str(s)?)
217 } else {
218 let decoded = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(s)?;
219 let json = String::from_utf8(decoded)?;
220 Ok(serde_json::from_str(&json)?)
221 }
222 }
223
224 pub fn from_file<P: AsRef<StdPath>>(path: P) -> crate::Result<Self> {
226 let contents = std::fs::read_to_string(&path)?;
227 Self::from_str(&contents)
228 }
229
230 #[cfg(feature = "tokio")]
232 pub async fn from_file_async<P: AsRef<StdPath>>(path: P) -> crate::Result<Self> {
233 let contents = tokio::fs::read_to_string(path).await?;
234 Self::from_str(&contents)
235 }
236
237 pub fn to_str(&self) -> crate::Result<String> {
239 let json = serde_json::to_string(self)?;
240 Ok(base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(json.as_bytes()))
241 }
242
243 pub fn to_file<P: AsRef<StdPath>>(&self, path: P) -> crate::Result<()> {
245 let encoded = self.to_str()?;
246 std::fs::write(path, encoded)?;
247 Ok(())
248 }
249
250 pub fn to_public(&self) -> crate::Result<Self> {
251 if !self.operations.contains(&KeyOperation::Verify) {
252 return Err(KeyError::VerifyUnsupported.into());
253 }
254
255 let key = match self.key {
256 KeyType::RSA { ref public, .. } => KeyType::RSA {
257 public: public.clone(),
258 private: None,
259 },
260 KeyType::EC {
261 ref x,
262 ref y,
263 ref curve,
264 ..
265 } => KeyType::EC {
266 x: x.clone(),
267 y: y.clone(),
268 curve: curve.clone(),
269 d: None,
270 },
271 KeyType::OCT { .. } => return Err(KeyError::NoPublicKey.into()),
272 KeyType::OKP { ref x, ref curve, .. } => KeyType::OKP {
273 x: x.clone(),
274 curve: curve.clone(),
275 d: None,
276 },
277 };
278
279 Ok(Self {
280 algorithm: self.algorithm,
281 operations: [KeyOperation::Verify].into(),
282 key,
283 kid: self.kid.clone(),
284 decode: Default::default(),
285 encode: Default::default(),
286 })
287 }
288
289 fn to_decoding_key(&self) -> crate::Result<&DecodingKey> {
290 if let Some(key) = self.decode.get() {
291 return Ok(key);
292 }
293
294 let decoding_key = match self.key {
295 KeyType::OCT { ref secret } => match self.algorithm {
296 Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => DecodingKey::from_secret(secret),
297 _ => return Err(KeyError::InvalidAlgorithm.into()),
298 },
299 KeyType::EC {
300 ref curve,
301 ref x,
302 ref y,
303 ..
304 } => match curve {
305 EllipticCurve::P256 => {
306 if self.algorithm != Algorithm::ES256 {
307 return Err(KeyError::InvalidAlgorithmForCurve("P-256").into());
308 }
309 if x.len() != 32 || y.len() != 32 {
310 return Err(KeyError::InvalidCoordinateLength("P-256").into());
311 }
312
313 DecodingKey::from_ec_components(
314 base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(x).as_ref(),
315 base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(y).as_ref(),
316 )?
317 }
318 EllipticCurve::P384 => {
319 if self.algorithm != Algorithm::ES384 {
320 return Err(KeyError::InvalidAlgorithmForCurve("P-384").into());
321 }
322 if x.len() != 48 || y.len() != 48 {
323 return Err(KeyError::InvalidCoordinateLength("P-384").into());
324 }
325
326 DecodingKey::from_ec_components(
327 base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(x).as_ref(),
328 base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(y).as_ref(),
329 )?
330 }
331 _ => return Err(KeyError::InvalidCurve("EC").into()),
332 },
333 KeyType::OKP { ref curve, ref x, .. } => match curve {
334 EllipticCurve::Ed25519 => {
335 if self.algorithm != Algorithm::EdDSA {
336 return Err(KeyError::InvalidAlgorithmForCurve("Ed25519").into());
337 }
338
339 DecodingKey::from_ed_components(
340 base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(x).as_ref(),
341 )?
342 }
343 _ => return Err(KeyError::InvalidCurve("OKP").into()),
344 },
345 KeyType::RSA { ref public, .. } => {
346 DecodingKey::from_rsa_raw_components(public.n.as_ref(), public.e.as_ref())
347 }
348 };
349
350 Ok(self.decode.get_or_init(|| decoding_key))
351 }
352
353 fn to_encoding_key(&self) -> crate::Result<&EncodingKey> {
354 if let Some(key) = self.encode.get() {
355 return Ok(key);
356 }
357
358 let encoding_key = match self.key {
359 KeyType::OCT { ref secret } => match self.algorithm {
360 Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => EncodingKey::from_secret(secret),
361 _ => return Err(KeyError::InvalidAlgorithm.into()),
362 },
363 KeyType::EC { ref curve, ref d, .. } => {
364 let d = d.as_ref().ok_or(KeyError::MissingPrivateKey)?;
365
366 match curve {
367 EllipticCurve::P256 => {
368 let secret_key = SecretKey::<p256::NistP256>::from_slice(d)?;
369 let doc = secret_key.to_pkcs8_der()?;
370 EncodingKey::from_ec_der(doc.as_bytes())
371 }
372 EllipticCurve::P384 => {
373 let secret_key = SecretKey::<p384::NistP384>::from_slice(d)?;
374 let doc = secret_key.to_pkcs8_der()?;
375 EncodingKey::from_ec_der(doc.as_bytes())
376 }
377 _ => return Err(KeyError::InvalidCurve("EC").into()),
378 }
379 }
380 KeyType::OKP {
381 ref curve,
382 ref d,
383 ref x,
384 } => {
385 let d = d.as_ref().ok_or(KeyError::MissingPrivateKey)?;
386
387 let key_pair =
388 aws_lc_rs::signature::Ed25519KeyPair::from_seed_and_public_key(d.as_slice(), x.as_slice())?;
389
390 match curve {
391 EllipticCurve::Ed25519 => EncodingKey::from_ed_der(key_pair.to_pkcs8()?.as_ref()),
392 _ => return Err(KeyError::InvalidCurve("OKP").into()),
393 }
394 }
395 KeyType::RSA {
396 ref public,
397 ref private,
398 } => {
399 let n = BigUint::from_bytes_be(&public.n);
400 let e = BigUint::from_bytes_be(&public.e);
401 let private = private.as_ref().ok_or(KeyError::MissingPrivateKey)?;
402 let d = BigUint::from_bytes_be(&private.d);
403 let p = BigUint::from_bytes_be(&private.p);
404 let q = BigUint::from_bytes_be(&private.q);
405
406 let rsa = rsa::RsaPrivateKey::from_components(n, e, d, vec![p, q]);
407 let pem = rsa?.to_pkcs1_pem(rsa::pkcs1::LineEnding::LF);
408
409 EncodingKey::from_rsa_pem(pem?.as_bytes())?
410 }
411 };
412
413 Ok(self.encode.get_or_init(|| encoding_key))
414 }
415
416 pub fn decode(&self, token: &str) -> crate::Result<Claims> {
417 if !self.operations.contains(&KeyOperation::Verify) {
418 return Err(KeyError::VerifyUnsupported.into());
419 }
420
421 let decode = self.to_decoding_key()?;
422
423 let mut validation = jsonwebtoken::Validation::new(self.algorithm.into());
424 validation.required_spec_claims = Default::default(); validation.validate_exp = false; let token = jsonwebtoken::decode::<Claims>(token, decode, &validation)?;
428
429 if let Some(exp) = token.claims.expires
430 && exp < std::time::SystemTime::now()
431 {
432 return Err(crate::Error::TokenExpired);
433 }
434
435 token.claims.validate()?;
436
437 Ok(token.claims)
438 }
439
440 pub fn encode(&self, payload: &Claims) -> crate::Result<String> {
441 if !self.operations.contains(&KeyOperation::Sign) {
442 return Err(KeyError::SignUnsupported.into());
443 }
444
445 payload.validate()?;
446
447 let encode = self.to_encoding_key()?;
448
449 let mut header = Header::new(self.algorithm.into());
450 header.kid = self.kid.as_ref().map(|k| k.to_string());
451 let token = jsonwebtoken::encode(&header, &payload, encode)?;
452 Ok(token)
453 }
454
455 pub fn generate(algorithm: Algorithm, id: Option<crate::KeyId>) -> crate::Result<Self> {
457 generate(algorithm, id)
458 }
459}
460
461fn serialize_base64url<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
463where
464 S: Serializer,
465{
466 let encoded = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(bytes);
467 serializer.serialize_str(&encoded)
468}
469
470fn serialize_base64url_optional<S>(bytes: &Option<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error>
471where
472 S: Serializer,
473{
474 match bytes {
475 Some(b) => serialize_base64url(b, serializer),
476 None => serializer.serialize_none(),
477 }
478}
479
480fn deserialize_base64url<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
482where
483 D: Deserializer<'de>,
484{
485 let s = String::deserialize(deserializer)?;
486
487 base64::engine::general_purpose::URL_SAFE_NO_PAD
489 .decode(&s)
490 .or_else(|_| {
491 base64::engine::general_purpose::URL_SAFE.decode(&s)
493 })
494 .map_err(serde::de::Error::custom)
495}
496
497fn deserialize_base64url_optional<'de, D>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error>
498where
499 D: Deserializer<'de>,
500{
501 let s: Option<String> = Option::deserialize(deserializer)?;
502 match s {
503 Some(s) => {
504 let decoded = base64::engine::general_purpose::URL_SAFE_NO_PAD
505 .decode(&s)
506 .or_else(|_| base64::engine::general_purpose::URL_SAFE.decode(&s))
507 .map_err(serde::de::Error::custom)?;
508 Ok(Some(decoded))
509 }
510 None => Ok(None),
511 }
512}
513
514#[cfg(test)]
515mod tests {
516 use super::*;
517 use std::time::{Duration, SystemTime};
518
519 fn create_test_key() -> Key {
520 Key {
521 algorithm: Algorithm::HS256,
522 operations: [KeyOperation::Sign, KeyOperation::Verify].into(),
523 key: KeyType::OCT {
524 secret: b"test-secret-that-is-long-enough-for-hmac-sha256".to_vec(),
525 },
526 kid: Some(crate::KeyId::decode("test-key-1").unwrap()),
527 decode: Default::default(),
528 encode: Default::default(),
529 }
530 }
531
532 fn create_test_claims() -> Claims {
533 Claims {
534 root: "test-path".to_string(),
535 publish: vec!["test-pub".into()],
536 cluster: false,
537 subscribe: vec!["test-sub".into()],
538 expires: Some(SystemTime::now() + Duration::from_secs(3600)),
539 issued: Some(SystemTime::now()),
540 }
541 }
542
543 #[test]
544 fn test_key_from_str_valid() {
545 let key = create_test_key();
546 let json = key.to_str().unwrap();
547 let loaded_key = Key::from_str(&json).unwrap();
548
549 assert_eq!(loaded_key.algorithm, key.algorithm);
550 assert_eq!(loaded_key.operations, key.operations);
551 match (loaded_key.key, key.key) {
552 (KeyType::OCT { secret: loaded_secret }, KeyType::OCT { secret }) => {
553 assert_eq!(loaded_secret, secret);
554 }
555 _ => panic!("Expected OCT key"),
556 }
557 assert_eq!(loaded_key.kid, key.kid);
558 }
559
560 #[test]
562 fn test_key_oct_backwards_compatibility() {
563 let json = r#"{"alg":"HS256","key_ops":["sign","verify"],"k":"Fp8kipWUJeUFqeSqWym_tRC_tyI8z-QpqopIGrbrD68"}"#;
564 let key = Key::from_str(json);
565
566 assert!(key.is_ok());
567 let key = key.unwrap();
568
569 if let KeyType::OCT { ref secret, .. } = key.key {
570 let base64_key = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(secret);
571 assert_eq!(base64_key, "Fp8kipWUJeUFqeSqWym_tRC_tyI8z-QpqopIGrbrD68");
572 } else {
573 panic!("Expected OCT key");
574 }
575
576 let key_str = key.to_str().unwrap();
577
578 let loaded = Key::from_str(&key_str).unwrap();
580 assert_eq!(loaded.algorithm, Algorithm::HS256);
581 assert!(loaded.operations.contains(&KeyOperation::Sign));
582 assert!(loaded.operations.contains(&KeyOperation::Verify));
583 assert!(matches!(loaded.key, KeyType::OCT { .. }));
584 }
585
586 #[test]
587 fn test_key_from_str_invalid_json() {
588 let result = Key::from_str("invalid json");
589 assert!(result.is_err());
590 }
591
592 #[test]
593 fn test_key_to_str() {
594 let key = create_test_key();
595 let encoded = key.to_str().unwrap();
596
597 assert!(!encoded.contains('{'));
599
600 let loaded = Key::from_str(&encoded).unwrap();
602 assert_eq!(loaded.algorithm, Algorithm::HS256);
603 assert_eq!(loaded.kid, key.kid);
604 assert!(loaded.operations.contains(&KeyOperation::Sign));
605 assert!(loaded.operations.contains(&KeyOperation::Verify));
606 }
607
608 #[test]
609 fn test_key_sign_success() {
610 let key = create_test_key();
611 let claims = create_test_claims();
612 let token = key.encode(&claims).unwrap();
613
614 assert!(!token.is_empty());
615 assert_eq!(token.matches('.').count(), 2); }
617
618 #[test]
619 fn test_key_sign_no_permission() {
620 let mut key = create_test_key();
621 key.operations = [KeyOperation::Verify].into();
622 let claims = create_test_claims();
623
624 let result = key.encode(&claims);
625 assert!(result.is_err());
626 assert!(result.unwrap_err().to_string().contains("key does not support signing"));
627 }
628
629 #[test]
630 fn test_key_sign_invalid_claims() {
631 let key = create_test_key();
632 let invalid_claims = Claims {
633 root: "test-path".to_string(),
634 publish: vec![],
635 subscribe: vec![],
636 cluster: false,
637 expires: None,
638 issued: None,
639 };
640
641 let result = key.encode(&invalid_claims);
642 assert!(result.is_err());
643 assert!(
644 result
645 .unwrap_err()
646 .to_string()
647 .contains("no publish or subscribe allowed; token is useless")
648 );
649 }
650
651 #[test]
652 fn test_key_verify_success() {
653 let key = create_test_key();
654 let claims = create_test_claims();
655 let token = key.encode(&claims).unwrap();
656
657 let verified_claims = key.decode(&token).unwrap();
658 assert_eq!(verified_claims.root, claims.root);
659 assert_eq!(verified_claims.publish, claims.publish);
660 assert_eq!(verified_claims.subscribe, claims.subscribe);
661 assert_eq!(verified_claims.cluster, claims.cluster);
662 }
663
664 #[test]
665 fn test_key_verify_no_permission() {
666 let mut key = create_test_key();
667 key.operations = [KeyOperation::Sign].into();
668
669 let result = key.decode("some.jwt.token");
670 assert!(result.is_err());
671 assert!(
672 result
673 .unwrap_err()
674 .to_string()
675 .contains("key does not support verification")
676 );
677 }
678
679 #[test]
680 fn test_key_verify_invalid_token() {
681 let key = create_test_key();
682 let result = key.decode("invalid-token");
683 assert!(result.is_err());
684 }
685
686 #[test]
687 fn test_key_verify_path_mismatch() {
688 let key = create_test_key();
689 let claims = create_test_claims();
690 let token = key.encode(&claims).unwrap();
691
692 let result = key.decode(&token);
694 assert!(result.is_ok());
695 }
696
697 #[test]
698 fn test_key_verify_expired_token() {
699 let key = create_test_key();
700 let mut claims = create_test_claims();
701 claims.expires = Some(SystemTime::now() - Duration::from_secs(3600)); let token = key.encode(&claims).unwrap();
703
704 let result = key.decode(&token);
705 assert!(result.is_err());
706 }
707
708 #[test]
709 fn test_key_verify_token_without_exp() {
710 let key = create_test_key();
711 let claims = Claims {
712 root: "test-path".to_string(),
713 publish: vec!["".to_string()],
714 subscribe: vec!["".to_string()],
715 cluster: false,
716 expires: None,
717 issued: None,
718 };
719 let token = key.encode(&claims).unwrap();
720
721 let verified_claims = key.decode(&token).unwrap();
722 assert_eq!(verified_claims.root, claims.root);
723 assert_eq!(verified_claims.publish, claims.publish);
724 assert_eq!(verified_claims.subscribe, claims.subscribe);
725 assert_eq!(verified_claims.expires, None);
726 }
727
728 #[test]
729 fn test_key_round_trip() {
730 let key = create_test_key();
731 let original_claims = Claims {
732 root: "test-path".to_string(),
733 publish: vec!["test-pub".into()],
734 subscribe: vec!["test-sub".into()],
735 cluster: true,
736 expires: Some(SystemTime::now() + Duration::from_secs(3600)),
737 issued: Some(SystemTime::now()),
738 };
739
740 let token = key.encode(&original_claims).unwrap();
741 let verified_claims = key.decode(&token).unwrap();
742
743 assert_eq!(verified_claims.root, original_claims.root);
744 assert_eq!(verified_claims.publish, original_claims.publish);
745 assert_eq!(verified_claims.subscribe, original_claims.subscribe);
746 assert_eq!(verified_claims.cluster, original_claims.cluster);
747 }
748
749 #[test]
750 fn test_key_generate_hs256() {
751 let key = Key::generate(Algorithm::HS256, Some(crate::KeyId::decode("test-id").unwrap()));
752 assert!(key.is_ok());
753 let key = key.unwrap();
754
755 assert_eq!(key.algorithm, Algorithm::HS256);
756 assert_eq!(key.kid, Some(crate::KeyId::decode("test-id").unwrap()));
757 assert_eq!(key.operations, [KeyOperation::Sign, KeyOperation::Verify].into());
758
759 match key.key {
760 KeyType::OCT { ref secret } => assert_eq!(secret.len(), 32),
761 _ => panic!("Expected OCT key"),
762 }
763 }
764
765 #[test]
766 fn test_key_generate_hs384() {
767 let key = Key::generate(Algorithm::HS384, Some(crate::KeyId::decode("test-id").unwrap()));
768 assert!(key.is_ok());
769 let key = key.unwrap();
770
771 assert_eq!(key.algorithm, Algorithm::HS384);
772
773 match key.key {
774 KeyType::OCT { ref secret } => assert_eq!(secret.len(), 48),
775 _ => panic!("Expected OCT key"),
776 }
777 }
778
779 #[test]
780 fn test_key_generate_hs512() {
781 let key = Key::generate(Algorithm::HS512, Some(crate::KeyId::decode("test-id").unwrap()));
782 assert!(key.is_ok());
783 let key = key.unwrap();
784
785 assert_eq!(key.algorithm, Algorithm::HS512);
786
787 match key.key {
788 KeyType::OCT { ref secret } => assert_eq!(secret.len(), 64),
789 _ => panic!("Expected OCT key"),
790 }
791 }
792
793 #[test]
794 fn test_key_generate_rs512() {
795 let key = Key::generate(Algorithm::RS512, Some(crate::KeyId::decode("test-id").unwrap()));
796 assert!(key.is_ok());
797 let key = key.unwrap();
798
799 assert_eq!(key.algorithm, Algorithm::RS512);
800 assert!(matches!(key.key, KeyType::RSA { .. }));
801 match key.key {
802 KeyType::RSA {
803 ref public,
804 ref private,
805 } => {
806 assert!(private.is_some());
807 assert_eq!(public.n.len(), 256);
808 assert_eq!(public.e.len(), 3);
809 }
810 _ => panic!("Expected RSA key"),
811 }
812 }
813
814 #[test]
815 fn test_key_generate_es256() {
816 let key = Key::generate(Algorithm::ES256, Some(crate::KeyId::decode("test-id").unwrap()));
817 assert!(key.is_ok());
818 let key = key.unwrap();
819
820 assert_eq!(key.algorithm, Algorithm::ES256);
821 assert!(matches!(key.key, KeyType::EC { .. }))
822 }
823
824 #[test]
825 fn test_key_generate_ps512() {
826 let key = Key::generate(Algorithm::PS512, Some(crate::KeyId::decode("test-id").unwrap()));
827 assert!(key.is_ok());
828 let key = key.unwrap();
829
830 assert_eq!(key.algorithm, Algorithm::PS512);
831 assert!(matches!(key.key, KeyType::RSA { .. }));
832 }
833
834 #[test]
835 fn test_key_generate_eddsa() {
836 let key = Key::generate(Algorithm::EdDSA, Some(crate::KeyId::decode("test-id").unwrap()));
837 assert!(key.is_ok());
838 let key = key.unwrap();
839
840 assert_eq!(key.algorithm, Algorithm::EdDSA);
841 assert!(matches!(key.key, KeyType::OKP { .. }));
842 }
843
844 #[test]
845 fn test_key_generate_without_id() {
846 let key = Key::generate(Algorithm::HS256, None);
847 assert!(key.is_ok());
848 let key = key.unwrap();
849
850 assert_eq!(key.algorithm, Algorithm::HS256);
851 assert_eq!(key.kid, None);
852 assert_eq!(key.operations, [KeyOperation::Sign, KeyOperation::Verify].into());
853 }
854
855 #[test]
856 fn test_public_key_conversion_hmac() {
857 let key = Key::generate(Algorithm::HS256, Some(crate::KeyId::decode("test-id").unwrap()))
858 .expect("HMAC key generation failed");
859
860 assert!(key.to_public().is_err());
861 }
862
863 #[test]
864 fn test_public_key_conversion_rsa() {
865 let key = Key::generate(Algorithm::RS256, Some(crate::KeyId::decode("test-id").unwrap()));
866 assert!(key.is_ok());
867 let key = key.unwrap();
868
869 let public_key = key.to_public().unwrap();
870 assert_eq!(key.kid, public_key.kid);
871 assert_eq!(public_key.operations, [KeyOperation::Verify].into());
872 assert!(public_key.encode.get().is_none());
873 assert!(public_key.decode.get().is_none());
874 assert!(matches!(public_key.key, KeyType::RSA { .. }));
875
876 if let KeyType::RSA { public, private } = &public_key.key {
877 assert!(private.is_none());
878
879 if let KeyType::RSA { public: src_public, .. } = &key.key {
880 assert_eq!(public.e, src_public.e);
881 assert_eq!(public.n, src_public.n);
882 } else {
883 unreachable!("Expected RSA key")
884 }
885 } else {
886 unreachable!("Expected RSA key");
887 }
888 }
889
890 #[test]
891 fn test_public_key_conversion_es() {
892 let key = Key::generate(Algorithm::ES256, Some(crate::KeyId::decode("test-id").unwrap()));
893 assert!(key.is_ok());
894 let key = key.unwrap();
895
896 let public_key = key.to_public().unwrap();
897 assert_eq!(key.kid, public_key.kid);
898 assert_eq!(public_key.operations, [KeyOperation::Verify].into());
899 assert!(public_key.encode.get().is_none());
900 assert!(public_key.decode.get().is_none());
901 assert!(matches!(public_key.key, KeyType::EC { .. }));
902
903 if let KeyType::EC { x, y, d, curve } = &public_key.key {
904 assert!(d.is_none());
905
906 if let KeyType::EC {
907 x: src_x,
908 y: src_y,
909 curve: src_curve,
910 ..
911 } = &key.key
912 {
913 assert_eq!(x, src_x);
914 assert_eq!(y, src_y);
915 assert_eq!(curve, src_curve);
916 } else {
917 unreachable!("Expected EC key")
918 }
919 } else {
920 unreachable!("Expected EC key");
921 }
922 }
923
924 #[test]
925 fn test_public_key_conversion_ed() {
926 let key = Key::generate(Algorithm::EdDSA, Some(crate::KeyId::decode("test-id").unwrap()));
927 assert!(key.is_ok());
928 let key = key.unwrap();
929
930 let public_key = key.to_public().unwrap();
931 assert_eq!(key.kid, public_key.kid);
932 assert_eq!(public_key.operations, [KeyOperation::Verify].into());
933 assert!(public_key.encode.get().is_none());
934 assert!(public_key.decode.get().is_none());
935 assert!(matches!(public_key.key, KeyType::OKP { .. }));
936
937 if let KeyType::OKP { x, d, curve } = &public_key.key {
938 assert!(d.is_none());
939
940 if let KeyType::OKP {
941 x: src_x,
942 curve: src_curve,
943 ..
944 } = &key.key
945 {
946 assert_eq!(x, src_x);
947 assert_eq!(curve, src_curve);
948 } else {
949 unreachable!("Expected OKP key")
950 }
951 } else {
952 unreachable!("Expected OKP key");
953 }
954 }
955
956 #[test]
957 fn test_key_generate_sign_verify_cycle() {
958 let key = Key::generate(Algorithm::HS256, Some(crate::KeyId::decode("test-id").unwrap()));
959 assert!(key.is_ok());
960 let key = key.unwrap();
961
962 let claims = create_test_claims();
963
964 let token = key.encode(&claims).unwrap();
965 let verified_claims = key.decode(&token).unwrap();
966
967 assert_eq!(verified_claims.root, claims.root);
968 assert_eq!(verified_claims.publish, claims.publish);
969 assert_eq!(verified_claims.subscribe, claims.subscribe);
970 assert_eq!(verified_claims.cluster, claims.cluster);
971 }
972
973 #[test]
974 fn test_key_debug_no_secret() {
975 let key = create_test_key();
976 let debug_str = format!("{key:?}");
977
978 assert!(debug_str.contains("algorithm: HS256"));
979 assert!(debug_str.contains("operations"));
980 assert!(debug_str.contains("kid: Some(KeyId(\"test-key-1\"))"));
981 assert!(!debug_str.contains("secret")); }
983
984 #[test]
985 fn test_key_operations_enum() {
986 let sign_op = KeyOperation::Sign;
987 let verify_op = KeyOperation::Verify;
988 let decrypt_op = KeyOperation::Decrypt;
989 let encrypt_op = KeyOperation::Encrypt;
990
991 assert_eq!(sign_op, KeyOperation::Sign);
992 assert_eq!(verify_op, KeyOperation::Verify);
993 assert_eq!(decrypt_op, KeyOperation::Decrypt);
994 assert_eq!(encrypt_op, KeyOperation::Encrypt);
995
996 assert_ne!(sign_op, verify_op);
997 assert_ne!(decrypt_op, encrypt_op);
998 }
999
1000 #[test]
1001 fn test_key_operations_serde() {
1002 let operations = [KeyOperation::Sign, KeyOperation::Verify];
1003 let json = serde_json::to_string(&operations).unwrap();
1004 assert!(json.contains("\"sign\""));
1005 assert!(json.contains("\"verify\""));
1006
1007 let deserialized: Vec<KeyOperation> = serde_json::from_str(&json).unwrap();
1008 assert_eq!(deserialized, operations);
1009 }
1010
1011 #[test]
1012 fn test_key_serde() {
1013 let key = create_test_key();
1014 let json = serde_json::to_string(&key).unwrap();
1015 let deserialized: Key = serde_json::from_str(&json).unwrap();
1016
1017 assert_eq!(deserialized.algorithm, key.algorithm);
1018 assert_eq!(deserialized.operations, key.operations);
1019 assert_eq!(deserialized.kid, key.kid);
1020
1021 if let (
1022 KeyType::OCT {
1023 secret: original_secret,
1024 },
1025 KeyType::OCT {
1026 secret: deserialized_secret,
1027 },
1028 ) = (&key.key, &deserialized.key)
1029 {
1030 assert_eq!(deserialized_secret, original_secret);
1031 } else {
1032 panic!("Expected both keys to be OCT variant");
1033 }
1034 }
1035
1036 #[test]
1037 fn test_key_clone() {
1038 let key = create_test_key();
1039 let cloned = key.clone();
1040
1041 assert_eq!(cloned.algorithm, key.algorithm);
1042 assert_eq!(cloned.operations, key.operations);
1043 assert_eq!(cloned.kid, key.kid);
1044
1045 if let (
1046 KeyType::OCT {
1047 secret: original_secret,
1048 },
1049 KeyType::OCT { secret: cloned_secret },
1050 ) = (&key.key, &cloned.key)
1051 {
1052 assert_eq!(cloned_secret, original_secret);
1053 } else {
1054 panic!("Expected both keys to be OCT variant");
1055 }
1056 }
1057
1058 #[test]
1059 fn test_hmac_algorithms() {
1060 let key_256 = Key::generate(Algorithm::HS256, Some(crate::KeyId::decode("test-id").unwrap()));
1061 let key_384 = Key::generate(Algorithm::HS384, Some(crate::KeyId::decode("test-id").unwrap()));
1062 let key_512 = Key::generate(Algorithm::HS512, Some(crate::KeyId::decode("test-id").unwrap()));
1063
1064 let claims = create_test_claims();
1065
1066 for key in [key_256, key_384, key_512] {
1068 assert!(key.is_ok());
1069 let key = key.unwrap();
1070
1071 let token = key.encode(&claims).unwrap();
1072 let verified_claims = key.decode(&token).unwrap();
1073 assert_eq!(verified_claims.root, claims.root);
1074 }
1075 }
1076
1077 #[test]
1078 fn test_rsa_pkcs1_asymmetric_algorithms() {
1079 let key_rs256 = Key::generate(Algorithm::RS256, Some(crate::KeyId::decode("test-id").unwrap()));
1080 let key_rs384 = Key::generate(Algorithm::RS384, Some(crate::KeyId::decode("test-id").unwrap()));
1081 let key_rs512 = Key::generate(Algorithm::RS512, Some(crate::KeyId::decode("test-id").unwrap()));
1082
1083 for key in [key_rs256, key_rs384, key_rs512] {
1084 test_asymmetric_key(key);
1085 }
1086 }
1087
1088 #[test]
1089 fn test_rsa_pss_asymmetric_algorithms() {
1090 let key_ps256 = Key::generate(Algorithm::PS256, Some(crate::KeyId::decode("test-id").unwrap()));
1091 let key_ps384 = Key::generate(Algorithm::PS384, Some(crate::KeyId::decode("test-id").unwrap()));
1092 let key_ps512 = Key::generate(Algorithm::PS512, Some(crate::KeyId::decode("test-id").unwrap()));
1093
1094 for key in [key_ps256, key_ps384, key_ps512] {
1095 test_asymmetric_key(key);
1096 }
1097 }
1098
1099 #[test]
1100 fn test_ec_asymmetric_algorithms() {
1101 let key_es256 = Key::generate(Algorithm::ES256, Some(crate::KeyId::decode("test-id").unwrap()));
1102 let key_es384 = Key::generate(Algorithm::ES384, Some(crate::KeyId::decode("test-id").unwrap()));
1103
1104 for key in [key_es256, key_es384] {
1105 test_asymmetric_key(key);
1106 }
1107 }
1108
1109 #[test]
1110 fn test_ed_asymmetric_algorithms() {
1111 let key_eddsa = Key::generate(Algorithm::EdDSA, Some(crate::KeyId::decode("test-id").unwrap()));
1112
1113 test_asymmetric_key(key_eddsa);
1114 }
1115
1116 fn test_asymmetric_key(key: crate::Result<Key>) {
1117 assert!(key.is_ok());
1118 let key = key.unwrap();
1119
1120 let claims = create_test_claims();
1121 let token = key.encode(&claims).unwrap();
1122
1123 let private_verified_claims = key.decode(&token).unwrap();
1124 assert_eq!(
1125 private_verified_claims.root, claims.root,
1126 "validation using private key"
1127 );
1128
1129 let public_verified_claims = key.to_public().unwrap().decode(&token).unwrap();
1130 assert_eq!(public_verified_claims.root, claims.root, "validation using public key");
1131 }
1132
1133 #[test]
1134 fn test_cross_algorithm_verification_fails() {
1135 let key_256 = Key::generate(Algorithm::HS256, Some(crate::KeyId::decode("test-id").unwrap()));
1136 assert!(key_256.is_ok());
1137 let key_256 = key_256.unwrap();
1138
1139 let key_384 = Key::generate(Algorithm::HS384, Some(crate::KeyId::decode("test-id").unwrap()));
1140 assert!(key_384.is_ok());
1141 let key_384 = key_384.unwrap();
1142
1143 let claims = create_test_claims();
1144 let token = key_256.encode(&claims).unwrap();
1145
1146 let result = key_384.decode(&token);
1148 assert!(result.is_err());
1149 }
1150
1151 #[test]
1152 fn test_asymmetric_cross_algorithm_verification_fails() {
1153 let key_rs256 = Key::generate(Algorithm::RS256, Some(crate::KeyId::decode("test-id").unwrap()));
1154 assert!(key_rs256.is_ok());
1155 let key_rs256 = key_rs256.unwrap();
1156
1157 let key_ps256 = Key::generate(Algorithm::PS256, Some(crate::KeyId::decode("test-id").unwrap()));
1158 assert!(key_ps256.is_ok());
1159 let key_ps256 = key_ps256.unwrap();
1160
1161 let claims = create_test_claims();
1162 let token = key_rs256.encode(&claims).unwrap();
1163
1164 let private_result = key_ps256.decode(&token);
1166 let public_result = key_ps256.to_public().unwrap().decode(&token);
1167 assert!(private_result.is_err());
1168 assert!(public_result.is_err());
1169 }
1170
1171 #[test]
1172 fn test_rsa_pkcs1_public_key_conversion() {
1173 let key = Key::generate(Algorithm::RS256, Some(crate::KeyId::decode("test-id").unwrap()));
1174 assert!(key.is_ok());
1175 let key = key.unwrap();
1176
1177 assert!(key.operations.contains(&KeyOperation::Sign));
1178 assert!(key.operations.contains(&KeyOperation::Verify));
1179
1180 let public_key = key.to_public().unwrap();
1181 assert!(!public_key.operations.contains(&KeyOperation::Sign));
1182 assert!(public_key.operations.contains(&KeyOperation::Verify));
1183
1184 match key.key {
1185 KeyType::RSA {
1186 ref public,
1187 ref private,
1188 } => {
1189 assert!(private.is_some());
1190 assert_eq!(public.n.len(), 256);
1191 assert_eq!(public.e.len(), 3);
1192
1193 match public_key.key {
1194 KeyType::RSA {
1195 public: ref guest_public,
1196 private: ref public_private,
1197 } => {
1198 assert!(public_private.is_none());
1199 assert_eq!(public.n, guest_public.n);
1200 assert_eq!(public.e, guest_public.e);
1201 }
1202 _ => panic!("Expected public key to be an RSA key"),
1203 }
1204 }
1205 _ => panic!("Expected private key to be an RSA key"),
1206 }
1207 }
1208
1209 #[test]
1210 fn test_rsa_pss_public_key_conversion() {
1211 let key = Key::generate(Algorithm::PS384, Some(crate::KeyId::decode("test-id").unwrap()));
1212 assert!(key.is_ok());
1213 let key = key.unwrap();
1214
1215 assert!(key.operations.contains(&KeyOperation::Sign));
1216 assert!(key.operations.contains(&KeyOperation::Verify));
1217
1218 let public_key = key.to_public().unwrap();
1219 assert!(!public_key.operations.contains(&KeyOperation::Sign));
1220 assert!(public_key.operations.contains(&KeyOperation::Verify));
1221
1222 match key.key {
1223 KeyType::RSA {
1224 ref public,
1225 ref private,
1226 } => {
1227 assert!(private.is_some());
1228 assert_eq!(public.n.len(), 256);
1229 assert_eq!(public.e.len(), 3);
1230
1231 match public_key.key {
1232 KeyType::RSA {
1233 public: ref guest_public,
1234 private: ref public_private,
1235 } => {
1236 assert!(public_private.is_none());
1237 assert_eq!(public.n, guest_public.n);
1238 assert_eq!(public.e, guest_public.e);
1239 }
1240 _ => panic!("Expected public key to be an RSA key"),
1241 }
1242 }
1243 _ => panic!("Expected private key to be an RSA key"),
1244 }
1245 }
1246
1247 #[test]
1248 fn test_base64url_serialization() {
1249 let key = create_test_key();
1250 let json = serde_json::to_string(&key).unwrap();
1251
1252 let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
1254 let k_value = parsed["k"].as_str().unwrap();
1255
1256 assert!(!k_value.contains('='));
1258 assert!(!k_value.contains('+'));
1259 assert!(!k_value.contains('/'));
1260
1261 let decoded = base64::engine::general_purpose::URL_SAFE_NO_PAD
1263 .decode(k_value)
1264 .unwrap();
1265
1266 if let KeyType::OCT {
1267 secret: original_secret,
1268 } = &key.key
1269 {
1270 assert_eq!(decoded, *original_secret);
1271 } else {
1272 panic!("Expected both keys to be OCT variant");
1273 }
1274 }
1275
1276 #[test]
1277 fn test_backwards_compatibility_unpadded_base64url() {
1278 let unpadded_json = r#"{"kty":"oct","alg":"HS256","key_ops":["sign","verify"],"k":"dGVzdC1zZWNyZXQtdGhhdC1pcy1sb25nLWVub3VnaC1mb3ItaG1hYy1zaGEyNTY","kid":"test-key-1"}"#;
1280
1281 let key: Key = serde_json::from_str(unpadded_json).unwrap();
1283 assert_eq!(key.algorithm, Algorithm::HS256);
1284 assert_eq!(key.kid, Some(crate::KeyId::decode("test-key-1").unwrap()));
1285
1286 if let KeyType::OCT { secret } = &key.key {
1287 assert_eq!(secret, b"test-secret-that-is-long-enough-for-hmac-sha256");
1288 } else {
1289 panic!("Expected key to be OCT variant");
1290 }
1291 }
1292
1293 #[test]
1294 fn test_backwards_compatibility_padded_base64url() {
1295 let padded_json = r#"{"kty":"oct","alg":"HS256","key_ops":["sign","verify"],"k":"dGVzdC1zZWNyZXQtdGhhdC1pcy1sb25nLWVub3VnaC1mb3ItaG1hYy1zaGEyNTY=","kid":"test-key-1"}"#;
1297
1298 let key: Key = serde_json::from_str(padded_json).unwrap();
1300 assert_eq!(key.algorithm, Algorithm::HS256);
1301 assert_eq!(key.kid, Some(crate::KeyId::decode("test-key-1").unwrap()));
1302
1303 if let KeyType::OCT { secret } = &key.key {
1304 assert_eq!(secret, b"test-secret-that-is-long-enough-for-hmac-sha256");
1305 } else {
1306 panic!("Expected key to be OCT variant");
1307 }
1308 }
1309
1310 const JS_HS256_KEY: &str = r#"{"kty":"oct","alg":"HS256","k":"xm6xsSkfFqzPU3KfcbAcF2_h0OkStxQ_nNqVPYl0ync","kid":"js-test-key","key_ops":["sign","verify"],"guest":[],"guest_sub":[],"guest_pub":[]}"#;
1318
1319 const JS_HS256_TOKEN: &str = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImpzLXRlc3Qta2V5In0.eyJyb290IjoibGl2ZSIsInB1dCI6WyJjYW1lcmExIl0sImdldCI6WyJjYW1lcmExIiwiY2FtZXJhMiJdLCJpYXQiOjE3NzUxNzY3NTR9.tHNQtHh_HCIKxXOexDCM7AkjqWzbULLZzjEckfOGRfY";
1321
1322 const JS_EDDSA_PRIVATE_KEY: &str = r#"{"kty":"OKP","alg":"EdDSA","crv":"Ed25519","x":"UiU9fT_SdBBpkFtJPRCY0gX1jK_Dr9syYLFuEz4QUM4","d":"lm-L_PV3ksuQ-KrFBgFMDJqAZC3_Z6Z5UC4ZQY5OoDQ","kid":"js-eddsa-key","key_ops":["sign","verify"],"guest":[],"guest_sub":[],"guest_pub":[]}"#;
1324
1325 const JS_EDDSA_PUBLIC_KEY: &str = r#"{"kty":"OKP","alg":"EdDSA","crv":"Ed25519","x":"UiU9fT_SdBBpkFtJPRCY0gX1jK_Dr9syYLFuEz4QUM4","kid":"js-eddsa-key","guest":[],"guest_sub":[],"guest_pub":[],"key_ops":["verify"]}"#;
1327
1328 const JS_EDDSA_TOKEN: &str = "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCIsImtpZCI6ImpzLWVkZHNhLWtleSJ9.eyJyb290Ijoic3RyZWFtIiwicHV0IjpbInZpZGVvIl0sImlhdCI6MTc3NTE3Njc1Nn0.l9rUMHjPSXWKSXRP3mmeMgTAywtqpdqQehhViWaPrKxax1Y2D9KRIYTixYz-b6PI-AoHQYusHWeeLu_HRw2cAg";
1330
1331 #[test]
1332 fn test_js_hs256_key_load() {
1333 let key = Key::from_str(JS_HS256_KEY).unwrap();
1334 assert_eq!(key.algorithm, Algorithm::HS256);
1335 assert_eq!(key.kid, Some(crate::KeyId::decode("js-test-key").unwrap()));
1336 }
1337
1338 #[test]
1339 fn test_js_hs256_token_verify() {
1340 let key = Key::from_str(JS_HS256_KEY).unwrap();
1341 let claims = key.decode(JS_HS256_TOKEN).unwrap();
1342 assert_eq!(claims.root, "live");
1343 assert_eq!(claims.publish, vec!["camera1"]);
1344 assert_eq!(claims.subscribe, vec!["camera1", "camera2"]);
1345 }
1346
1347 #[test]
1348 fn test_js_hs256_sign_and_roundtrip() {
1349 let key = Key::from_str(JS_HS256_KEY).unwrap();
1350 let claims = Claims {
1351 root: "rust-test".to_string(),
1352 publish: vec!["pub1".into()],
1353 subscribe: vec!["sub1".into()],
1354 ..Default::default()
1355 };
1356 let token = key.encode(&claims).unwrap();
1357 let verified = key.decode(&token).unwrap();
1358 assert_eq!(verified.root, "rust-test");
1359 assert_eq!(verified.publish, vec!["pub1"]);
1360 }
1361
1362 #[test]
1363 fn test_js_eddsa_key_load() {
1364 let private_key = Key::from_str(JS_EDDSA_PRIVATE_KEY).unwrap();
1365 assert_eq!(private_key.algorithm, Algorithm::EdDSA);
1366 assert!(matches!(private_key.key, KeyType::OKP { .. }));
1367
1368 let public_key = Key::from_str(JS_EDDSA_PUBLIC_KEY).unwrap();
1369 assert_eq!(public_key.algorithm, Algorithm::EdDSA);
1370 }
1371
1372 #[test]
1373 fn test_js_eddsa_token_verify_with_private_key() {
1374 let key = Key::from_str(JS_EDDSA_PRIVATE_KEY).unwrap();
1375 let claims = key.decode(JS_EDDSA_TOKEN).unwrap();
1376 assert_eq!(claims.root, "stream");
1377 assert_eq!(claims.publish, vec!["video"]);
1378 }
1379
1380 #[test]
1381 fn test_js_eddsa_token_verify_with_public_key() {
1382 let key = Key::from_str(JS_EDDSA_PUBLIC_KEY).unwrap();
1383 let claims = key.decode(JS_EDDSA_TOKEN).unwrap();
1384 assert_eq!(claims.root, "stream");
1385 assert_eq!(claims.publish, vec!["video"]);
1386 }
1387
1388 #[test]
1389 fn test_js_token_wrong_key_fails() {
1390 let wrong_key = Key::generate(Algorithm::HS256, None).unwrap();
1392 let result = wrong_key.decode(JS_HS256_TOKEN);
1393 assert!(result.is_err());
1394 }
1395
1396 #[test]
1397 fn test_js_eddsa_token_wrong_key_fails() {
1398 let wrong_key = Key::from_str(JS_HS256_KEY).unwrap();
1400 let result = wrong_key.decode(JS_EDDSA_TOKEN);
1401 assert!(result.is_err());
1402 }
1403
1404 #[test]
1405 fn test_file_io_base64url() {
1406 let key = create_test_key();
1407 let temp_dir = std::env::temp_dir();
1408 let temp_path = temp_dir.join("test_jwk.key");
1409
1410 key.to_file(&temp_path).unwrap();
1412
1413 let contents = std::fs::read_to_string(&temp_path).unwrap();
1415
1416 assert!(!contents.contains('{'));
1418 assert!(!contents.contains('}'));
1419 assert!(!contents.contains('"'));
1420
1421 let decoded = base64::engine::general_purpose::URL_SAFE_NO_PAD
1423 .decode(&contents)
1424 .unwrap();
1425 let json_str = String::from_utf8(decoded).unwrap();
1426 let _: serde_json::Value = serde_json::from_str(&json_str).unwrap();
1427
1428 let loaded_key = Key::from_file(&temp_path).unwrap();
1430 assert_eq!(loaded_key.algorithm, key.algorithm);
1431 assert_eq!(loaded_key.operations, key.operations);
1432 assert_eq!(loaded_key.kid, key.kid);
1433
1434 if let (
1435 KeyType::OCT {
1436 secret: original_secret,
1437 },
1438 KeyType::OCT { secret: loaded_secret },
1439 ) = (&key.key, &loaded_key.key)
1440 {
1441 assert_eq!(loaded_secret, original_secret);
1442 } else {
1443 panic!("Expected both keys to be OCT variant");
1444 }
1445
1446 std::fs::remove_file(temp_path).ok();
1448 }
1449
1450 #[test]
1451 fn test_file_io_raw_json() {
1452 let key = create_test_key();
1453 let temp_dir = std::env::temp_dir();
1454 let temp_path = temp_dir.join("test_jwk_raw_json.key");
1455
1456 let json = serde_json::to_string(&key).unwrap();
1458 std::fs::write(&temp_path, &json).unwrap();
1459
1460 assert!(json.starts_with('{'));
1462
1463 let loaded_key = Key::from_file(&temp_path).unwrap();
1465 assert_eq!(loaded_key.algorithm, key.algorithm);
1466 assert_eq!(loaded_key.operations, key.operations);
1467 assert_eq!(loaded_key.kid, key.kid);
1468
1469 if let (
1470 KeyType::OCT {
1471 secret: original_secret,
1472 },
1473 KeyType::OCT { secret: loaded_secret },
1474 ) = (&key.key, &loaded_key.key)
1475 {
1476 assert_eq!(loaded_secret, original_secret);
1477 } else {
1478 panic!("Expected both keys to be OCT variant");
1479 }
1480
1481 std::fs::remove_file(temp_path).ok();
1483 }
1484}