1mod ec;
34mod okp;
35mod rsa;
36mod symmetric;
37pub mod thumbprint;
38
39pub use ec::{EcCurve, EcParams};
40pub use okp::{OkpCurve, OkpParams};
41pub use rsa::{RsaOtherPrime, RsaParams, RsaParamsBuilder};
42pub use symmetric::SymmetricParams;
43
44use std::collections::HashSet;
45
46use serde::{Deserialize, Deserializer, Serialize, Serializer};
47use zeroize::{Zeroize, ZeroizeOnDrop};
48
49use crate::encoding::Base64UrlBytes;
50use crate::error::{Error, ParseError, Result, ValidationError};
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
54pub enum KeyType {
55 Rsa,
57 Ec,
59 Symmetric,
61 Okp,
63}
64
65impl KeyType {
66 pub fn as_str(&self) -> &'static str {
68 match self {
69 KeyType::Rsa => "RSA",
70 KeyType::Ec => "EC",
71 KeyType::Symmetric => "oct",
72 KeyType::Okp => "OKP",
73 }
74 }
75}
76
77impl std::str::FromStr for KeyType {
78 type Err = Error;
79
80 fn from_str(s: &str) -> Result<Self> {
81 match s {
82 "RSA" => Ok(KeyType::Rsa),
83 "EC" => Ok(KeyType::Ec),
84 "oct" => Ok(KeyType::Symmetric),
85 "OKP" => Ok(KeyType::Okp),
86 _ => Err(Error::Parse(ParseError::UnknownKeyType(s.to_string()))),
87 }
88 }
89}
90
91impl Serialize for KeyType {
92 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
93 where
94 S: Serializer,
95 {
96 serializer.serialize_str(self.as_str())
97 }
98}
99
100impl<'de> Deserialize<'de> for KeyType {
101 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
102 where
103 D: Deserializer<'de>,
104 {
105 let s = String::deserialize(deserializer)?;
106 s.parse().map_err(serde::de::Error::custom)
107 }
108}
109
110#[derive(Debug, Clone, PartialEq, Eq, Hash)]
117pub enum KeyUse {
118 Signature,
120 Encryption,
122 Unknown(String),
127}
128
129impl KeyUse {
130 pub fn as_str(&self) -> &str {
132 match self {
133 KeyUse::Signature => "sig",
134 KeyUse::Encryption => "enc",
135 KeyUse::Unknown(s) => s.as_str(),
136 }
137 }
138
139 pub fn is_unknown(&self) -> bool {
141 matches!(self, KeyUse::Unknown(_))
142 }
143}
144
145impl std::fmt::Display for KeyUse {
146 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
147 write!(f, "{}", self.as_str())
148 }
149}
150
151impl Serialize for KeyUse {
152 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
153 where
154 S: Serializer,
155 {
156 serializer.serialize_str(self.as_str())
157 }
158}
159
160impl<'de> Deserialize<'de> for KeyUse {
161 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
162 where
163 D: Deserializer<'de>,
164 {
165 let s = String::deserialize(deserializer)?;
166 Ok(match s.as_str() {
167 "sig" => KeyUse::Signature,
168 "enc" => KeyUse::Encryption,
169 _ => KeyUse::Unknown(s),
170 })
171 }
172}
173
174#[derive(Debug, Clone, PartialEq, Eq, Hash)]
179pub enum KeyOperation {
180 Sign,
182 Verify,
184 Encrypt,
186 Decrypt,
188 WrapKey,
190 UnwrapKey,
192 DeriveKey,
194 DeriveBits,
196 Unknown(String),
201}
202
203impl KeyOperation {
204 pub fn as_str(&self) -> &str {
206 match self {
207 KeyOperation::Sign => "sign",
208 KeyOperation::Verify => "verify",
209 KeyOperation::Encrypt => "encrypt",
210 KeyOperation::Decrypt => "decrypt",
211 KeyOperation::WrapKey => "wrapKey",
212 KeyOperation::UnwrapKey => "unwrapKey",
213 KeyOperation::DeriveKey => "deriveKey",
214 KeyOperation::DeriveBits => "deriveBits",
215 KeyOperation::Unknown(s) => s.as_str(),
216 }
217 }
218
219 pub fn is_unknown(&self) -> bool {
221 matches!(self, KeyOperation::Unknown(_))
222 }
223}
224
225impl std::fmt::Display for KeyOperation {
226 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
227 write!(f, "{}", self.as_str())
228 }
229}
230
231impl Serialize for KeyOperation {
232 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
233 where
234 S: Serializer,
235 {
236 serializer.serialize_str(self.as_str())
237 }
238}
239
240impl<'de> Deserialize<'de> for KeyOperation {
241 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
242 where
243 D: Deserializer<'de>,
244 {
245 let s = String::deserialize(deserializer)?;
246 Ok(match s.as_str() {
247 "sign" => KeyOperation::Sign,
248 "verify" => KeyOperation::Verify,
249 "encrypt" => KeyOperation::Encrypt,
250 "decrypt" => KeyOperation::Decrypt,
251 "wrapKey" => KeyOperation::WrapKey,
252 "unwrapKey" => KeyOperation::UnwrapKey,
253 "deriveKey" => KeyOperation::DeriveKey,
254 "deriveBits" => KeyOperation::DeriveBits,
255 _ => KeyOperation::Unknown(s),
256 })
257 }
258}
259
260#[derive(Debug, Clone, PartialEq, Eq, Hash)]
265pub enum Algorithm {
266 Hs256,
269 Hs384,
271 Hs512,
273
274 Rs256,
277 Rs384,
279 Rs512,
281
282 Ps256,
285 Ps384,
287 Ps512,
289
290 Es256,
293 Es384,
295 Es512,
297 Es256k,
299
300 EdDsa,
303
304 RsaOaep,
307 RsaOaep256,
309 Rsa1_5,
311
312 A128kw,
315 A192kw,
317 A256kw,
319
320 Dir,
323
324 EcdhEs,
327 EcdhEsA128kw,
329 EcdhEsA192kw,
331 EcdhEsA256kw,
333
334 A128gcmkw,
337 A192gcmkw,
339 A256gcmkw,
341
342 Pbes2Hs256A128kw,
345 Pbes2Hs384A192kw,
347 Pbes2Hs512A256kw,
349
350 A128cbcHs256,
353 A192cbcHs384,
355 A256cbcHs512,
357 A128gcm,
359 A192gcm,
361 A256gcm,
363
364 Unknown(String),
369}
370
371impl Algorithm {
372 pub fn as_str(&self) -> &str {
377 match self {
378 Algorithm::Hs256 => "HS256",
379 Algorithm::Hs384 => "HS384",
380 Algorithm::Hs512 => "HS512",
381 Algorithm::Rs256 => "RS256",
382 Algorithm::Rs384 => "RS384",
383 Algorithm::Rs512 => "RS512",
384 Algorithm::Ps256 => "PS256",
385 Algorithm::Ps384 => "PS384",
386 Algorithm::Ps512 => "PS512",
387 Algorithm::Es256 => "ES256",
388 Algorithm::Es384 => "ES384",
389 Algorithm::Es512 => "ES512",
390 Algorithm::Es256k => "ES256K",
391 Algorithm::EdDsa => "EdDSA",
392 Algorithm::RsaOaep => "RSA-OAEP",
393 Algorithm::RsaOaep256 => "RSA-OAEP-256",
394 Algorithm::Rsa1_5 => "RSA1_5",
395 Algorithm::A128kw => "A128KW",
396 Algorithm::A192kw => "A192KW",
397 Algorithm::A256kw => "A256KW",
398 Algorithm::Dir => "dir",
399 Algorithm::EcdhEs => "ECDH-ES",
400 Algorithm::EcdhEsA128kw => "ECDH-ES+A128KW",
401 Algorithm::EcdhEsA192kw => "ECDH-ES+A192KW",
402 Algorithm::EcdhEsA256kw => "ECDH-ES+A256KW",
403 Algorithm::A128gcmkw => "A128GCMKW",
404 Algorithm::A192gcmkw => "A192GCMKW",
405 Algorithm::A256gcmkw => "A256GCMKW",
406 Algorithm::Pbes2Hs256A128kw => "PBES2-HS256+A128KW",
407 Algorithm::Pbes2Hs384A192kw => "PBES2-HS384+A192KW",
408 Algorithm::Pbes2Hs512A256kw => "PBES2-HS512+A256KW",
409 Algorithm::A128cbcHs256 => "A128CBC-HS256",
410 Algorithm::A192cbcHs384 => "A192CBC-HS384",
411 Algorithm::A256cbcHs512 => "A256CBC-HS512",
412 Algorithm::A128gcm => "A128GCM",
413 Algorithm::A192gcm => "A192GCM",
414 Algorithm::A256gcm => "A256GCM",
415 Algorithm::Unknown(s) => s.as_str(),
416 }
417 }
418
419 pub fn is_unknown(&self) -> bool {
421 matches!(self, Algorithm::Unknown(_))
422 }
423
424 pub fn is_signing(&self) -> bool {
428 matches!(
429 self,
430 Algorithm::Hs256
431 | Algorithm::Hs384
432 | Algorithm::Hs512
433 | Algorithm::Rs256
434 | Algorithm::Rs384
435 | Algorithm::Rs512
436 | Algorithm::Ps256
437 | Algorithm::Ps384
438 | Algorithm::Ps512
439 | Algorithm::Es256
440 | Algorithm::Es384
441 | Algorithm::Es512
442 | Algorithm::Es256k
443 | Algorithm::EdDsa
444 )
445 }
446
447 pub fn is_key_encryption(&self) -> bool {
451 matches!(
452 self,
453 Algorithm::RsaOaep
454 | Algorithm::RsaOaep256
455 | Algorithm::Rsa1_5
456 | Algorithm::A128kw
457 | Algorithm::A192kw
458 | Algorithm::A256kw
459 | Algorithm::Dir
460 | Algorithm::EcdhEs
461 | Algorithm::EcdhEsA128kw
462 | Algorithm::EcdhEsA192kw
463 | Algorithm::EcdhEsA256kw
464 | Algorithm::A128gcmkw
465 | Algorithm::A192gcmkw
466 | Algorithm::A256gcmkw
467 | Algorithm::Pbes2Hs256A128kw
468 | Algorithm::Pbes2Hs384A192kw
469 | Algorithm::Pbes2Hs512A256kw
470 )
471 }
472}
473
474impl std::fmt::Display for Algorithm {
475 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
476 write!(f, "{}", self.as_str())
477 }
478}
479
480impl std::str::FromStr for Algorithm {
481 type Err = std::convert::Infallible;
482
483 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
488 Ok(match s {
489 "HS256" => Algorithm::Hs256,
490 "HS384" => Algorithm::Hs384,
491 "HS512" => Algorithm::Hs512,
492 "RS256" => Algorithm::Rs256,
493 "RS384" => Algorithm::Rs384,
494 "RS512" => Algorithm::Rs512,
495 "PS256" => Algorithm::Ps256,
496 "PS384" => Algorithm::Ps384,
497 "PS512" => Algorithm::Ps512,
498 "ES256" => Algorithm::Es256,
499 "ES384" => Algorithm::Es384,
500 "ES512" => Algorithm::Es512,
501 "ES256K" => Algorithm::Es256k,
502 "EdDSA" => Algorithm::EdDsa,
503 "RSA-OAEP" => Algorithm::RsaOaep,
504 "RSA-OAEP-256" => Algorithm::RsaOaep256,
505 "RSA1_5" => Algorithm::Rsa1_5,
506 "A128KW" => Algorithm::A128kw,
507 "A192KW" => Algorithm::A192kw,
508 "A256KW" => Algorithm::A256kw,
509 "dir" => Algorithm::Dir,
510 "ECDH-ES" => Algorithm::EcdhEs,
511 "ECDH-ES+A128KW" => Algorithm::EcdhEsA128kw,
512 "ECDH-ES+A192KW" => Algorithm::EcdhEsA192kw,
513 "ECDH-ES+A256KW" => Algorithm::EcdhEsA256kw,
514 "A128GCMKW" => Algorithm::A128gcmkw,
515 "A192GCMKW" => Algorithm::A192gcmkw,
516 "A256GCMKW" => Algorithm::A256gcmkw,
517 "PBES2-HS256+A128KW" => Algorithm::Pbes2Hs256A128kw,
518 "PBES2-HS384+A192KW" => Algorithm::Pbes2Hs384A192kw,
519 "PBES2-HS512+A256KW" => Algorithm::Pbes2Hs512A256kw,
520 "A128CBC-HS256" => Algorithm::A128cbcHs256,
521 "A192CBC-HS384" => Algorithm::A192cbcHs384,
522 "A256CBC-HS512" => Algorithm::A256cbcHs512,
523 "A128GCM" => Algorithm::A128gcm,
524 "A192GCM" => Algorithm::A192gcm,
525 "A256GCM" => Algorithm::A256gcm,
526 _ => Algorithm::Unknown(s.to_string()),
527 })
528 }
529}
530
531impl Serialize for Algorithm {
532 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
533 where
534 S: Serializer,
535 {
536 serializer.serialize_str(self.as_str())
537 }
538}
539
540impl<'de> Deserialize<'de> for Algorithm {
541 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
542 where
543 D: Deserializer<'de>,
544 {
545 let s = String::deserialize(deserializer)?;
546 s.parse().map_err(serde::de::Error::custom)
547 }
548}
549
550#[derive(Clone, Zeroize, ZeroizeOnDrop)]
552pub enum KeyParams {
553 Rsa(RsaParams),
555 Ec(EcParams),
557 Symmetric(SymmetricParams),
559 Okp(OkpParams),
561}
562
563impl KeyParams {
564 pub fn is_public_key_only(&self) -> bool {
566 match self {
567 KeyParams::Rsa(p) => p.is_public_key_only(),
568 KeyParams::Ec(p) => p.is_public_key_only(),
569 KeyParams::Symmetric(p) => p.is_public_key_only(),
570 KeyParams::Okp(p) => p.is_public_key_only(),
571 }
572 }
573
574 pub fn has_private_key(&self) -> bool {
576 !self.is_public_key_only()
577 }
578
579 pub fn validate(&self) -> Result<()> {
581 match self {
582 KeyParams::Rsa(p) => p.validate(),
583 KeyParams::Ec(p) => p.validate(),
584 KeyParams::Symmetric(p) => p.validate(),
585 KeyParams::Okp(p) => p.validate(),
586 }
587 }
588}
589
590impl std::fmt::Debug for KeyParams {
591 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
592 match self {
593 KeyParams::Rsa(p) => write!(f, "KeyParams::Rsa({:?})", p),
594 KeyParams::Ec(p) => write!(f, "KeyParams::Ec({:?})", p),
595 KeyParams::Symmetric(p) => write!(f, "KeyParams::Symmetric({:?})", p),
596 KeyParams::Okp(p) => write!(f, "KeyParams::Okp({:?})", p),
597 }
598 }
599}
600
601impl PartialEq for KeyParams {
602 fn eq(&self, other: &Self) -> bool {
603 match (self, other) {
604 (KeyParams::Rsa(a), KeyParams::Rsa(b)) => a == b,
605 (KeyParams::Ec(a), KeyParams::Ec(b)) => a == b,
606 (KeyParams::Symmetric(a), KeyParams::Symmetric(b)) => a == b,
607 (KeyParams::Okp(a), KeyParams::Okp(b)) => a == b,
608 _ => false,
609 }
610 }
611}
612
613impl Eq for KeyParams {}
614
615#[derive(Clone, Zeroize, ZeroizeOnDrop)]
633pub struct Key {
634 #[zeroize(skip)]
636 pub kty: KeyType,
637
638 #[zeroize(skip)]
640 pub kid: Option<String>,
641
642 #[zeroize(skip)]
644 pub key_use: Option<KeyUse>,
645
646 #[zeroize(skip)]
648 pub key_ops: Option<Vec<KeyOperation>>,
649
650 #[zeroize(skip)]
652 pub alg: Option<Algorithm>,
653
654 pub params: KeyParams,
656
657 #[zeroize(skip)]
659 pub x5c: Option<Vec<String>>,
660
661 #[zeroize(skip)]
663 pub x5t: Option<String>,
664
665 #[zeroize(skip)]
667 #[allow(non_snake_case)]
668 pub x5t_s256: Option<String>,
669
670 #[zeroize(skip)]
672 pub x5u: Option<String>,
673}
674
675impl Key {
676 pub fn is_public_key_only(&self) -> bool {
678 self.params.is_public_key_only()
679 }
680
681 pub fn has_private_key(&self) -> bool {
683 self.params.has_private_key()
684 }
685
686 pub fn validate(&self) -> Result<()> {
696 let expected_kty = match &self.params {
698 KeyParams::Rsa(_) => KeyType::Rsa,
699 KeyParams::Ec(_) => KeyType::Ec,
700 KeyParams::Symmetric(_) => KeyType::Symmetric,
701 KeyParams::Okp(_) => KeyType::Okp,
702 };
703
704 if self.kty != expected_kty {
705 return Err(Error::Validation(ValidationError::InconsistentParameters(
706 format!(
707 "kty '{}' doesn't match key parameters (expected '{}')",
708 self.kty.as_str(),
709 expected_kty.as_str()
710 ),
711 )));
712 }
713
714 if self.key_use.is_some() && self.key_ops.is_some() {
716 return Err(Error::Validation(ValidationError::InconsistentParameters(
717 "RFC 7517: 'use' and 'key_ops' SHOULD NOT be used together".to_string(),
718 )));
719 }
720
721 if let Some(ref ops) = self.key_ops {
723 let mut seen = HashSet::new();
724 for op in ops {
725 if !seen.insert(op) {
726 return Err(Error::Validation(ValidationError::InconsistentParameters(
727 format!(
728 "RFC 7517: key_ops array contains duplicate value '{:?}'",
729 op
730 ),
731 )));
732 }
733 }
734 }
735
736 if let Some(ref url) = self.x5u
738 && !url.starts_with("https://") {
739 return Err(Error::Validation(ValidationError::InvalidParameter {
740 name: "x5u",
741 reason: "RFC 7517: x5u URL must use HTTPS for integrity protection".to_string(),
742 }));
743 }
744
745 if let Some(ref certs) = self.x5c {
747 for (i, cert) in certs.iter().enumerate() {
748 if cert.contains('-') || cert.contains('_') {
753 return Err(Error::Validation(ValidationError::InvalidParameter {
754 name: "x5c",
755 reason: format!(
756 "RFC 7517: x5c[{}] appears to be base64url encoded; must be standard base64",
757 i
758 ),
759 }));
760 }
761
762 if !is_valid_base64(cert) {
764 return Err(Error::Validation(ValidationError::InvalidParameter {
765 name: "x5c",
766 reason: format!("RFC 7517: x5c[{}] is not valid base64 encoding", i),
767 }));
768 }
769
770 use base64ct::{Base64, Encoding};
773 if let Ok(der_bytes) = Base64::decode_vec(cert) {
774 if !is_valid_der_certificate(&der_bytes) {
775 return Err(Error::Validation(ValidationError::InvalidParameter {
776 name: "x5c",
777 reason: format!(
778 "RFC 7517: x5c[{}] is not a valid DER-encoded X.509 certificate",
779 i
780 ),
781 }));
782 }
783 } else {
784 return Err(Error::Validation(ValidationError::InvalidParameter {
785 name: "x5c",
786 reason: format!("RFC 7517: x5c[{}] failed base64 decoding", i),
787 }));
788 }
789 }
790 }
791
792 if let Some(ref x5t) = self.x5t {
794 validate_x509_thumbprint(x5t, "x5t", 20)?;
795 }
796
797 if let Some(ref x5t_s256) = self.x5t_s256 {
799 validate_x509_thumbprint(x5t_s256, "x5t#S256", 32)?;
800 }
801
802 if let Some(ref alg) = self.alg {
804 self.validate_algorithm_key_type_match(alg)?;
805 }
806
807 self.params.validate()
809 }
810
811 fn validate_algorithm_key_type_match(&self, alg: &Algorithm) -> Result<()> {
813 if alg.is_unknown() {
816 return Ok(());
817 }
818
819 let valid = match (&self.params, alg) {
820 (KeyParams::Rsa(_), Algorithm::Rs256)
822 | (KeyParams::Rsa(_), Algorithm::Rs384)
823 | (KeyParams::Rsa(_), Algorithm::Rs512)
824 | (KeyParams::Rsa(_), Algorithm::Ps256)
825 | (KeyParams::Rsa(_), Algorithm::Ps384)
826 | (KeyParams::Rsa(_), Algorithm::Ps512)
827 | (KeyParams::Rsa(_), Algorithm::RsaOaep)
828 | (KeyParams::Rsa(_), Algorithm::RsaOaep256)
829 | (KeyParams::Rsa(_), Algorithm::Rsa1_5) => true,
830
831 (KeyParams::Symmetric(_), Algorithm::Hs256)
833 | (KeyParams::Symmetric(_), Algorithm::Hs384)
834 | (KeyParams::Symmetric(_), Algorithm::Hs512) => true,
835
836 (KeyParams::Symmetric(_), Algorithm::A128kw)
838 | (KeyParams::Symmetric(_), Algorithm::A192kw)
839 | (KeyParams::Symmetric(_), Algorithm::A256kw)
840 | (KeyParams::Symmetric(_), Algorithm::A128gcmkw)
841 | (KeyParams::Symmetric(_), Algorithm::A192gcmkw)
842 | (KeyParams::Symmetric(_), Algorithm::A256gcmkw)
843 | (KeyParams::Symmetric(_), Algorithm::Dir) => true,
844
845 (KeyParams::Symmetric(_), Algorithm::A128cbcHs256)
847 | (KeyParams::Symmetric(_), Algorithm::A192cbcHs384)
848 | (KeyParams::Symmetric(_), Algorithm::A256cbcHs512)
849 | (KeyParams::Symmetric(_), Algorithm::A128gcm)
850 | (KeyParams::Symmetric(_), Algorithm::A192gcm)
851 | (KeyParams::Symmetric(_), Algorithm::A256gcm) => true,
852
853 (KeyParams::Symmetric(_), Algorithm::Pbes2Hs256A128kw)
855 | (KeyParams::Symmetric(_), Algorithm::Pbes2Hs384A192kw)
856 | (KeyParams::Symmetric(_), Algorithm::Pbes2Hs512A256kw) => true,
857
858 (KeyParams::Ec(ec), Algorithm::Es256) => ec.crv == EcCurve::P256,
860 (KeyParams::Ec(ec), Algorithm::Es384) => ec.crv == EcCurve::P384,
861 (KeyParams::Ec(ec), Algorithm::Es512) => ec.crv == EcCurve::P521,
862 (KeyParams::Ec(ec), Algorithm::Es256k) => ec.crv == EcCurve::Secp256k1,
863
864 (KeyParams::Ec(_), Algorithm::EcdhEs)
866 | (KeyParams::Ec(_), Algorithm::EcdhEsA128kw)
867 | (KeyParams::Ec(_), Algorithm::EcdhEsA192kw)
868 | (KeyParams::Ec(_), Algorithm::EcdhEsA256kw) => true,
869
870 (KeyParams::Okp(okp), Algorithm::EdDsa) => {
872 okp.crv == OkpCurve::Ed25519 || okp.crv == OkpCurve::Ed448
873 }
874
875 (KeyParams::Okp(okp), Algorithm::EcdhEs)
877 | (KeyParams::Okp(okp), Algorithm::EcdhEsA128kw)
878 | (KeyParams::Okp(okp), Algorithm::EcdhEsA192kw)
879 | (KeyParams::Okp(okp), Algorithm::EcdhEsA256kw) => {
880 okp.crv == OkpCurve::X25519 || okp.crv == OkpCurve::X448
881 }
882
883 _ => false,
885 };
886
887 if !valid {
888 return Err(Error::Validation(ValidationError::InconsistentParameters(
889 format!(
890 "algorithm '{}' is not compatible with key type '{}'",
891 alg.as_str(),
892 self.kty.as_str()
893 ),
894 )));
895 }
896
897 Ok(())
898 }
899
900 #[must_use]
905 pub fn thumbprint(&self) -> String {
906 thumbprint::calculate_thumbprint(self)
907 }
908
909 pub fn as_rsa(&self) -> Option<&RsaParams> {
911 match &self.params {
912 KeyParams::Rsa(p) => Some(p),
913 _ => None,
914 }
915 }
916
917 pub fn as_ec(&self) -> Option<&EcParams> {
919 match &self.params {
920 KeyParams::Ec(p) => Some(p),
921 _ => None,
922 }
923 }
924
925 pub fn as_symmetric(&self) -> Option<&SymmetricParams> {
927 match &self.params {
928 KeyParams::Symmetric(p) => Some(p),
929 _ => None,
930 }
931 }
932
933 pub fn as_okp(&self) -> Option<&OkpParams> {
935 match &self.params {
936 KeyParams::Okp(p) => Some(p),
937 _ => None,
938 }
939 }
940
941 #[must_use]
969 pub fn to_public(&self) -> Option<Key> {
970 let public_params = match &self.params {
971 KeyParams::Rsa(p) => KeyParams::Rsa(p.to_public()),
972 KeyParams::Ec(p) => KeyParams::Ec(p.to_public()),
973 KeyParams::Okp(p) => KeyParams::Okp(p.to_public()),
974 KeyParams::Symmetric(_) => return None, };
976
977 Some(Key {
978 kty: self.kty,
979 kid: self.kid.clone(),
980 key_use: self.key_use.clone(),
981 key_ops: self.key_ops.clone(),
982 alg: self.alg.clone(),
983 params: public_params,
984 x5c: self.x5c.clone(),
985 x5t: self.x5t.clone(),
986 x5t_s256: self.x5t_s256.clone(),
987 x5u: self.x5u.clone(),
988 })
989 }
990}
991
992impl std::fmt::Debug for Key {
993 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
994 f.debug_struct("Key")
995 .field("kty", &self.kty)
996 .field("kid", &self.kid)
997 .field("key_use", &self.key_use)
998 .field("alg", &self.alg)
999 .field("params", &self.params)
1000 .finish()
1001 }
1002}
1003
1004impl PartialEq for Key {
1005 fn eq(&self, other: &Self) -> bool {
1006 self.kty == other.kty
1007 && self.kid == other.kid
1008 && self.key_use == other.key_use
1009 && self.key_ops == other.key_ops
1010 && self.alg == other.alg
1011 && self.params == other.params
1012 }
1013}
1014
1015impl Eq for Key {}
1016
1017impl Serialize for Key {
1019 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
1020 where
1021 S: Serializer,
1022 {
1023 use serde::ser::SerializeMap;
1024
1025 let mut field_count = 1; if self.kid.is_some() {
1028 field_count += 1;
1029 }
1030 if self.key_use.is_some() {
1031 field_count += 1;
1032 }
1033 if self.key_ops.is_some() {
1034 field_count += 1;
1035 }
1036 if self.alg.is_some() {
1037 field_count += 1;
1038 }
1039 if self.x5c.is_some() {
1040 field_count += 1;
1041 }
1042 if self.x5t.is_some() {
1043 field_count += 1;
1044 }
1045 if self.x5t_s256.is_some() {
1046 field_count += 1;
1047 }
1048 if self.x5u.is_some() {
1049 field_count += 1;
1050 }
1051
1052 field_count += match &self.params {
1054 KeyParams::Rsa(p) => {
1055 2 + if p.d.is_some() { 1 } else { 0 }
1056 + if p.p.is_some() { 1 } else { 0 }
1057 + if p.q.is_some() { 1 } else { 0 }
1058 + if p.dp.is_some() { 1 } else { 0 }
1059 + if p.dq.is_some() { 1 } else { 0 }
1060 + if p.qi.is_some() { 1 } else { 0 }
1061 + if p.oth.is_some() { 1 } else { 0 }
1062 }
1063 KeyParams::Ec(p) => 3 + if p.d.is_some() { 1 } else { 0 },
1064 KeyParams::Symmetric(_) => 1,
1065 KeyParams::Okp(p) => 2 + if p.d.is_some() { 1 } else { 0 },
1066 };
1067
1068 let mut map = serializer.serialize_map(Some(field_count))?;
1069
1070 map.serialize_entry("kty", self.kty.as_str())?;
1072
1073 if let Some(ref kid) = self.kid {
1075 map.serialize_entry("kid", kid)?;
1076 }
1077 if let Some(ref use_) = self.key_use {
1078 map.serialize_entry("use", use_)?;
1079 }
1080 if let Some(ref key_ops) = self.key_ops {
1081 map.serialize_entry("key_ops", key_ops)?;
1082 }
1083 if let Some(ref alg) = self.alg {
1084 map.serialize_entry("alg", alg)?;
1085 }
1086
1087 match &self.params {
1089 KeyParams::Rsa(p) => {
1090 map.serialize_entry("n", &p.n)?;
1091 map.serialize_entry("e", &p.e)?;
1092 if let Some(ref d) = p.d {
1093 map.serialize_entry("d", d)?;
1094 }
1095 if let Some(ref p_val) = p.p {
1096 map.serialize_entry("p", p_val)?;
1097 }
1098 if let Some(ref q) = p.q {
1099 map.serialize_entry("q", q)?;
1100 }
1101 if let Some(ref dp) = p.dp {
1102 map.serialize_entry("dp", dp)?;
1103 }
1104 if let Some(ref dq) = p.dq {
1105 map.serialize_entry("dq", dq)?;
1106 }
1107 if let Some(ref qi) = p.qi {
1108 map.serialize_entry("qi", qi)?;
1109 }
1110 if let Some(ref oth) = p.oth {
1111 map.serialize_entry("oth", oth)?;
1112 }
1113 }
1114 KeyParams::Ec(p) => {
1115 map.serialize_entry("crv", &p.crv)?;
1116 map.serialize_entry("x", &p.x)?;
1117 map.serialize_entry("y", &p.y)?;
1118 if let Some(ref d) = p.d {
1119 map.serialize_entry("d", d)?;
1120 }
1121 }
1122 KeyParams::Symmetric(p) => {
1123 map.serialize_entry("k", &p.k)?;
1124 }
1125 KeyParams::Okp(p) => {
1126 map.serialize_entry("crv", &p.crv)?;
1127 map.serialize_entry("x", &p.x)?;
1128 if let Some(ref d) = p.d {
1129 map.serialize_entry("d", d)?;
1130 }
1131 }
1132 }
1133
1134 if let Some(ref x5c) = self.x5c {
1136 map.serialize_entry("x5c", x5c)?;
1137 }
1138 if let Some(ref x5t) = self.x5t {
1139 map.serialize_entry("x5t", x5t)?;
1140 }
1141 if let Some(ref x5t_s256) = self.x5t_s256 {
1142 map.serialize_entry("x5t#S256", x5t_s256)?;
1143 }
1144 if let Some(ref x5u) = self.x5u {
1145 map.serialize_entry("x5u", x5u)?;
1146 }
1147
1148 map.end()
1149 }
1150}
1151
1152impl<'de> Deserialize<'de> for Key {
1154 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
1155 where
1156 D: Deserializer<'de>,
1157 {
1158 #[derive(Deserialize)]
1159 struct RawJwk {
1160 kty: String,
1161 kid: Option<String>,
1162 #[serde(rename = "use")]
1163 key_use: Option<KeyUse>,
1164 key_ops: Option<Vec<KeyOperation>>,
1165 alg: Option<Algorithm>,
1166
1167 n: Option<Base64UrlBytes>,
1169 e: Option<Base64UrlBytes>,
1170
1171 crv: Option<String>,
1173 x: Option<Base64UrlBytes>,
1174 y: Option<Base64UrlBytes>,
1175
1176 d: Option<Base64UrlBytes>,
1178
1179 p: Option<Base64UrlBytes>,
1181 q: Option<Base64UrlBytes>,
1182 dp: Option<Base64UrlBytes>,
1183 dq: Option<Base64UrlBytes>,
1184 qi: Option<Base64UrlBytes>,
1185
1186 oth: Option<Vec<rsa::RsaOtherPrime>>,
1188
1189 k: Option<Base64UrlBytes>,
1191
1192 x5c: Option<Vec<String>>,
1194 x5t: Option<String>,
1195 #[serde(rename = "x5t#S256")]
1196 x5t_s256: Option<String>,
1197 x5u: Option<String>,
1198 }
1199
1200 let raw = RawJwk::deserialize(deserializer)?;
1201
1202 let kty: KeyType = raw.kty.parse().map_err(serde::de::Error::custom)?;
1203
1204 let params = match kty {
1205 KeyType::Rsa => {
1206 let n = raw
1207 .n
1208 .ok_or_else(|| serde::de::Error::missing_field("n"))?;
1209 let e = raw
1210 .e
1211 .ok_or_else(|| serde::de::Error::missing_field("e"))?;
1212
1213 KeyParams::Rsa(RsaParams {
1214 n,
1215 e,
1216 d: raw.d,
1217 p: raw.p,
1218 q: raw.q,
1219 dp: raw.dp,
1220 dq: raw.dq,
1221 qi: raw.qi,
1222 oth: raw.oth,
1223 })
1224 }
1225 KeyType::Ec => {
1226 let crv_str = raw
1227 .crv
1228 .ok_or_else(|| serde::de::Error::missing_field("crv"))?;
1229 let crv: EcCurve = crv_str.parse().map_err(serde::de::Error::custom)?;
1230 let x = raw
1231 .x
1232 .ok_or_else(|| serde::de::Error::missing_field("x"))?;
1233 let y = raw
1234 .y
1235 .ok_or_else(|| serde::de::Error::missing_field("y"))?;
1236
1237 KeyParams::Ec(EcParams {
1238 crv,
1239 x,
1240 y,
1241 d: raw.d,
1242 })
1243 }
1244 KeyType::Symmetric => {
1245 let k = raw
1246 .k
1247 .ok_or_else(|| serde::de::Error::missing_field("k"))?;
1248
1249 KeyParams::Symmetric(SymmetricParams { k })
1250 }
1251 KeyType::Okp => {
1252 let crv_str = raw
1253 .crv
1254 .ok_or_else(|| serde::de::Error::missing_field("crv"))?;
1255 let crv: OkpCurve = crv_str.parse().map_err(serde::de::Error::custom)?;
1256 let x = raw
1257 .x
1258 .ok_or_else(|| serde::de::Error::missing_field("x"))?;
1259
1260 KeyParams::Okp(OkpParams { crv, x, d: raw.d })
1261 }
1262 };
1263
1264 Ok(Key {
1265 kty,
1266 kid: raw.kid,
1267 key_use: raw.key_use,
1268 key_ops: raw.key_ops,
1269 alg: raw.alg,
1270 params,
1271 x5c: raw.x5c,
1272 x5t: raw.x5t,
1273 x5t_s256: raw.x5t_s256,
1274 x5u: raw.x5u,
1275 })
1276 }
1277}
1278
1279fn is_valid_der_certificate(der: &[u8]) -> bool {
1289 if der.len() < 100 {
1291 return false;
1292 }
1293
1294 if der[0] != 0x30 {
1296 return false;
1297 }
1298
1299 let (content_len, header_len) = match parse_der_length(&der[1..]) {
1301 Some((len, hlen)) => (len, hlen + 1), None => return false,
1303 };
1304
1305 let expected_len = header_len + content_len;
1307 if der.len() < expected_len {
1308 return false;
1309 }
1310
1311 let content_start = header_len;
1313 if der.get(content_start) != Some(&0x30) {
1314 return false;
1315 }
1316
1317 true
1318}
1319
1320fn parse_der_length(data: &[u8]) -> Option<(usize, usize)> {
1322 if data.is_empty() {
1323 return None;
1324 }
1325
1326 let first = data[0];
1327 if first < 0x80 {
1328 Some((first as usize, 1))
1330 } else if first == 0x80 {
1331 None
1333 } else {
1334 let num_bytes = (first & 0x7f) as usize;
1336 if num_bytes > 4 || data.len() < 1 + num_bytes {
1337 return None;
1338 }
1339
1340 let mut length: usize = 0;
1341 for &b in &data[1..1 + num_bytes] {
1342 length = length.checked_mul(256)?.checked_add(b as usize)?;
1343 }
1344
1345 Some((length, 1 + num_bytes))
1346 }
1347}
1348
1349fn is_valid_base64(s: &str) -> bool {
1352 if s.is_empty() {
1353 return false;
1354 }
1355
1356 let bytes = s.as_bytes();
1357 let mut padding_started = false;
1358
1359 for (i, &b) in bytes.iter().enumerate() {
1360 match b {
1361 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'+' | b'/' => {
1362 if padding_started {
1363 return false; }
1365 }
1366 b'=' => {
1367 padding_started = true;
1368 let remaining = bytes.len() - i;
1370 if remaining > 2 {
1371 return false;
1372 }
1373 }
1374 _ => return false, }
1376 }
1377
1378 let len = s.len();
1381 if padding_started {
1382 len.is_multiple_of(4)
1383 } else {
1384 len % 4 != 1
1386 }
1387}
1388
1389fn validate_x509_thumbprint(thumbprint: &str, param_name: &'static str, expected_bytes: usize) -> Result<()> {
1395 use base64ct::{Base64UrlUnpadded, Encoding};
1396
1397 if !is_valid_base64url(thumbprint) {
1399 return Err(Error::Validation(ValidationError::InvalidParameter {
1400 name: param_name,
1401 reason: format!(
1402 "RFC 7517: {} must be base64url-encoded (invalid characters found)",
1403 param_name
1404 ),
1405 }));
1406 }
1407
1408 match Base64UrlUnpadded::decode_vec(thumbprint) {
1410 Ok(decoded) => {
1411 if decoded.len() != expected_bytes {
1412 return Err(Error::Validation(ValidationError::InvalidParameter {
1413 name: param_name,
1414 reason: format!(
1415 "RFC 7517: {} must be {} bytes when decoded (got {} bytes)",
1416 param_name,
1417 expected_bytes,
1418 decoded.len()
1419 ),
1420 }));
1421 }
1422 Ok(())
1423 }
1424 Err(_) => Err(Error::Validation(ValidationError::InvalidParameter {
1425 name: param_name,
1426 reason: format!("RFC 7517: {} failed base64url decoding", param_name),
1427 })),
1428 }
1429}
1430
1431fn is_valid_base64url(s: &str) -> bool {
1434 if s.is_empty() {
1435 return false;
1436 }
1437
1438 for b in s.bytes() {
1439 match b {
1440 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' => {}
1441 _ => return false,
1442 }
1443 }
1444
1445 s.len() % 4 != 1
1447}
1448
1449#[cfg(test)]
1450mod tests {
1451 use super::*;
1452
1453 #[test]
1454 fn test_parse_rsa_public_key() {
1455 let json = r#"{
1456 "kty": "RSA",
1457 "kid": "test-key",
1458 "use": "sig",
1459 "alg": "RS256",
1460 "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
1461 "e": "AQAB"
1462 }"#;
1463
1464 let jwk: Key = serde_json::from_str(json).unwrap();
1465 assert_eq!(jwk.kty, KeyType::Rsa);
1466 assert_eq!(jwk.kid, Some("test-key".to_string()));
1467 assert_eq!(jwk.key_use, Some(KeyUse::Signature));
1468 assert_eq!(jwk.alg, Some(Algorithm::Rs256));
1469 assert!(jwk.is_public_key_only());
1470 }
1471
1472 #[test]
1473 fn test_parse_ec_public_key() {
1474 let json = r#"{
1475 "kty": "EC",
1476 "crv": "P-256",
1477 "x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
1478 "y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM"
1479 }"#;
1480
1481 let jwk: Key = serde_json::from_str(json).unwrap();
1482 assert_eq!(jwk.kty, KeyType::Ec);
1483
1484 let ec = jwk.as_ec().unwrap();
1485 assert_eq!(ec.crv, EcCurve::P256);
1486 assert!(jwk.is_public_key_only());
1487 }
1488
1489 #[test]
1490 fn test_parse_symmetric_key() {
1491 let json = r#"{
1492 "kty": "oct",
1493 "k": "GawgguFyGrWKav7AX4VKUg"
1494 }"#;
1495
1496 let jwk: Key = serde_json::from_str(json).unwrap();
1497 assert_eq!(jwk.kty, KeyType::Symmetric);
1498 assert!(jwk.as_symmetric().is_some());
1499 }
1500
1501 #[test]
1502 fn test_parse_okp_key() {
1503 let json = r#"{
1504 "kty": "OKP",
1505 "crv": "Ed25519",
1506 "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"
1507 }"#;
1508
1509 let jwk: Key = serde_json::from_str(json).unwrap();
1510 assert_eq!(jwk.kty, KeyType::Okp);
1511
1512 let okp = jwk.as_okp().unwrap();
1513 assert_eq!(okp.crv, OkpCurve::Ed25519);
1514 }
1515
1516 #[test]
1517 fn test_roundtrip_serialization() {
1518 let json = r#"{"kty":"RSA","kid":"test","use":"sig","n":"AQAB","e":"AQAB"}"#;
1519 let jwk: Key = serde_json::from_str(json).unwrap();
1520 let serialized = serde_json::to_string(&jwk).unwrap();
1521 let deserialized: Key = serde_json::from_str(&serialized).unwrap();
1522 assert_eq!(jwk, deserialized);
1523 }
1524}