1mod ec;
37mod okp;
38mod rsa;
39mod symmetric;
40pub(crate) mod thumbprint;
41
42pub use ec::{EcCurve, EcParams};
43pub use okp::{OkpCurve, OkpParams};
44pub use rsa::{RsaOtherPrime, RsaParams, RsaParamsBuilder};
45pub use symmetric::SymmetricParams;
46
47use std::collections::HashSet;
48use std::convert::Infallible;
49use std::fmt::{self, Debug, Display};
50use std::hash::{Hash, Hasher};
51use std::str::FromStr;
52
53use base64ct::{Base64UrlUnpadded, Encoding};
54use serde::{Deserialize, Deserializer, Serialize, Serializer};
55use sha1::{Digest as Sha1Digest, Sha1};
56use sha2::Sha256;
57use url::Url;
58use x509_parser::prelude::parse_x509_certificate;
59use zeroize::{Zeroize, ZeroizeOnDrop};
60
61use crate::encoding::Base64UrlBytes;
62use crate::error::{Error, IncompatibleKeyError, InvalidKeyError, ParseError, Result};
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
66#[non_exhaustive]
67pub enum KeyType {
68 Rsa,
70 Ec,
72 Symmetric,
74 Okp,
76}
77
78impl KeyType {
79 pub fn as_str(&self) -> &'static str {
81 match self {
82 KeyType::Rsa => "RSA",
83 KeyType::Ec => "EC",
84 KeyType::Symmetric => "oct",
85 KeyType::Okp => "OKP",
86 }
87 }
88}
89
90impl Display for KeyType {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 write!(f, "{}", self.as_str())
93 }
94}
95
96impl FromStr for KeyType {
97 type Err = Error;
98
99 fn from_str(s: &str) -> Result<Self> {
100 match s {
101 "RSA" => Ok(KeyType::Rsa),
102 "EC" => Ok(KeyType::Ec),
103 "oct" => Ok(KeyType::Symmetric),
104 "OKP" => Ok(KeyType::Okp),
105 _ => Err(Error::Parse(ParseError::UnknownKeyType(s.to_string()))),
106 }
107 }
108}
109
110impl Serialize for KeyType {
111 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
112 where
113 S: Serializer,
114 {
115 serializer.serialize_str(self.as_str())
116 }
117}
118
119impl<'de> Deserialize<'de> for KeyType {
120 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
121 where
122 D: Deserializer<'de>,
123 {
124 String::deserialize(deserializer)?
125 .parse()
126 .map_err(serde::de::Error::custom)
127 }
128}
129
130#[derive(Debug, Clone, PartialEq, Eq, Hash)]
137#[non_exhaustive]
138pub enum KeyUse {
139 Signature,
141 Encryption,
143 Unknown(String),
148}
149
150impl KeyUse {
151 pub fn as_str(&self) -> &str {
153 match self {
154 KeyUse::Signature => "sig",
155 KeyUse::Encryption => "enc",
156 KeyUse::Unknown(s) => s.as_str(),
157 }
158 }
159}
160
161impl Display for KeyUse {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 write!(f, "{}", self.as_str())
164 }
165}
166
167impl From<&str> for KeyUse {
168 fn from(s: &str) -> Self {
172 match s {
173 "sig" => KeyUse::Signature,
174 "enc" => KeyUse::Encryption,
175 _ => KeyUse::Unknown(s.to_string()),
176 }
177 }
178}
179
180impl FromStr for KeyUse {
181 type Err = Infallible;
182
183 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
184 Ok(Self::from(s))
185 }
186}
187
188impl Serialize for KeyUse {
189 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
190 where
191 S: Serializer,
192 {
193 serializer.serialize_str(self.as_str())
194 }
195}
196
197impl<'de> Deserialize<'de> for KeyUse {
198 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
199 where
200 D: Deserializer<'de>,
201 {
202 Ok(KeyUse::from(String::deserialize(deserializer)?.as_str()))
203 }
204}
205
206#[derive(Debug, Clone, PartialEq, Eq, Hash)]
211#[non_exhaustive]
212pub enum KeyOperation {
213 Sign,
215 Verify,
217 Encrypt,
219 Decrypt,
221 WrapKey,
223 UnwrapKey,
225 DeriveKey,
227 DeriveBits,
229 Unknown(String),
234}
235
236impl KeyOperation {
237 pub fn as_str(&self) -> &str {
239 match self {
240 KeyOperation::Sign => "sign",
241 KeyOperation::Verify => "verify",
242 KeyOperation::Encrypt => "encrypt",
243 KeyOperation::Decrypt => "decrypt",
244 KeyOperation::WrapKey => "wrapKey",
245 KeyOperation::UnwrapKey => "unwrapKey",
246 KeyOperation::DeriveKey => "deriveKey",
247 KeyOperation::DeriveBits => "deriveBits",
248 KeyOperation::Unknown(s) => s.as_str(),
249 }
250 }
251
252 pub fn is_unknown(&self) -> bool {
254 matches!(self, KeyOperation::Unknown(_))
255 }
256}
257
258impl Display for KeyOperation {
259 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
260 write!(f, "{}", self.as_str())
261 }
262}
263
264impl From<&str> for KeyOperation {
265 fn from(s: &str) -> Self {
269 match s {
270 "sign" => KeyOperation::Sign,
271 "verify" => KeyOperation::Verify,
272 "encrypt" => KeyOperation::Encrypt,
273 "decrypt" => KeyOperation::Decrypt,
274 "wrapKey" => KeyOperation::WrapKey,
275 "unwrapKey" => KeyOperation::UnwrapKey,
276 "deriveKey" => KeyOperation::DeriveKey,
277 "deriveBits" => KeyOperation::DeriveBits,
278 _ => KeyOperation::Unknown(s.to_string()),
279 }
280 }
281}
282
283impl FromStr for KeyOperation {
284 type Err = Infallible;
285
286 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
287 Ok(Self::from(s))
288 }
289}
290
291impl Serialize for KeyOperation {
292 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
293 where
294 S: Serializer,
295 {
296 serializer.serialize_str(self.as_str())
297 }
298}
299
300impl<'de> Deserialize<'de> for KeyOperation {
301 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
302 where
303 D: Deserializer<'de>,
304 {
305 Ok(KeyOperation::from(
306 String::deserialize(deserializer)?.as_str(),
307 ))
308 }
309}
310
311#[derive(Debug, Clone, PartialEq, Eq, Hash)]
316#[non_exhaustive]
317pub enum Algorithm {
318 Hs256,
321 Hs384,
323 Hs512,
325
326 Rs256,
329 Rs384,
331 Rs512,
333
334 Ps256,
337 Ps384,
339 Ps512,
341
342 Es256,
345 Es384,
347 Es512,
349 Es256k,
351
352 EdDsa,
358 Ed25519,
360 Ed448,
362
363 RsaOaep,
366 RsaOaep256,
368 RsaOaep384,
370 RsaOaep512,
372 Rsa1_5,
374
375 A128kw,
378 A192kw,
380 A256kw,
382
383 Dir,
386
387 EcdhEs,
390 EcdhEsA128kw,
392 EcdhEsA192kw,
394 EcdhEsA256kw,
396
397 A128gcmkw,
400 A192gcmkw,
402 A256gcmkw,
404
405 Pbes2Hs256A128kw,
408 Pbes2Hs384A192kw,
410 Pbes2Hs512A256kw,
412
413 A128cbcHs256,
416 A192cbcHs384,
418 A256cbcHs512,
420 A128gcm,
422 A192gcm,
424 A256gcm,
426
427 Unknown(String),
432}
433
434impl Algorithm {
435 pub fn as_str(&self) -> &str {
439 match self {
440 Algorithm::Hs256 => "HS256",
441 Algorithm::Hs384 => "HS384",
442 Algorithm::Hs512 => "HS512",
443 Algorithm::Rs256 => "RS256",
444 Algorithm::Rs384 => "RS384",
445 Algorithm::Rs512 => "RS512",
446 Algorithm::Ps256 => "PS256",
447 Algorithm::Ps384 => "PS384",
448 Algorithm::Ps512 => "PS512",
449 Algorithm::Es256 => "ES256",
450 Algorithm::Es384 => "ES384",
451 Algorithm::Es512 => "ES512",
452 Algorithm::Es256k => "ES256K",
453 Algorithm::EdDsa => "EdDSA",
454 Algorithm::Ed25519 => "Ed25519",
455 Algorithm::Ed448 => "Ed448",
456 Algorithm::RsaOaep => "RSA-OAEP",
457 Algorithm::RsaOaep256 => "RSA-OAEP-256",
458 Algorithm::RsaOaep384 => "RSA-OAEP-384",
459 Algorithm::RsaOaep512 => "RSA-OAEP-512",
460 Algorithm::Rsa1_5 => "RSA1_5",
461 Algorithm::A128kw => "A128KW",
462 Algorithm::A192kw => "A192KW",
463 Algorithm::A256kw => "A256KW",
464 Algorithm::Dir => "dir",
465 Algorithm::EcdhEs => "ECDH-ES",
466 Algorithm::EcdhEsA128kw => "ECDH-ES+A128KW",
467 Algorithm::EcdhEsA192kw => "ECDH-ES+A192KW",
468 Algorithm::EcdhEsA256kw => "ECDH-ES+A256KW",
469 Algorithm::A128gcmkw => "A128GCMKW",
470 Algorithm::A192gcmkw => "A192GCMKW",
471 Algorithm::A256gcmkw => "A256GCMKW",
472 Algorithm::Pbes2Hs256A128kw => "PBES2-HS256+A128KW",
473 Algorithm::Pbes2Hs384A192kw => "PBES2-HS384+A192KW",
474 Algorithm::Pbes2Hs512A256kw => "PBES2-HS512+A256KW",
475 Algorithm::A128cbcHs256 => "A128CBC-HS256",
476 Algorithm::A192cbcHs384 => "A192CBC-HS384",
477 Algorithm::A256cbcHs512 => "A256CBC-HS512",
478 Algorithm::A128gcm => "A128GCM",
479 Algorithm::A192gcm => "A192GCM",
480 Algorithm::A256gcm => "A256GCM",
481 Algorithm::Unknown(s) => s.as_str(),
482 }
483 }
484
485 pub fn is_unknown(&self) -> bool {
487 matches!(self, Algorithm::Unknown(_))
488 }
489
490 pub fn is_deprecated(&self) -> bool {
495 matches!(self, Algorithm::EdDsa)
496 }
497}
498
499impl Display for Algorithm {
500 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
501 write!(f, "{}", self.as_str())
502 }
503}
504
505impl From<&str> for Algorithm {
506 fn from(s: &str) -> Self {
510 match s {
511 "HS256" => Algorithm::Hs256,
512 "HS384" => Algorithm::Hs384,
513 "HS512" => Algorithm::Hs512,
514 "RS256" => Algorithm::Rs256,
515 "RS384" => Algorithm::Rs384,
516 "RS512" => Algorithm::Rs512,
517 "PS256" => Algorithm::Ps256,
518 "PS384" => Algorithm::Ps384,
519 "PS512" => Algorithm::Ps512,
520 "ES256" => Algorithm::Es256,
521 "ES384" => Algorithm::Es384,
522 "ES512" => Algorithm::Es512,
523 "ES256K" => Algorithm::Es256k,
524 "EdDSA" => Algorithm::EdDsa,
525 "Ed25519" => Algorithm::Ed25519,
526 "Ed448" => Algorithm::Ed448,
527 "RSA-OAEP" => Algorithm::RsaOaep,
528 "RSA-OAEP-256" => Algorithm::RsaOaep256,
529 "RSA-OAEP-384" => Algorithm::RsaOaep384,
530 "RSA-OAEP-512" => Algorithm::RsaOaep512,
531 "RSA1_5" => Algorithm::Rsa1_5,
532 "A128KW" => Algorithm::A128kw,
533 "A192KW" => Algorithm::A192kw,
534 "A256KW" => Algorithm::A256kw,
535 "dir" => Algorithm::Dir,
536 "ECDH-ES" => Algorithm::EcdhEs,
537 "ECDH-ES+A128KW" => Algorithm::EcdhEsA128kw,
538 "ECDH-ES+A192KW" => Algorithm::EcdhEsA192kw,
539 "ECDH-ES+A256KW" => Algorithm::EcdhEsA256kw,
540 "A128GCMKW" => Algorithm::A128gcmkw,
541 "A192GCMKW" => Algorithm::A192gcmkw,
542 "A256GCMKW" => Algorithm::A256gcmkw,
543 "PBES2-HS256+A128KW" => Algorithm::Pbes2Hs256A128kw,
544 "PBES2-HS384+A192KW" => Algorithm::Pbes2Hs384A192kw,
545 "PBES2-HS512+A256KW" => Algorithm::Pbes2Hs512A256kw,
546 "A128CBC-HS256" => Algorithm::A128cbcHs256,
547 "A192CBC-HS384" => Algorithm::A192cbcHs384,
548 "A256CBC-HS512" => Algorithm::A256cbcHs512,
549 "A128GCM" => Algorithm::A128gcm,
550 "A192GCM" => Algorithm::A192gcm,
551 "A256GCM" => Algorithm::A256gcm,
552 _ => Algorithm::Unknown(s.to_string()),
553 }
554 }
555}
556
557impl FromStr for Algorithm {
558 type Err = Infallible;
559
560 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
561 Ok(Self::from(s))
562 }
563}
564
565impl Serialize for Algorithm {
566 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
567 where
568 S: Serializer,
569 {
570 serializer.serialize_str(self.as_str())
571 }
572}
573
574impl<'de> Deserialize<'de> for Algorithm {
575 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
576 where
577 D: Deserializer<'de>,
578 {
579 Ok(Algorithm::from(String::deserialize(deserializer)?.as_str()))
580 }
581}
582
583#[derive(Debug, Clone, PartialEq, Eq, Hash, Zeroize, ZeroizeOnDrop)]
585#[non_exhaustive]
586pub enum KeyParams {
587 Rsa(RsaParams),
589 Ec(EcParams),
591 Symmetric(SymmetricParams),
593 Okp(OkpParams),
595}
596
597impl KeyParams {
598 pub fn key_type(&self) -> KeyType {
600 match self {
601 KeyParams::Rsa(_) => KeyType::Rsa,
602 KeyParams::Ec(_) => KeyType::Ec,
603 KeyParams::Symmetric(_) => KeyType::Symmetric,
604 KeyParams::Okp(_) => KeyType::Okp,
605 }
606 }
607
608 pub fn is_public_key_only(&self) -> bool {
610 match self {
611 KeyParams::Rsa(p) => p.is_public_key_only(),
612 KeyParams::Ec(p) => p.is_public_key_only(),
613 KeyParams::Symmetric(p) => p.is_public_key_only(),
614 KeyParams::Okp(p) => p.is_public_key_only(),
615 }
616 }
617
618 pub fn has_private_key(&self) -> bool {
620 !self.is_public_key_only()
621 }
622
623 pub fn validate(&self) -> Result<()> {
625 match self {
626 KeyParams::Rsa(p) => p.validate(),
627 KeyParams::Ec(p) => p.validate(),
628 KeyParams::Symmetric(p) => p.validate(),
629 KeyParams::Okp(p) => p.validate(),
630 }
631 }
632}
633
634impl From<&KeyParams> for KeyType {
635 fn from(params: &KeyParams) -> Self {
636 params.key_type()
637 }
638}
639
640impl From<KeyParams> for KeyType {
641 fn from(params: KeyParams) -> Self {
642 (¶ms).into()
643 }
644}
645
646impl From<RsaParams> for KeyParams {
647 fn from(p: RsaParams) -> Self {
648 KeyParams::Rsa(p)
649 }
650}
651
652impl From<EcParams> for KeyParams {
653 fn from(p: EcParams) -> Self {
654 KeyParams::Ec(p)
655 }
656}
657
658impl From<SymmetricParams> for KeyParams {
659 fn from(p: SymmetricParams) -> Self {
660 KeyParams::Symmetric(p)
661 }
662}
663
664impl From<OkpParams> for KeyParams {
665 fn from(p: OkpParams) -> Self {
666 KeyParams::Okp(p)
667 }
668}
669
670#[derive(Clone, Zeroize, ZeroizeOnDrop)]
688pub struct Key {
689 #[zeroize(skip)]
691 kid: Option<String>,
692
693 #[zeroize(skip)]
695 key_use: Option<KeyUse>,
696
697 #[zeroize(skip)]
699 key_ops: Option<Vec<KeyOperation>>,
700
701 #[zeroize(skip)]
703 alg: Option<Algorithm>,
704
705 params: KeyParams,
707
708 #[zeroize(skip)]
710 x5c: Option<Vec<String>>,
711
712 #[zeroize(skip)]
714 x5t: Option<String>,
715
716 #[zeroize(skip)]
718 #[allow(non_snake_case)]
719 x5t_s256: Option<String>,
720
721 #[zeroize(skip)]
723 x5u: Option<String>,
724}
725
726impl Key {
727 #[must_use]
753 pub fn new(params: KeyParams) -> Self {
754 Self {
755 kid: None,
756 key_use: None,
757 key_ops: None,
758 alg: None,
759 params,
760 x5c: None,
761 x5t: None,
762 x5t_s256: None,
763 x5u: None,
764 }
765 }
766
767 #[inline]
775 #[must_use]
776 pub fn kty(&self) -> KeyType {
777 self.params.key_type()
778 }
779
780 #[must_use]
782 pub fn kid(&self) -> Option<&str> {
783 self.kid.as_deref()
784 }
785
786 #[must_use]
788 pub fn key_use(&self) -> Option<&KeyUse> {
789 self.key_use.as_ref()
790 }
791
792 #[must_use]
794 pub fn key_ops(&self) -> Option<&[KeyOperation]> {
795 self.key_ops.as_deref()
796 }
797
798 #[must_use]
800 pub fn alg(&self) -> Option<&Algorithm> {
801 self.alg.as_ref()
802 }
803
804 #[must_use]
806 pub fn params(&self) -> &KeyParams {
807 &self.params
808 }
809
810 #[must_use]
812 pub fn x5c(&self) -> Option<&[String]> {
813 self.x5c.as_deref()
814 }
815
816 #[must_use]
818 pub fn x5t(&self) -> Option<&str> {
819 self.x5t.as_deref()
820 }
821
822 #[must_use]
824 #[allow(non_snake_case)]
825 pub fn x5t_s256(&self) -> Option<&str> {
826 self.x5t_s256.as_deref()
827 }
828
829 #[must_use]
831 pub fn x5u(&self) -> Option<&str> {
832 self.x5u.as_deref()
833 }
834
835 #[must_use]
837 pub fn with_kid(mut self, kid: impl Into<String>) -> Self {
838 self.kid = Some(kid.into());
839 self
840 }
841
842 #[must_use]
844 pub fn with_use(mut self, key_use: KeyUse) -> Self {
845 self.key_use = Some(key_use);
846 self
847 }
848
849 #[must_use]
851 pub fn with_key_ops(mut self, key_ops: impl IntoIterator<Item = KeyOperation>) -> Self {
852 self.key_ops = Some(key_ops.into_iter().collect());
853 self
854 }
855
856 #[must_use]
858 pub fn with_alg(mut self, alg: Algorithm) -> Self {
859 self.alg = Some(alg);
860 self
861 }
862
863 #[must_use]
865 pub fn with_x5c(mut self, x5c: Vec<String>) -> Self {
866 self.x5c = Some(x5c);
867 self
868 }
869
870 #[must_use]
872 pub fn with_x5t(mut self, x5t: impl Into<String>) -> Self {
873 self.x5t = Some(x5t.into());
874 self
875 }
876
877 #[must_use]
879 pub fn with_x5t_s256(mut self, x5t_s256: impl Into<String>) -> Self {
880 self.x5t_s256 = Some(x5t_s256.into());
881 self
882 }
883
884 #[must_use]
886 pub fn with_x5u(mut self, x5u: impl Into<String>) -> Self {
887 self.x5u = Some(x5u.into());
888 self
889 }
890
891 pub fn is_public_key_only(&self) -> bool {
893 self.params.is_public_key_only()
894 }
895
896 pub fn has_private_key(&self) -> bool {
898 self.params.has_private_key()
899 }
900
901 #[must_use = "validation result must be checked"]
923 pub fn validate(&self) -> Result<()> {
924 self.params.validate()?;
926
927 self.validate_use_key_ops_consistency()?;
929 self.validate_key_ops_unique()?;
930
931 self.validate_certificate_metadata()?;
932
933 Ok(())
934 }
935
936 pub(crate) fn validate_certificate_metadata(&self) -> Result<()> {
937 if let Some(ref x5u) = self.x5u {
939 let parsed = Url::parse(x5u).map_err(|_| {
940 Error::from(InvalidKeyError::InvalidParameter {
941 name: "x5u",
942 reason: "RFC 7517: x5u must be a valid absolute URL".to_string(),
943 })
944 })?;
945
946 if parsed.scheme() != "https" || parsed.host_str().is_none() {
947 return Err(InvalidKeyError::InvalidParameter {
948 name: "x5u",
949 reason: "RFC 7517: x5u URL must use HTTPS and include a host".to_string(),
950 }
951 .into());
952 }
953 }
954
955 let first_x5c_der = self.decode_and_validate_x5c_first_der()?;
956
957 if let Some(first_der) = first_x5c_der.as_ref() {
960 self.validate_x5c_public_key_match(first_der)?;
961 }
962
963 if let Some(ref x5t) = self.x5t {
965 validate_x509_thumbprint(x5t, "x5t", 20)?;
966 }
967
968 if let Some(ref x5t_s256) = self.x5t_s256 {
970 validate_x509_thumbprint(x5t_s256, "x5t#S256", 32)?;
971 }
972
973 if let Some(first_der) = first_x5c_der.as_ref() {
976 if let Some(ref x5t) = self.x5t {
977 let mut hasher = Sha1::new();
978 hasher.update(first_der);
979 let expected = Base64UrlUnpadded::encode_string(&hasher.finalize());
980
981 if x5t != &expected {
982 return Err(InvalidKeyError::InconsistentParameters(
983 "RFC 7517: x5t does not match SHA-1 thumbprint of x5c[0]".to_string(),
984 )
985 .into());
986 }
987 }
988
989 if let Some(ref x5t_s256) = self.x5t_s256 {
990 let mut hasher = Sha256::new();
991 hasher.update(first_der);
992 let expected = Base64UrlUnpadded::encode_string(&hasher.finalize());
993
994 if x5t_s256 != &expected {
995 return Err(InvalidKeyError::InconsistentParameters(
996 "RFC 7517: x5t#S256 does not match SHA-256 thumbprint of x5c[0]"
997 .to_string(),
998 )
999 .into());
1000 }
1001 }
1002 }
1003
1004 Ok(())
1005 }
1006
1007 fn validate_use_key_ops_consistency(&self) -> Result<()> {
1008 if let (Some(key_use), Some(key_ops)) = (&self.key_use, &self.key_ops)
1009 && !is_use_consistent_with_ops(key_use, key_ops)
1010 {
1011 return Err(InvalidKeyError::InconsistentParameters(
1012 "RFC 7517: 'use' and 'key_ops' are both present but inconsistent".to_string(),
1013 )
1014 .into());
1015 }
1016
1017 Ok(())
1018 }
1019
1020 fn validate_key_ops_unique(&self) -> Result<()> {
1021 if let Some(ref ops) = self.key_ops {
1022 let mut seen = HashSet::new();
1023 for op in ops {
1024 if !seen.insert(op) {
1025 return Err(InvalidKeyError::InconsistentParameters(format!(
1026 "RFC 7517: key_ops array contains duplicate value '{}'",
1027 op.as_str()
1028 ))
1029 .into());
1030 }
1031 }
1032 }
1033
1034 Ok(())
1035 }
1036
1037 fn decode_and_validate_x5c_first_der(&self) -> Result<Option<Vec<u8>>> {
1038 let Some(ref certs) = self.x5c else {
1040 return Ok(None);
1041 };
1042
1043 if certs.is_empty() {
1044 return Err(InvalidKeyError::InvalidParameter {
1045 name: "x5c",
1046 reason: "RFC 7517: x5c must contain one or more certificates".to_string(),
1047 }
1048 .into());
1049 }
1050
1051 let mut first_der = None;
1052
1053 for (i, cert) in certs.iter().enumerate() {
1055 if cert.contains('-') || cert.contains('_') {
1060 return Err(InvalidKeyError::InvalidParameter {
1061 name: "x5c",
1062 reason: format!(
1063 "RFC 7517: x5c[{}] appears to be base64url encoded; must be standard base64",
1064 i
1065 ),
1066 }
1067 .into());
1068 }
1069
1070 if !is_valid_base64(cert) {
1072 return Err(InvalidKeyError::InvalidParameter {
1073 name: "x5c",
1074 reason: format!("RFC 7517: x5c[{}] is not valid base64 encoding", i),
1075 }
1076 .into());
1077 }
1078
1079 use base64ct::{Base64, Encoding};
1082 let der_bytes = Base64::decode_vec(cert).map_err(|_| {
1083 Error::from(InvalidKeyError::InvalidParameter {
1084 name: "x5c",
1085 reason: format!("RFC 7517: x5c[{}] failed base64 decoding", i),
1086 })
1087 })?;
1088
1089 let (remaining, _) = parse_x509_certificate(&der_bytes).map_err(|_| {
1090 InvalidKeyError::InvalidParameter {
1091 name: "x5c",
1092 reason: format!(
1093 "RFC 7517: x5c[{}] is not a valid DER-encoded X.509 certificate",
1094 i
1095 ),
1096 }
1097 })?;
1098
1099 if !remaining.is_empty() {
1100 return Err(InvalidKeyError::InvalidParameter {
1101 name: "x5c",
1102 reason: format!(
1103 "RFC 7517: x5c[{}] contains trailing data after DER certificate",
1104 i
1105 ),
1106 }
1107 .into());
1108 }
1109
1110 if i == 0 {
1111 first_der = Some(der_bytes);
1112 }
1113 }
1114
1115 Ok(first_der)
1116 }
1117
1118 #[must_use = "validation result must be checked"]
1156 pub fn validate_for_use(
1157 &self,
1158 alg: &Algorithm,
1159 ops: impl IntoIterator<Item = KeyOperation>,
1160 ) -> Result<()> {
1161 let ops: Vec<KeyOperation> = ops.into_iter().collect();
1162 if ops.is_empty() {
1163 return Err(Error::InvalidInput(
1164 "at least one requested operation is required",
1165 ));
1166 }
1167
1168 self.validate()?;
1170
1171 self.validate_declared_algorithm_match(alg)?;
1172
1173 self.validate_for_use_inner(alg, &ops)
1174 }
1175
1176 #[cfg(feature = "web-crypto")]
1182 pub(crate) fn validate_for_use_with_alg_override(
1183 &self,
1184 alg: &Algorithm,
1185 ops: impl IntoIterator<Item = KeyOperation>,
1186 ) -> Result<()> {
1187 let ops: Vec<KeyOperation> = ops.into_iter().collect();
1188 if ops.is_empty() {
1189 return Err(Error::InvalidInput(
1190 "at least one requested operation is required",
1191 ));
1192 }
1193
1194 self.validate()?;
1196
1197 self.validate_for_use_inner(alg, &ops)
1201 }
1202
1203 fn validate_for_use_inner(&self, alg: &Algorithm, ops: &[KeyOperation]) -> Result<()> {
1206 self.validate_algorithm_key_type_match(alg)?;
1210 self.validate_algorithm_key_strength(alg)?;
1211 self.validate_operation_algorithm_compatibility_for_all(alg, ops)?;
1212
1213 self.validate_operation_capability_for_all(ops)?;
1215
1216 self.validate_operation_intent_for_all(ops)
1220 }
1221
1222 pub fn check_operations_permitted(&self, operations: impl AsRef<[KeyOperation]>) -> Result<()> {
1257 let operations = operations.as_ref();
1258 if operations.is_empty() {
1259 return Err(Error::InvalidInput(
1260 "at least one requested operation is required",
1261 ));
1262 }
1263 self.validate_use_key_ops_consistency()?;
1266 self.validate_key_ops_unique()?;
1267 self.validate_operation_intent_for_all(operations)
1268 }
1269
1270 pub(crate) fn check_algorithm_suitability(&self, alg: &Algorithm) -> Result<()> {
1280 self.params.validate()?;
1283 self.validate_algorithm_key_type_match(alg)?;
1284 self.validate_algorithm_key_strength(alg)
1285 }
1286
1287 pub(crate) fn check_operation_intent(&self, operations: &[KeyOperation]) -> Result<()> {
1303 debug_assert!(!operations.is_empty());
1304 self.validate_use_key_ops_consistency()?;
1305 self.validate_key_ops_unique()?;
1306 self.validate_operation_intent_for_all(operations)
1307 }
1308
1309 pub(crate) fn check_operation_capability(&self, operations: &[KeyOperation]) -> Result<()> {
1314 debug_assert!(!operations.is_empty());
1315 self.validate_operation_capability_for_all(operations)
1316 }
1317
1318 pub(crate) fn validate_operation_intent_for_all(
1323 &self,
1324 operations: &[KeyOperation],
1325 ) -> Result<()> {
1326 debug_assert!(!operations.is_empty());
1327
1328 if let Some(key_use) = &self.key_use {
1329 let disallowed: Vec<KeyOperation> = operations
1330 .iter()
1331 .filter(|op| !is_operation_allowed_by_use(key_use, op))
1332 .cloned()
1333 .collect();
1334
1335 if !disallowed.is_empty() {
1336 return Err(IncompatibleKeyError::OperationNotPermitted {
1337 operations: disallowed,
1338 reason: format!(
1339 "RFC 7517: key 'use' '{}' does not permit requested operation(s)",
1340 key_use
1341 ),
1342 }
1343 .into());
1344 }
1345 }
1346
1347 if let Some(key_ops) = &self.key_ops {
1348 let disallowed: Vec<KeyOperation> = operations
1351 .iter()
1352 .filter(|op| !key_ops.contains(op))
1353 .cloned()
1354 .collect();
1355
1356 if !disallowed.is_empty() {
1357 return Err(IncompatibleKeyError::OperationNotPermitted {
1358 operations: disallowed,
1359 reason: "RFC 7517: key_ops does not permit requested operation(s)".to_string(),
1360 }
1361 .into());
1362 }
1363 }
1364
1365 Ok(())
1366 }
1367
1368 fn validate_operation_capability_for_all(&self, operations: &[KeyOperation]) -> Result<()> {
1369 debug_assert!(!operations.is_empty());
1370
1371 if matches!(self.params, KeyParams::Symmetric(_)) || self.has_private_key() {
1375 return Ok(());
1376 }
1377
1378 let requires_private: Vec<KeyOperation> = operations
1379 .iter()
1380 .filter(|op| {
1381 matches!(
1382 op,
1383 KeyOperation::Sign
1384 | KeyOperation::Decrypt
1385 | KeyOperation::UnwrapKey
1386 | KeyOperation::DeriveKey
1387 | KeyOperation::DeriveBits
1388 )
1389 })
1390 .cloned()
1391 .collect();
1392
1393 if requires_private.is_empty() {
1394 return Ok(());
1395 }
1396
1397 Err(IncompatibleKeyError::OperationNotPermitted {
1398 operations: requires_private,
1399 reason: "requested operation(s) require private key material, but key contains only public parameters".to_string(),
1400 }
1401 .into())
1402 }
1403
1404 fn validate_operation_algorithm_compatibility_for_all(
1405 &self,
1406 alg: &Algorithm,
1407 operations: &[KeyOperation],
1408 ) -> Result<()> {
1409 debug_assert!(!operations.is_empty());
1410
1411 let incompatible: Vec<KeyOperation> = operations
1412 .iter()
1413 .filter(|op| !is_operation_compatible_with_algorithm(op, alg))
1414 .cloned()
1415 .collect();
1416
1417 if incompatible.is_empty() {
1418 return Ok(());
1419 }
1420
1421 Err(IncompatibleKeyError::OperationNotPermitted {
1422 operations: incompatible,
1423 reason: format!(
1424 "requested operation(s) are not compatible with algorithm '{}'",
1425 alg.as_str()
1426 ),
1427 }
1428 .into())
1429 }
1430
1431 pub fn is_algorithm_compatible(&self, alg: &Algorithm) -> bool {
1453 if alg.is_unknown() {
1455 return false;
1456 }
1457
1458 match (&self.params, alg) {
1459 (KeyParams::Rsa(_), Algorithm::Rs256)
1461 | (KeyParams::Rsa(_), Algorithm::Rs384)
1462 | (KeyParams::Rsa(_), Algorithm::Rs512)
1463 | (KeyParams::Rsa(_), Algorithm::Ps256)
1464 | (KeyParams::Rsa(_), Algorithm::Ps384)
1465 | (KeyParams::Rsa(_), Algorithm::Ps512)
1466 | (KeyParams::Rsa(_), Algorithm::RsaOaep)
1467 | (KeyParams::Rsa(_), Algorithm::RsaOaep256)
1468 | (KeyParams::Rsa(_), Algorithm::RsaOaep384)
1469 | (KeyParams::Rsa(_), Algorithm::RsaOaep512)
1470 | (KeyParams::Rsa(_), Algorithm::Rsa1_5) => true,
1471
1472 (KeyParams::Symmetric(_), Algorithm::Hs256)
1474 | (KeyParams::Symmetric(_), Algorithm::Hs384)
1475 | (KeyParams::Symmetric(_), Algorithm::Hs512) => true,
1476
1477 (KeyParams::Symmetric(_), Algorithm::A128kw)
1479 | (KeyParams::Symmetric(_), Algorithm::A192kw)
1480 | (KeyParams::Symmetric(_), Algorithm::A256kw)
1481 | (KeyParams::Symmetric(_), Algorithm::A128gcmkw)
1482 | (KeyParams::Symmetric(_), Algorithm::A192gcmkw)
1483 | (KeyParams::Symmetric(_), Algorithm::A256gcmkw)
1484 | (KeyParams::Symmetric(_), Algorithm::Dir) => true,
1485
1486 (KeyParams::Symmetric(_), Algorithm::A128cbcHs256)
1488 | (KeyParams::Symmetric(_), Algorithm::A192cbcHs384)
1489 | (KeyParams::Symmetric(_), Algorithm::A256cbcHs512)
1490 | (KeyParams::Symmetric(_), Algorithm::A128gcm)
1491 | (KeyParams::Symmetric(_), Algorithm::A192gcm)
1492 | (KeyParams::Symmetric(_), Algorithm::A256gcm) => true,
1493
1494 (KeyParams::Symmetric(_), Algorithm::Pbes2Hs256A128kw)
1496 | (KeyParams::Symmetric(_), Algorithm::Pbes2Hs384A192kw)
1497 | (KeyParams::Symmetric(_), Algorithm::Pbes2Hs512A256kw) => true,
1498
1499 (KeyParams::Ec(ec), Algorithm::Es256) => ec.crv == EcCurve::P256,
1501 (KeyParams::Ec(ec), Algorithm::Es384) => ec.crv == EcCurve::P384,
1502 (KeyParams::Ec(ec), Algorithm::Es512) => ec.crv == EcCurve::P521,
1503 (KeyParams::Ec(ec), Algorithm::Es256k) => ec.crv == EcCurve::Secp256k1,
1504
1505 (KeyParams::Ec(_), Algorithm::EcdhEs)
1507 | (KeyParams::Ec(_), Algorithm::EcdhEsA128kw)
1508 | (KeyParams::Ec(_), Algorithm::EcdhEsA192kw)
1509 | (KeyParams::Ec(_), Algorithm::EcdhEsA256kw) => true,
1510
1511 (KeyParams::Okp(okp), Algorithm::EdDsa) => {
1513 okp.crv == OkpCurve::Ed25519 || okp.crv == OkpCurve::Ed448
1514 }
1515
1516 (KeyParams::Okp(okp), Algorithm::Ed25519) => okp.crv == OkpCurve::Ed25519,
1518 (KeyParams::Okp(okp), Algorithm::Ed448) => okp.crv == OkpCurve::Ed448,
1519
1520 (KeyParams::Okp(okp), Algorithm::EcdhEs)
1522 | (KeyParams::Okp(okp), Algorithm::EcdhEsA128kw)
1523 | (KeyParams::Okp(okp), Algorithm::EcdhEsA192kw)
1524 | (KeyParams::Okp(okp), Algorithm::EcdhEsA256kw) => {
1525 okp.crv == OkpCurve::X25519 || okp.crv == OkpCurve::X448
1526 }
1527
1528 _ => false,
1530 }
1531 }
1532
1533 fn validate_algorithm_key_type_match(&self, alg: &Algorithm) -> Result<()> {
1535 if !self.is_algorithm_compatible(alg) {
1536 return Err(IncompatibleKeyError::IncompatibleAlgorithm {
1537 algorithm: alg.clone(),
1538 key_type: self.kty(),
1539 }
1540 .into());
1541 }
1542
1543 Ok(())
1544 }
1545
1546 fn validate_algorithm_key_strength(&self, alg: &Algorithm) -> Result<()> {
1548 match (&self.params, alg) {
1549 (
1550 KeyParams::Rsa(rsa),
1551 Algorithm::Rs256
1552 | Algorithm::Rs384
1553 | Algorithm::Rs512
1554 | Algorithm::Ps256
1555 | Algorithm::Ps384
1556 | Algorithm::Ps512
1557 | Algorithm::Rsa1_5
1558 | Algorithm::RsaOaep
1559 | Algorithm::RsaOaep256
1560 | Algorithm::RsaOaep384
1561 | Algorithm::RsaOaep512,
1562 ) => rsa.validate_key_size(2048),
1563 (KeyParams::Symmetric(sym), Algorithm::Hs256) => sym.validate_min_size(256, "HS256"),
1564 (KeyParams::Symmetric(sym), Algorithm::Hs384) => sym.validate_min_size(384, "HS384"),
1565 (KeyParams::Symmetric(sym), Algorithm::Hs512) => sym.validate_min_size(512, "HS512"),
1566 (KeyParams::Symmetric(sym), Algorithm::A128kw)
1567 | (KeyParams::Symmetric(sym), Algorithm::A128gcmkw)
1568 | (KeyParams::Symmetric(sym), Algorithm::A128gcm) => {
1569 sym.validate_exact_size(128, "AES-128")
1570 }
1571 (KeyParams::Symmetric(sym), Algorithm::A192kw)
1572 | (KeyParams::Symmetric(sym), Algorithm::A192gcmkw)
1573 | (KeyParams::Symmetric(sym), Algorithm::A192gcm) => {
1574 sym.validate_exact_size(192, "AES-192")
1575 }
1576 (KeyParams::Symmetric(sym), Algorithm::A256kw)
1577 | (KeyParams::Symmetric(sym), Algorithm::A256gcmkw)
1578 | (KeyParams::Symmetric(sym), Algorithm::A256gcm) => {
1579 sym.validate_exact_size(256, "AES-256")
1580 }
1581 (KeyParams::Symmetric(sym), Algorithm::A128cbcHs256) => {
1582 sym.validate_exact_size(256, "A128CBC-HS256")
1585 }
1586 (KeyParams::Symmetric(sym), Algorithm::A192cbcHs384) => {
1587 sym.validate_exact_size(384, "A192CBC-HS384")
1590 }
1591 (KeyParams::Symmetric(sym), Algorithm::A256cbcHs512) => {
1592 sym.validate_exact_size(512, "A256CBC-HS512")
1595 }
1596 _ => Ok(()),
1597 }
1598 }
1599
1600 fn validate_x5c_public_key_match(&self, cert_der: &[u8]) -> Result<()> {
1602 let (remaining, cert) = parse_x509_certificate(cert_der).map_err(|_| {
1603 Error::from(InvalidKeyError::InvalidParameter {
1604 name: "x5c",
1605 reason: "RFC 7517: x5c[0] is not a parseable X.509 certificate".to_string(),
1606 })
1607 })?;
1608
1609 if !remaining.is_empty() {
1610 return Err(InvalidKeyError::InvalidParameter {
1611 name: "x5c",
1612 reason: "RFC 7517: x5c[0] contains trailing data after DER certificate".to_string(),
1613 }
1614 .into());
1615 }
1616
1617 let spki = &cert.tbs_certificate.subject_pki;
1618 let cert_alg_oid = spki.algorithm.algorithm.to_id_string();
1619 let cert_key = spki.subject_public_key.data.as_ref();
1620
1621 match &self.params {
1622 KeyParams::Rsa(rsa) => {
1623 if cert_alg_oid != "1.2.840.113549.1.1.1" {
1624 return Err(InvalidKeyError::InconsistentParameters(
1625 "RFC 7517: x5c[0] public key algorithm does not match JWK RSA key"
1626 .to_string(),
1627 )
1628 .into());
1629 }
1630
1631 let expected_der = encode_rsa_public_key_der(rsa.n.as_bytes(), rsa.e.as_bytes());
1632 if cert_key != expected_der.as_slice() {
1633 return Err(InvalidKeyError::InconsistentParameters(
1634 "RFC 7517: x5c[0] public key does not match JWK RSA key parameters"
1635 .to_string(),
1636 )
1637 .into());
1638 }
1639 }
1640 KeyParams::Ec(ec) => {
1641 if cert_alg_oid != "1.2.840.10045.2.1" {
1642 return Err(InvalidKeyError::InconsistentParameters(
1643 "RFC 7517: x5c[0] public key algorithm does not match JWK EC key"
1644 .to_string(),
1645 )
1646 .into());
1647 }
1648
1649 let expected_curve_oid = match ec.crv {
1650 EcCurve::P256 => "1.2.840.10045.3.1.7",
1651 EcCurve::P384 => "1.3.132.0.34",
1652 EcCurve::P521 => "1.3.132.0.35",
1653 EcCurve::Secp256k1 => "1.3.132.0.10",
1654 };
1655
1656 let cert_curve_oid = spki
1657 .algorithm
1658 .parameters
1659 .as_ref()
1660 .and_then(|p| p.as_oid().ok())
1661 .map(|oid| oid.to_id_string());
1662
1663 if cert_curve_oid.as_deref() != Some(expected_curve_oid) {
1664 return Err(InvalidKeyError::InconsistentParameters(
1665 "RFC 7517: x5c[0] EC curve does not match JWK crv".to_string(),
1666 )
1667 .into());
1668 }
1669
1670 let expected_point = ec.to_uncompressed_point();
1671 if cert_key != expected_point.as_slice() {
1672 return Err(InvalidKeyError::InconsistentParameters(
1673 "RFC 7517: x5c[0] public key does not match JWK EC key parameters"
1674 .to_string(),
1675 )
1676 .into());
1677 }
1678 }
1679 KeyParams::Okp(okp) => {
1680 let expected_oid = match okp.crv {
1681 OkpCurve::Ed25519 => "1.3.101.112",
1682 OkpCurve::Ed448 => "1.3.101.113",
1683 OkpCurve::X25519 => "1.3.101.110",
1684 OkpCurve::X448 => "1.3.101.111",
1685 };
1686
1687 if cert_alg_oid != expected_oid {
1688 return Err(InvalidKeyError::InconsistentParameters(
1689 "RFC 7517: x5c[0] public key algorithm does not match JWK OKP key"
1690 .to_string(),
1691 )
1692 .into());
1693 }
1694
1695 if cert_key != okp.x.as_bytes() {
1696 return Err(InvalidKeyError::InconsistentParameters(
1697 "RFC 7517: x5c[0] public key does not match JWK OKP key parameters"
1698 .to_string(),
1699 )
1700 .into());
1701 }
1702 }
1703 KeyParams::Symmetric(_) => {
1704 return Err(InvalidKeyError::InconsistentParameters(
1705 "RFC 7517: x5c is not valid for symmetric (oct) keys".to_string(),
1706 )
1707 .into());
1708 }
1709 }
1710
1711 Ok(())
1712 }
1713
1714 #[cfg(test)]
1715 fn validate_algorithm_strength_for_test(&self, alg: &Algorithm) -> Result<()> {
1716 self.validate_algorithm_key_strength(alg)
1717 }
1718
1719 #[must_use]
1724 pub fn thumbprint(&self) -> String {
1725 thumbprint::calculate_thumbprint(self)
1726 }
1727
1728 pub fn as_rsa(&self) -> Option<&RsaParams> {
1730 match &self.params {
1731 KeyParams::Rsa(p) => Some(p),
1732 _ => None,
1733 }
1734 }
1735
1736 pub fn as_ec(&self) -> Option<&EcParams> {
1738 match &self.params {
1739 KeyParams::Ec(p) => Some(p),
1740 _ => None,
1741 }
1742 }
1743
1744 pub fn as_symmetric(&self) -> Option<&SymmetricParams> {
1746 match &self.params {
1747 KeyParams::Symmetric(p) => Some(p),
1748 _ => None,
1749 }
1750 }
1751
1752 pub fn as_okp(&self) -> Option<&OkpParams> {
1754 match &self.params {
1755 KeyParams::Okp(p) => Some(p),
1756 _ => None,
1757 }
1758 }
1759
1760 #[must_use]
1788 pub fn to_public(&self) -> Option<Key> {
1789 let public_params = match &self.params {
1790 KeyParams::Rsa(p) => KeyParams::Rsa(p.to_public()),
1791 KeyParams::Ec(p) => KeyParams::Ec(p.to_public()),
1792 KeyParams::Okp(p) => KeyParams::Okp(p.to_public()),
1793 KeyParams::Symmetric(_) => return None, };
1795
1796 Some(Key {
1797 kid: self.kid.clone(),
1798 key_use: self.key_use.clone(),
1799 key_ops: self
1800 .key_ops
1801 .as_ref()
1802 .map(|ops| {
1803 ops.iter()
1804 .filter(|op| operation_survives_public_projection(op))
1805 .cloned()
1806 .collect::<Vec<_>>()
1807 })
1808 .filter(|ops| !ops.is_empty()),
1809 alg: self.alg.clone(),
1810 params: public_params,
1811 x5c: self.x5c.clone(),
1812 x5t: self.x5t.clone(),
1813 x5t_s256: self.x5t_s256.clone(),
1814 x5u: self.x5u.clone(),
1815 })
1816 }
1817}
1818
1819impl Debug for Key {
1820 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1821 f.debug_struct("Key")
1822 .field("kty", &self.kty())
1823 .field("kid", &self.kid)
1824 .field("key_use", &self.key_use)
1825 .field("alg", &self.alg)
1826 .field("params", &self.params)
1827 .finish()
1828 }
1829}
1830
1831impl PartialEq for Key {
1848 fn eq(&self, other: &Self) -> bool {
1849 self.kty() == other.kty()
1850 && self.kid == other.kid
1851 && self.key_use == other.key_use
1852 && self.key_ops == other.key_ops
1853 && self.alg == other.alg
1854 && self.params == other.params
1855 }
1856}
1857
1858impl Eq for Key {}
1859
1860impl Hash for Key {
1861 fn hash<H: Hasher>(&self, state: &mut H) {
1862 self.kty().hash(state);
1865 self.kid.hash(state);
1866 self.key_use.hash(state);
1867 self.key_ops.hash(state);
1868 self.alg.hash(state);
1869 self.params.hash(state);
1870 }
1871}
1872
1873impl Serialize for Key {
1875 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
1876 where
1877 S: Serializer,
1878 {
1879 use serde::ser::SerializeMap;
1880
1881 let mut field_count = 1; if self.kid.is_some() {
1884 field_count += 1;
1885 }
1886 if self.key_use.is_some() {
1887 field_count += 1;
1888 }
1889 if self.key_ops.is_some() {
1890 field_count += 1;
1891 }
1892 if self.alg.is_some() {
1893 field_count += 1;
1894 }
1895 if self.x5c.is_some() {
1896 field_count += 1;
1897 }
1898 if self.x5t.is_some() {
1899 field_count += 1;
1900 }
1901 if self.x5t_s256.is_some() {
1902 field_count += 1;
1903 }
1904 if self.x5u.is_some() {
1905 field_count += 1;
1906 }
1907
1908 field_count += match &self.params {
1910 KeyParams::Rsa(p) => {
1911 2 + if p.d.is_some() { 1 } else { 0 }
1912 + if p.p.is_some() { 1 } else { 0 }
1913 + if p.q.is_some() { 1 } else { 0 }
1914 + if p.dp.is_some() { 1 } else { 0 }
1915 + if p.dq.is_some() { 1 } else { 0 }
1916 + if p.qi.is_some() { 1 } else { 0 }
1917 + if p.oth.is_some() { 1 } else { 0 }
1918 }
1919 KeyParams::Ec(p) => 3 + if p.d.is_some() { 1 } else { 0 },
1920 KeyParams::Symmetric(_) => 1,
1921 KeyParams::Okp(p) => 2 + if p.d.is_some() { 1 } else { 0 },
1922 };
1923
1924 let mut map = serializer.serialize_map(Some(field_count))?;
1925
1926 map.serialize_entry("kty", self.kty().as_str())?;
1928
1929 if let Some(ref kid) = self.kid {
1931 map.serialize_entry("kid", kid)?;
1932 }
1933 if let Some(ref use_) = self.key_use {
1934 map.serialize_entry("use", use_)?;
1935 }
1936 if let Some(ref key_ops) = self.key_ops {
1937 map.serialize_entry("key_ops", key_ops)?;
1938 }
1939 if let Some(ref alg) = self.alg {
1940 map.serialize_entry("alg", alg)?;
1941 }
1942
1943 match &self.params {
1945 KeyParams::Rsa(p) => {
1946 map.serialize_entry("n", &p.n)?;
1947 map.serialize_entry("e", &p.e)?;
1948 if let Some(ref d) = p.d {
1949 map.serialize_entry("d", d)?;
1950 }
1951 if let Some(ref p_val) = p.p {
1952 map.serialize_entry("p", p_val)?;
1953 }
1954 if let Some(ref q) = p.q {
1955 map.serialize_entry("q", q)?;
1956 }
1957 if let Some(ref dp) = p.dp {
1958 map.serialize_entry("dp", dp)?;
1959 }
1960 if let Some(ref dq) = p.dq {
1961 map.serialize_entry("dq", dq)?;
1962 }
1963 if let Some(ref qi) = p.qi {
1964 map.serialize_entry("qi", qi)?;
1965 }
1966 if let Some(ref oth) = p.oth {
1967 map.serialize_entry("oth", oth)?;
1968 }
1969 }
1970 KeyParams::Ec(p) => {
1971 map.serialize_entry("crv", &p.crv)?;
1972 map.serialize_entry("x", &p.x)?;
1973 map.serialize_entry("y", &p.y)?;
1974 if let Some(ref d) = p.d {
1975 map.serialize_entry("d", d)?;
1976 }
1977 }
1978 KeyParams::Symmetric(p) => {
1979 map.serialize_entry("k", &p.k)?;
1980 }
1981 KeyParams::Okp(p) => {
1982 map.serialize_entry("crv", &p.crv)?;
1983 map.serialize_entry("x", &p.x)?;
1984 if let Some(ref d) = p.d {
1985 map.serialize_entry("d", d)?;
1986 }
1987 }
1988 }
1989
1990 if let Some(ref x5c) = self.x5c {
1992 map.serialize_entry("x5c", x5c)?;
1993 }
1994 if let Some(ref x5t) = self.x5t {
1995 map.serialize_entry("x5t", x5t)?;
1996 }
1997 if let Some(ref x5t_s256) = self.x5t_s256 {
1998 map.serialize_entry("x5t#S256", x5t_s256)?;
1999 }
2000 if let Some(ref x5u) = self.x5u {
2001 map.serialize_entry("x5u", x5u)?;
2002 }
2003
2004 map.end()
2005 }
2006}
2007
2008impl<'de> Deserialize<'de> for Key {
2010 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
2011 where
2012 D: Deserializer<'de>,
2013 {
2014 #[derive(Deserialize)]
2015 struct RawJwk {
2016 kty: String,
2017 kid: Option<String>,
2018 #[serde(rename = "use")]
2019 key_use: Option<KeyUse>,
2020 key_ops: Option<Vec<KeyOperation>>,
2021 alg: Option<Algorithm>,
2022
2023 n: Option<Base64UrlBytes>,
2025 e: Option<Base64UrlBytes>,
2026
2027 crv: Option<String>,
2029 x: Option<Base64UrlBytes>,
2030 y: Option<Base64UrlBytes>,
2031
2032 d: Option<Base64UrlBytes>,
2034
2035 p: Option<Base64UrlBytes>,
2037 q: Option<Base64UrlBytes>,
2038 dp: Option<Base64UrlBytes>,
2039 dq: Option<Base64UrlBytes>,
2040 qi: Option<Base64UrlBytes>,
2041
2042 oth: Option<Vec<rsa::RsaOtherPrime>>,
2044
2045 k: Option<Base64UrlBytes>,
2047
2048 x5c: Option<Vec<String>>,
2050 x5t: Option<String>,
2051 #[serde(rename = "x5t#S256")]
2052 x5t_s256: Option<String>,
2053 x5u: Option<String>,
2054 }
2055
2056 let raw = RawJwk::deserialize(deserializer)?;
2057
2058 let kty: KeyType = raw.kty.parse().map_err(serde::de::Error::custom)?;
2059
2060 let params = match kty {
2061 KeyType::Rsa => {
2062 let n = raw.n.ok_or_else(|| serde::de::Error::missing_field("n"))?;
2063 let e = raw.e.ok_or_else(|| serde::de::Error::missing_field("e"))?;
2064
2065 KeyParams::Rsa(RsaParams {
2066 n,
2067 e,
2068 d: raw.d,
2069 p: raw.p,
2070 q: raw.q,
2071 dp: raw.dp,
2072 dq: raw.dq,
2073 qi: raw.qi,
2074 oth: raw.oth,
2075 })
2076 }
2077 KeyType::Ec => {
2078 let crv_str = raw
2079 .crv
2080 .ok_or_else(|| serde::de::Error::missing_field("crv"))?;
2081 let crv: EcCurve = crv_str.parse().map_err(serde::de::Error::custom)?;
2082 let x = raw.x.ok_or_else(|| serde::de::Error::missing_field("x"))?;
2083 let y = raw.y.ok_or_else(|| serde::de::Error::missing_field("y"))?;
2084
2085 KeyParams::Ec(EcParams {
2086 crv,
2087 x,
2088 y,
2089 d: raw.d,
2090 })
2091 }
2092 KeyType::Symmetric => {
2093 let k = raw.k.ok_or_else(|| serde::de::Error::missing_field("k"))?;
2094
2095 KeyParams::Symmetric(SymmetricParams { k })
2096 }
2097 KeyType::Okp => {
2098 let crv_str = raw
2099 .crv
2100 .ok_or_else(|| serde::de::Error::missing_field("crv"))?;
2101 let crv: OkpCurve = crv_str.parse().map_err(serde::de::Error::custom)?;
2102 let x = raw.x.ok_or_else(|| serde::de::Error::missing_field("x"))?;
2103
2104 KeyParams::Okp(OkpParams { crv, x, d: raw.d })
2105 }
2106 };
2107
2108 Ok(Key {
2109 kid: raw.kid,
2110 key_use: raw.key_use,
2111 key_ops: raw.key_ops,
2112 alg: raw.alg,
2113 params,
2114 x5c: raw.x5c,
2115 x5t: raw.x5t,
2116 x5t_s256: raw.x5t_s256,
2117 x5u: raw.x5u,
2118 })
2119 }
2120}
2121
2122fn is_use_consistent_with_ops(key_use: &KeyUse, key_ops: &[KeyOperation]) -> bool {
2132 if key_ops.is_empty() {
2134 return true;
2135 }
2136
2137 match key_use {
2138 KeyUse::Signature => key_ops.iter().all(|op| {
2139 matches!(
2140 op,
2141 KeyOperation::Sign | KeyOperation::Verify | KeyOperation::Unknown(_)
2142 )
2143 }),
2144 KeyUse::Encryption => key_ops.iter().all(|op| {
2145 matches!(
2146 op,
2147 KeyOperation::Encrypt
2148 | KeyOperation::Decrypt
2149 | KeyOperation::WrapKey
2150 | KeyOperation::UnwrapKey
2151 | KeyOperation::DeriveKey
2152 | KeyOperation::DeriveBits
2153 | KeyOperation::Unknown(_)
2154 )
2155 }),
2156 KeyUse::Unknown(_) => true,
2158 }
2159}
2160
2161fn is_operation_allowed_by_use(key_use: &KeyUse, operation: &KeyOperation) -> bool {
2162 if matches!(operation, KeyOperation::Unknown(_)) {
2163 return true;
2164 }
2165
2166 match key_use {
2167 KeyUse::Signature => is_signature_operation(operation),
2168 KeyUse::Encryption => is_encryption_operation(operation),
2169 KeyUse::Unknown(_) => true,
2170 }
2171}
2172
2173fn is_signature_operation(operation: &KeyOperation) -> bool {
2174 matches!(operation, KeyOperation::Sign | KeyOperation::Verify)
2175}
2176
2177fn is_encryption_operation(operation: &KeyOperation) -> bool {
2178 matches!(
2179 operation,
2180 KeyOperation::Encrypt
2181 | KeyOperation::Decrypt
2182 | KeyOperation::WrapKey
2183 | KeyOperation::UnwrapKey
2184 | KeyOperation::DeriveKey
2185 | KeyOperation::DeriveBits
2186 )
2187}
2188
2189fn operation_survives_public_projection(operation: &KeyOperation) -> bool {
2190 matches!(
2191 operation,
2192 KeyOperation::Verify | KeyOperation::Encrypt | KeyOperation::WrapKey
2193 )
2194}
2195
2196impl Key {
2197 fn validate_declared_algorithm_match(&self, requested_alg: &Algorithm) -> Result<()> {
2198 if let Some(declared_alg) = self.alg()
2199 && declared_alg != requested_alg
2200 {
2201 return Err(Error::IncompatibleKey(
2202 IncompatibleKeyError::AlgorithmMismatch {
2203 requested: requested_alg.clone(),
2204 declared: declared_alg.clone(),
2205 },
2206 ));
2207 }
2208
2209 Ok(())
2210 }
2211}
2212
2213pub(crate) fn is_operation_compatible_with_algorithm(
2214 operation: &KeyOperation,
2215 alg: &Algorithm,
2216) -> bool {
2217 if matches!(operation, KeyOperation::Unknown(_)) {
2218 return true;
2219 }
2220
2221 debug_assert!(
2222 !alg.is_unknown(),
2223 "unknown algorithms should be rejected before operation/algorithm compatibility checks"
2224 );
2225
2226 match alg {
2227 Algorithm::Rs256
2228 | Algorithm::Rs384
2229 | Algorithm::Rs512
2230 | Algorithm::Ps256
2231 | Algorithm::Ps384
2232 | Algorithm::Ps512
2233 | Algorithm::Es256
2234 | Algorithm::Es384
2235 | Algorithm::Es512
2236 | Algorithm::Es256k
2237 | Algorithm::EdDsa
2238 | Algorithm::Ed25519
2239 | Algorithm::Ed448
2240 | Algorithm::Hs256
2241 | Algorithm::Hs384
2242 | Algorithm::Hs512 => matches!(operation, KeyOperation::Sign | KeyOperation::Verify),
2243 Algorithm::RsaOaep
2244 | Algorithm::RsaOaep256
2245 | Algorithm::RsaOaep384
2246 | Algorithm::RsaOaep512
2247 | Algorithm::Rsa1_5 => matches!(
2248 operation,
2249 KeyOperation::Encrypt
2250 | KeyOperation::Decrypt
2251 | KeyOperation::WrapKey
2252 | KeyOperation::UnwrapKey
2253 ),
2254 Algorithm::A128kw
2255 | Algorithm::A192kw
2256 | Algorithm::A256kw
2257 | Algorithm::A128gcmkw
2258 | Algorithm::A192gcmkw
2259 | Algorithm::A256gcmkw
2260 | Algorithm::Pbes2Hs256A128kw
2261 | Algorithm::Pbes2Hs384A192kw
2262 | Algorithm::Pbes2Hs512A256kw => {
2263 matches!(operation, KeyOperation::WrapKey | KeyOperation::UnwrapKey)
2264 }
2265 Algorithm::Dir
2266 | Algorithm::A128cbcHs256
2267 | Algorithm::A192cbcHs384
2268 | Algorithm::A256cbcHs512
2269 | Algorithm::A128gcm
2270 | Algorithm::A192gcm
2271 | Algorithm::A256gcm => matches!(operation, KeyOperation::Encrypt | KeyOperation::Decrypt),
2272 Algorithm::EcdhEs
2273 | Algorithm::EcdhEsA128kw
2274 | Algorithm::EcdhEsA192kw
2275 | Algorithm::EcdhEsA256kw => {
2276 matches!(
2277 operation,
2278 KeyOperation::DeriveKey | KeyOperation::DeriveBits
2279 )
2280 }
2281 Algorithm::Unknown(_) => false,
2284 }
2285}
2286
2287fn encode_der_integer(bytes: &[u8]) -> Vec<u8> {
2289 if bytes.is_empty() {
2290 return vec![0x02, 0x01, 0x00];
2291 }
2292
2293 let bytes = {
2294 let mut start = 0;
2295 while start < bytes.len() - 1 && bytes[start] == 0 {
2296 start += 1;
2297 }
2298 &bytes[start..]
2299 };
2300
2301 let needs_padding = (bytes[0] & 0x80) != 0;
2302 let len = bytes.len() + if needs_padding { 1 } else { 0 };
2303
2304 let mut der = Vec::with_capacity(2 + len + 2);
2305 der.push(0x02);
2306 encode_der_length(&mut der, len);
2307 if needs_padding {
2308 der.push(0);
2309 }
2310 der.extend_from_slice(bytes);
2311 der
2312}
2313
2314fn encode_der_length(der: &mut Vec<u8>, len: usize) {
2316 if len < 128 {
2317 der.push(len as u8);
2318 } else if len < 256 {
2319 der.push(0x81);
2320 der.push(len as u8);
2321 } else if len < 65536 {
2322 der.push(0x82);
2323 der.push((len >> 8) as u8);
2324 der.push(len as u8);
2325 } else {
2326 der.push(0x83);
2327 der.push((len >> 16) as u8);
2328 der.push((len >> 8) as u8);
2329 der.push(len as u8);
2330 }
2331}
2332
2333fn encode_rsa_public_key_der(n: &[u8], e: &[u8]) -> Vec<u8> {
2335 let n_der = encode_der_integer(n);
2336 let e_der = encode_der_integer(e);
2337
2338 let content_len = n_der.len() + e_der.len();
2339 let mut der = Vec::with_capacity(4 + content_len);
2340 der.push(0x30);
2341 encode_der_length(&mut der, content_len);
2342 der.extend_from_slice(&n_der);
2343 der.extend_from_slice(&e_der);
2344 der
2345}
2346
2347fn is_valid_base64(s: &str) -> bool {
2350 if s.is_empty() {
2351 return false;
2352 }
2353
2354 let bytes = s.as_bytes();
2355 let mut padding_started = false;
2356
2357 for (i, &b) in bytes.iter().enumerate() {
2358 match b {
2359 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'+' | b'/' => {
2360 if padding_started {
2361 return false; }
2363 }
2364 b'=' => {
2365 padding_started = true;
2366 let remaining = bytes.len() - i;
2368 if remaining > 2 {
2369 return false;
2370 }
2371 }
2372 _ => return false, }
2374 }
2375
2376 let len = s.len();
2379 if padding_started {
2380 len.is_multiple_of(4)
2381 } else {
2382 len % 4 != 1
2384 }
2385}
2386
2387fn validate_x509_thumbprint(
2393 thumbprint: &str,
2394 param_name: &'static str,
2395 expected_bytes: usize,
2396) -> Result<()> {
2397 use base64ct::{Base64UrlUnpadded, Encoding};
2398
2399 if !is_valid_base64url(thumbprint) {
2401 return Err(InvalidKeyError::InvalidParameter {
2402 name: param_name,
2403 reason: format!(
2404 "RFC 7517: {} must be base64url-encoded (invalid characters found)",
2405 param_name
2406 ),
2407 }
2408 .into());
2409 }
2410
2411 match Base64UrlUnpadded::decode_vec(thumbprint) {
2413 Ok(decoded) => {
2414 if decoded.len() != expected_bytes {
2415 return Err(InvalidKeyError::InvalidParameter {
2416 name: param_name,
2417 reason: format!(
2418 "RFC 7517: {} must be {} bytes when decoded (got {} bytes)",
2419 param_name,
2420 expected_bytes,
2421 decoded.len()
2422 ),
2423 }
2424 .into());
2425 }
2426 Ok(())
2427 }
2428 Err(_) => Err(InvalidKeyError::InvalidParameter {
2429 name: param_name,
2430 reason: format!("RFC 7517: {} failed base64url decoding", param_name),
2431 }
2432 .into()),
2433 }
2434}
2435
2436fn is_valid_base64url(s: &str) -> bool {
2439 if s.is_empty() {
2440 return false;
2441 }
2442
2443 for b in s.bytes() {
2444 match b {
2445 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' => {}
2446 _ => return false,
2447 }
2448 }
2449
2450 s.len() % 4 != 1
2452}
2453
2454#[cfg(test)]
2455mod tests {
2456 use super::*;
2457
2458 #[test]
2459 fn test_parse_rsa_public_key() {
2460 let json = r#"{
2461 "kty": "RSA",
2462 "kid": "test-key",
2463 "use": "sig",
2464 "alg": "RS256",
2465 "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
2466 "e": "AQAB"
2467 }"#;
2468
2469 let jwk: Key = serde_json::from_str(json).unwrap();
2470 assert_eq!(jwk.kty(), KeyType::Rsa);
2471 assert_eq!(jwk.kid, Some("test-key".to_string()));
2472 assert_eq!(jwk.key_use, Some(KeyUse::Signature));
2473 assert_eq!(jwk.alg, Some(Algorithm::Rs256));
2474 assert!(jwk.is_public_key_only());
2475 }
2476
2477 #[test]
2478 fn test_parse_ec_public_key() {
2479 let json = r#"{
2480 "kty": "EC",
2481 "crv": "P-256",
2482 "x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
2483 "y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM"
2484 }"#;
2485
2486 let jwk: Key = serde_json::from_str(json).unwrap();
2487 assert_eq!(jwk.kty(), KeyType::Ec);
2488
2489 let ec = jwk.as_ec().unwrap();
2490 assert_eq!(ec.crv, EcCurve::P256);
2491 assert!(jwk.is_public_key_only());
2492 }
2493
2494 #[test]
2495 fn test_parse_symmetric_key() {
2496 let json = r#"{
2497 "kty": "oct",
2498 "k": "GawgguFyGrWKav7AX4VKUg"
2499 }"#;
2500
2501 let jwk: Key = serde_json::from_str(json).unwrap();
2502 assert_eq!(jwk.kty(), KeyType::Symmetric);
2503 assert!(jwk.as_symmetric().is_some());
2504 }
2505
2506 #[test]
2507 fn test_parse_okp_key() {
2508 let json = r#"{
2509 "kty": "OKP",
2510 "crv": "Ed25519",
2511 "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"
2512 }"#;
2513
2514 let jwk: Key = serde_json::from_str(json).unwrap();
2515 assert_eq!(jwk.kty(), KeyType::Okp);
2516
2517 let okp = jwk.as_okp().unwrap();
2518 assert_eq!(okp.crv, OkpCurve::Ed25519);
2519 }
2520
2521 #[test]
2522 fn test_roundtrip_serialization() {
2523 let json = r#"{"kty":"RSA","kid":"test","use":"sig","n":"AQAB","e":"AQAB"}"#;
2524 let jwk: Key = serde_json::from_str(json).unwrap();
2525 let serialized = serde_json::to_string(&jwk).unwrap();
2526 let deserialized: Key = serde_json::from_str(&serialized).unwrap();
2527 assert_eq!(jwk, deserialized);
2528 }
2529
2530 #[test]
2531 fn test_is_algorithm_compatible_rsa() {
2532 let json = r#"{"kty":"RSA","n":"AQAB","e":"AQAB"}"#;
2533 let key: Key = serde_json::from_str(json).unwrap();
2534
2535 assert!(key.is_algorithm_compatible(&Algorithm::Rs256));
2537 assert!(key.is_algorithm_compatible(&Algorithm::Rs384));
2538 assert!(key.is_algorithm_compatible(&Algorithm::Rs512));
2539 assert!(key.is_algorithm_compatible(&Algorithm::Ps256));
2540 assert!(key.is_algorithm_compatible(&Algorithm::Ps384));
2541 assert!(key.is_algorithm_compatible(&Algorithm::Ps512));
2542 assert!(key.is_algorithm_compatible(&Algorithm::RsaOaep));
2543 assert!(key.is_algorithm_compatible(&Algorithm::RsaOaep256));
2544
2545 assert!(!key.is_algorithm_compatible(&Algorithm::Es256));
2547 assert!(!key.is_algorithm_compatible(&Algorithm::Hs256));
2548 assert!(!key.is_algorithm_compatible(&Algorithm::EdDsa));
2549 assert!(!key.is_algorithm_compatible(&Algorithm::Ed25519));
2550 assert!(!key.is_algorithm_compatible(&Algorithm::Ed448));
2551 }
2552
2553 #[test]
2554 fn test_is_algorithm_compatible_ec() {
2555 let p256_json = r#"{"kty":"EC","crv":"P-256","x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4","y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM"}"#;
2556 let p256: Key = serde_json::from_str(p256_json).unwrap();
2557
2558 assert!(p256.is_algorithm_compatible(&Algorithm::Es256));
2559 assert!(!p256.is_algorithm_compatible(&Algorithm::Es384));
2560 assert!(!p256.is_algorithm_compatible(&Algorithm::Rs256));
2561 assert!(!p256.is_algorithm_compatible(&Algorithm::Hs256));
2562 }
2563
2564 #[test]
2565 fn test_is_algorithm_compatible_symmetric() {
2566 let json = r#"{"kty":"oct","k":"GawgguFyGrWKav7AX4VKUg"}"#;
2567 let key: Key = serde_json::from_str(json).unwrap();
2568
2569 assert!(key.is_algorithm_compatible(&Algorithm::Hs256));
2570 assert!(key.is_algorithm_compatible(&Algorithm::Hs384));
2571 assert!(key.is_algorithm_compatible(&Algorithm::Hs512));
2572 assert!(key.is_algorithm_compatible(&Algorithm::A128kw));
2573
2574 assert!(!key.is_algorithm_compatible(&Algorithm::Rs256));
2575 assert!(!key.is_algorithm_compatible(&Algorithm::Es256));
2576 }
2577
2578 #[test]
2579 fn test_is_algorithm_compatible_okp() {
2580 let json =
2581 r#"{"kty":"OKP","crv":"Ed25519","x":"11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"}"#;
2582 let key: Key = serde_json::from_str(json).unwrap();
2583
2584 assert!(key.is_algorithm_compatible(&Algorithm::EdDsa));
2585 assert!(key.is_algorithm_compatible(&Algorithm::Ed25519));
2586 assert!(!key.is_algorithm_compatible(&Algorithm::Ed448));
2587 assert!(!key.is_algorithm_compatible(&Algorithm::Rs256));
2588 assert!(!key.is_algorithm_compatible(&Algorithm::Es256));
2589 }
2590
2591 #[test]
2592 fn test_is_algorithm_compatible_okp_ed448() {
2593 let json = r#"{
2594 "kty": "OKP",
2595 "crv": "Ed448",
2596 "x": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
2597 }"#;
2598 let key: Key = serde_json::from_str(json).unwrap();
2599
2600 assert!(key.is_algorithm_compatible(&Algorithm::EdDsa));
2601 assert!(!key.is_algorithm_compatible(&Algorithm::Ed25519));
2602 assert!(key.is_algorithm_compatible(&Algorithm::Ed448));
2603 }
2604
2605 #[test]
2606 fn test_parse_rfc9864_ed_algorithms() {
2607 assert_eq!(Algorithm::from("Ed25519"), Algorithm::Ed25519);
2608 assert_eq!(Algorithm::from("Ed448"), Algorithm::Ed448);
2609 assert_eq!("Ed25519".parse::<Algorithm>().unwrap(), Algorithm::Ed25519);
2610 assert_eq!("Ed448".parse::<Algorithm>().unwrap(), Algorithm::Ed448);
2611 assert_eq!(Algorithm::Ed25519.as_str(), "Ed25519");
2612 assert_eq!(Algorithm::Ed448.as_str(), "Ed448");
2613 }
2614
2615 #[test]
2616 fn test_parse_key_use_and_operation_with_from_str() {
2617 assert_eq!("sig".parse::<KeyUse>().unwrap(), KeyUse::Signature);
2618 assert_eq!("enc".parse::<KeyUse>().unwrap(), KeyUse::Encryption);
2619 assert_eq!(
2620 "private-use".parse::<KeyUse>().unwrap(),
2621 KeyUse::Unknown("private-use".to_string())
2622 );
2623
2624 assert_eq!("sign".parse::<KeyOperation>().unwrap(), KeyOperation::Sign);
2625 assert_eq!(
2626 "verify".parse::<KeyOperation>().unwrap(),
2627 KeyOperation::Verify
2628 );
2629 assert_eq!(
2630 "custom-op".parse::<KeyOperation>().unwrap(),
2631 KeyOperation::Unknown("custom-op".to_string())
2632 );
2633 }
2634
2635 #[test]
2636 fn test_algorithm_deprecation_status() {
2637 assert!(Algorithm::EdDsa.is_deprecated());
2638 assert!(!Algorithm::Ed25519.is_deprecated());
2639 assert!(!Algorithm::Ed448.is_deprecated());
2640 assert!(!Algorithm::Rs256.is_deprecated());
2641 }
2642
2643 #[test]
2644 fn test_is_algorithm_compatible_unknown_algorithm() {
2645 let json = r#"{"kty":"RSA","n":"AQAB","e":"AQAB"}"#;
2646 let key: Key = serde_json::from_str(json).unwrap();
2647
2648 assert!(!key.is_algorithm_compatible(&Algorithm::Unknown("CUSTOM".to_string())));
2649 }
2650
2651 #[test]
2652 fn test_to_public_rsa() {
2653 let json = r#"{
2654 "kty": "RSA",
2655 "kid": "rsa-key",
2656 "use": "sig",
2657 "alg": "RS256",
2658 "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
2659 "e": "AQAB",
2660 "d": "X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqijwp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBznbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q"
2661 }"#;
2662 let private_key: Key = serde_json::from_str(json).unwrap();
2663 assert!(private_key.has_private_key());
2664
2665 let public_key = private_key.to_public().unwrap();
2666 assert!(public_key.is_public_key_only());
2667 assert_eq!(public_key.kty(), KeyType::Rsa);
2668 assert_eq!(public_key.kid, Some("rsa-key".to_string()));
2669 assert_eq!(public_key.key_use, Some(KeyUse::Signature));
2670 assert_eq!(public_key.alg, Some(Algorithm::Rs256));
2671
2672 let rsa = public_key.as_rsa().unwrap();
2673 assert!(rsa.d.is_none());
2674 assert_eq!(rsa.n, private_key.as_rsa().unwrap().n);
2676 }
2677
2678 #[test]
2679 fn test_to_public_ec() {
2680 let json = r#"{
2681 "kty": "EC",
2682 "crv": "P-256",
2683 "x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
2684 "y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
2685 "d": "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE"
2686 }"#;
2687 let private_key: Key = serde_json::from_str(json).unwrap();
2688 assert!(private_key.has_private_key());
2689
2690 let public_key = private_key.to_public().unwrap();
2691 assert!(public_key.is_public_key_only());
2692 assert_eq!(public_key.kty(), KeyType::Ec);
2693
2694 let ec = public_key.as_ec().unwrap();
2695 assert!(ec.d.is_none());
2696 assert_eq!(ec.crv, EcCurve::P256);
2697 }
2698
2699 #[test]
2700 fn test_to_public_okp() {
2701 let json = r#"{
2702 "kty": "OKP",
2703 "crv": "Ed25519",
2704 "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo",
2705 "d": "nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A"
2706 }"#;
2707 let private_key: Key = serde_json::from_str(json).unwrap();
2708 assert!(private_key.has_private_key());
2709
2710 let public_key = private_key.to_public().unwrap();
2711 assert!(public_key.is_public_key_only());
2712 assert_eq!(public_key.kty(), KeyType::Okp);
2713
2714 let okp = public_key.as_okp().unwrap();
2715 assert!(okp.d.is_none());
2716 assert_eq!(okp.crv, OkpCurve::Ed25519);
2717 }
2718
2719 #[test]
2720 fn test_to_public_symmetric_returns_none() {
2721 let json = r#"{"kty":"oct","k":"GawgguFyGrWKav7AX4VKUg"}"#;
2722 let key: Key = serde_json::from_str(json).unwrap();
2723 assert!(key.to_public().is_none());
2724 }
2725
2726 #[test]
2727 fn test_to_public_already_public() {
2728 let json = r#"{"kty":"RSA","n":"AQAB","e":"AQAB"}"#;
2729 let key: Key = serde_json::from_str(json).unwrap();
2730 assert!(key.is_public_key_only());
2731
2732 let public = key.to_public().unwrap();
2733 assert!(public.is_public_key_only());
2734 assert_eq!(key, public);
2735 }
2736
2737 #[test]
2738 fn test_to_public_filters_private_only_key_ops() {
2739 let key = Key::new(KeyParams::Rsa(RsaParams::new_private(
2740 Base64UrlBytes::new(vec![0x01; 256]),
2741 Base64UrlBytes::new(vec![0x01, 0x00, 0x01]),
2742 Base64UrlBytes::new(vec![0x02; 256]),
2743 None,
2744 None,
2745 None,
2746 None,
2747 None,
2748 )))
2749 .with_key_ops([
2750 KeyOperation::Sign,
2751 KeyOperation::Verify,
2752 KeyOperation::Decrypt,
2753 KeyOperation::Encrypt,
2754 KeyOperation::WrapKey,
2755 KeyOperation::UnwrapKey,
2756 KeyOperation::DeriveKey,
2757 KeyOperation::Unknown("custom".into()),
2758 ]);
2759
2760 let public = key.to_public().unwrap();
2761
2762 assert_eq!(
2763 public.key_ops(),
2764 Some(
2765 &[
2766 KeyOperation::Verify,
2767 KeyOperation::Encrypt,
2768 KeyOperation::WrapKey,
2769 ][..]
2770 )
2771 );
2772 }
2773
2774 #[test]
2775 fn test_to_public_clears_empty_key_ops_after_projection() {
2776 let key = Key::new(KeyParams::Ec(EcParams::new_private(
2777 EcCurve::P256,
2778 Base64UrlBytes::new(vec![0x01; 32]),
2779 Base64UrlBytes::new(vec![0x02; 32]),
2780 Base64UrlBytes::new(vec![0x03; 32]),
2781 )))
2782 .with_key_ops([KeyOperation::Sign]);
2783
2784 let public = key.to_public().unwrap();
2785
2786 assert_eq!(public.key_ops(), None);
2787 }
2788
2789 #[test]
2790 fn test_validate_algorithm_strength_enforces_cbc_hs_sizes() {
2791 let k256 = Base64UrlBytes::new(vec![0u8; 32]);
2792 let k384 = Base64UrlBytes::new(vec![0u8; 48]);
2793 let k512 = Base64UrlBytes::new(vec![0u8; 64]);
2794
2795 let key_256 = Key::new(KeyParams::Symmetric(SymmetricParams::new(k256)));
2796 assert!(
2797 key_256
2798 .validate_algorithm_strength_for_test(&Algorithm::A128cbcHs256)
2799 .is_ok()
2800 );
2801 assert!(
2802 key_256
2803 .validate_algorithm_strength_for_test(&Algorithm::A192cbcHs384)
2804 .is_err()
2805 );
2806
2807 let key_384 = Key::new(KeyParams::Symmetric(SymmetricParams::new(k384)));
2808 assert!(
2809 key_384
2810 .validate_algorithm_strength_for_test(&Algorithm::A192cbcHs384)
2811 .is_ok()
2812 );
2813 assert!(
2814 key_384
2815 .validate_algorithm_strength_for_test(&Algorithm::A256cbcHs512)
2816 .is_err()
2817 );
2818
2819 let key_512 = Key::new(KeyParams::Symmetric(SymmetricParams::new(k512)));
2820 assert!(
2821 key_512
2822 .validate_algorithm_strength_for_test(&Algorithm::A256cbcHs512)
2823 .is_ok()
2824 );
2825 }
2826 #[test]
2827 fn test_check_algorithm_suitability_enforces_strength_without_key_alg() {
2828 let weak_hmac_key = Key::new(KeyParams::Symmetric(SymmetricParams::new(
2829 Base64UrlBytes::new(vec![0u8; 31]),
2830 )));
2831
2832 assert!(weak_hmac_key.validate().is_ok());
2834
2835 assert!(
2837 weak_hmac_key
2838 .check_algorithm_suitability(&Algorithm::Hs256)
2839 .is_err()
2840 );
2841 }
2842
2843 #[test]
2844 fn test_check_operation_intent_enforces_use_when_present() {
2845 let key = Key::new(KeyParams::Symmetric(SymmetricParams::new(
2846 Base64UrlBytes::new(vec![0u8; 32]),
2847 )))
2848 .with_use(KeyUse::Encryption);
2849
2850 assert!(key.check_operation_intent(&[KeyOperation::Encrypt]).is_ok());
2851 assert!(key.check_operation_intent(&[KeyOperation::Sign]).is_err());
2852 }
2853
2854 #[test]
2855 fn test_check_operation_intent_enforces_key_ops_when_present() {
2856 let key = Key::new(KeyParams::Rsa(RsaParams::new_public(
2857 Base64UrlBytes::new(vec![1, 2, 3]),
2858 Base64UrlBytes::new(vec![1, 0, 1]),
2859 )))
2860 .with_key_ops(vec![KeyOperation::Verify]);
2861
2862 assert!(key.check_operation_intent(&[KeyOperation::Verify]).is_ok());
2863 assert!(key.check_operation_intent(&[KeyOperation::Sign]).is_err());
2864 }
2865
2866 #[test]
2867 fn test_check_operation_intent_allows_missing_optional_fields() {
2868 let key = Key::new(KeyParams::Rsa(RsaParams::new_public(
2869 Base64UrlBytes::new(vec![1, 2, 3]),
2870 Base64UrlBytes::new(vec![1, 0, 1]),
2871 )));
2872
2873 assert!(key.check_operation_intent(&[KeyOperation::Verify]).is_ok());
2874 assert!(key.check_operation_intent(&[KeyOperation::Sign]).is_ok());
2875 }
2876
2877 #[test]
2878 fn test_validate_for_use_rejects_empty_operation_set() {
2879 let key = Key::new(KeyParams::Rsa(RsaParams::new_public(
2880 Base64UrlBytes::new(vec![1, 2, 3]),
2881 Base64UrlBytes::new(vec![1, 0, 1]),
2882 )));
2883
2884 let result = key.validate_for_use(&Algorithm::Rs256, vec![]);
2885 assert!(matches!(result, Err(Error::InvalidInput(_))));
2886 }
2887
2888 #[test]
2889 fn test_validate_for_use_rejects_sign_with_public_rsa_key() {
2890 let mut n = vec![0xff; 256];
2891 n[255] = 0x01;
2892 let key = Key::new(KeyParams::Rsa(RsaParams::new_public(
2893 Base64UrlBytes::new(n),
2894 Base64UrlBytes::new(vec![1, 0, 1]),
2895 )));
2896
2897 let result = key.validate_for_use(&Algorithm::Rs256, [KeyOperation::Sign]);
2898 assert!(matches!(
2899 result,
2900 Err(Error::IncompatibleKey(
2901 IncompatibleKeyError::OperationNotPermitted { .. }
2902 ))
2903 ));
2904 }
2905
2906 #[test]
2907 fn test_validate_for_use_rejects_sign_with_public_okp_key() {
2908 let key = Key::new(KeyParams::Okp(OkpParams::new_public(
2909 OkpCurve::Ed25519,
2910 Base64UrlBytes::new(vec![0u8; 32]),
2911 )));
2912
2913 let result = key.validate_for_use(&Algorithm::Ed25519, [KeyOperation::Sign]);
2914 assert!(matches!(
2915 result,
2916 Err(Error::IncompatibleKey(
2917 IncompatibleKeyError::OperationNotPermitted { .. }
2918 ))
2919 ));
2920 }
2921
2922 #[test]
2923 fn test_validate_for_use_rejects_sign_with_public_ec_key() {
2924 let key = Key::new(KeyParams::Ec(EcParams::new_public(
2925 EcCurve::P256,
2926 Base64UrlBytes::new(vec![0u8; 32]),
2927 Base64UrlBytes::new(vec![0u8; 32]),
2928 )));
2929
2930 let result = key.validate_for_use(&Algorithm::Es256, [KeyOperation::Sign]);
2931 assert!(matches!(
2932 result,
2933 Err(Error::IncompatibleKey(
2934 IncompatibleKeyError::OperationNotPermitted { .. }
2935 ))
2936 ));
2937 }
2938
2939 #[test]
2940 fn test_validate_for_use_rejects_unknown_algorithm() {
2941 let key = Key::new(KeyParams::Symmetric(SymmetricParams::new(
2942 Base64UrlBytes::new(vec![0u8; 32]),
2943 )));
2944
2945 let result = key.validate_for_use(
2946 &Algorithm::Unknown("CUSTOM-ALG".to_string()),
2947 [KeyOperation::Sign],
2948 );
2949 assert!(matches!(
2950 result,
2951 Err(Error::IncompatibleKey(
2952 IncompatibleKeyError::IncompatibleAlgorithm { .. }
2953 ))
2954 ));
2955 }
2956
2957 #[test]
2958 fn test_validate_for_use_rejects_operation_algorithm_mismatch() {
2959 let key = Key::new(KeyParams::Symmetric(SymmetricParams::new(
2960 Base64UrlBytes::new(vec![0u8; 32]),
2961 )));
2962
2963 let result = key.validate_for_use(&Algorithm::Hs256, [KeyOperation::Encrypt]);
2964 assert!(matches!(
2965 result,
2966 Err(Error::IncompatibleKey(
2967 IncompatibleKeyError::OperationNotPermitted { .. }
2968 ))
2969 ));
2970 }
2971
2972 #[test]
2973 fn test_validate_for_use_rejects_declared_algorithm_mismatch() {
2974 let key = Key::new(KeyParams::Symmetric(SymmetricParams::new(
2975 Base64UrlBytes::new(vec![0u8; 32]),
2976 )))
2977 .with_alg(Algorithm::Hs256);
2978
2979 let result = key.validate_for_use(&Algorithm::Hs384, [KeyOperation::Sign]);
2980 assert!(matches!(
2981 result,
2982 Err(Error::IncompatibleKey(
2983 IncompatibleKeyError::AlgorithmMismatch { .. }
2984 ))
2985 ));
2986 }
2987
2988 #[test]
2989 fn test_check_operation_intent_rejects_inconsistent_use_and_key_ops() {
2990 let key = Key::new(KeyParams::Rsa(RsaParams::new_public(
2991 Base64UrlBytes::new(vec![1, 2, 3]),
2992 Base64UrlBytes::new(vec![1, 0, 1]),
2993 )))
2994 .with_use(KeyUse::Signature)
2995 .with_key_ops(vec![KeyOperation::Encrypt]);
2996
2997 assert!(key.check_operation_intent(&[KeyOperation::Verify]).is_err());
2998 }
2999
3000 #[test]
3001 fn test_check_operation_intent_allows_unknown_operation_with_use() {
3002 let key = Key::new(KeyParams::Symmetric(SymmetricParams::new(
3003 Base64UrlBytes::new(vec![0u8; 32]),
3004 )))
3005 .with_use(KeyUse::Signature);
3006
3007 let result = key.check_operation_intent(&[KeyOperation::Unknown("custom-op".into())]);
3008 assert!(result.is_ok());
3009 }
3010}