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