diff --git a/crates/jose/tests/jws.rs b/crates/jose/tests/jws.rs index b706b58c..b88c2d87 100644 --- a/crates/jose/tests/jws.rs +++ b/crates/jose/tests/jws.rs @@ -94,20 +94,18 @@ macro_rules! asymetric_jwt_test { } conditional! { $supported => - use mas_iana::jose::JsonWebKeyUse; - use mas_jose::{constraints::Constraint, jwt::JsonWebSignatureHeader}; + use mas_jose::jwt::JsonWebSignatureHeader; #[test] fn verify_jwt() { let jwks = public_jwks(); let jwt: Jwt<'_, Payload> = Jwt::try_from($jwt).unwrap(); - let key = ConstraintSet::from(jwt.header()) - .filter(jwks.deref())[0]; + let key = jwks.find_key(&jwt.header().into()).unwrap(); let key = mas_jose::jwa::AsymmetricVerifyingKey::from_jwk_and_alg( key.params(), - JsonWebSignatureAlg::$alg + JsonWebSignatureAlg::$alg, ) .unwrap(); @@ -116,34 +114,27 @@ macro_rules! asymetric_jwt_test { #[test] fn sign_and_verify_jwt() { - let payload = Payload { hello: "world".to_string() }; - let header = JsonWebSignatureHeader::new(JsonWebSignatureAlg::$alg); + let alg = JsonWebSignatureAlg::$alg; + let payload = Payload { + hello: "world".to_string(), + }; + let header = JsonWebSignatureHeader::new(alg); let jwks = private_jwks(); - let key = ConstraintSet::new(vec![ - Constraint::alg(JsonWebSignatureAlg::$alg), - Constraint::use_(JsonWebKeyUse::Sig), - ]) - .filter(jwks.deref())[0]; + let key = jwks.signing_key_for_algorithm(alg).unwrap(); - let key = mas_jose::jwa::AsymmetricSigningKey::from_jwk_and_alg( - key.params(), - JsonWebSignatureAlg::$alg, - ) - .unwrap(); + let key = mas_jose::jwa::AsymmetricSigningKey::from_jwk_and_alg(key.params(), alg) + .unwrap(); - let jwks = public_jwks(); let jwt: Jwt<'_, Payload> = Jwt::sign(header, payload, &key).unwrap(); let jwt: Jwt<'_, Payload> = Jwt::try_from(jwt.as_str()).unwrap(); - let key = ConstraintSet::from(jwt.header()) - .filter(jwks.deref())[0]; + let jwks = public_jwks(); + let key = jwks.find_key(&jwt.header().into()).unwrap(); - let key = mas_jose::jwa::AsymmetricVerifyingKey::from_jwk_and_alg( - key.params(), - JsonWebSignatureAlg::$alg - ) - .unwrap(); + let key = + mas_jose::jwa::AsymmetricVerifyingKey::from_jwk_and_alg(key.params(), alg) + .unwrap(); jwt.verify(&key).unwrap(); } @@ -178,14 +169,13 @@ macro_rules! symetric_jwt_test { #[test] fn sign_and_verify_jwt() { + let alg = JsonWebSignatureAlg::$alg; let payload = Payload { hello: "world".to_string(), }; - let header = JsonWebSignatureHeader::new(JsonWebSignatureAlg::$alg); + let header = JsonWebSignatureHeader::new(alg); - let key = - mas_jose::jwa::SymmetricKey::new_for_alg(oct_key(), JsonWebSignatureAlg::$alg) - .unwrap(); + let key = mas_jose::jwa::SymmetricKey::new_for_alg(oct_key(), alg).unwrap(); let jwt: Jwt<'_, Payload> = Jwt::sign(header, payload, &key).unwrap(); let jwt: Jwt<'_, Payload> = Jwt::try_from(jwt.as_str()).unwrap(); diff --git a/crates/keystore/src/lib.rs b/crates/keystore/src/lib.rs index 968e0fed..abb65415 100644 --- a/crates/keystore/src/lib.rs +++ b/crates/keystore/src/lib.rs @@ -114,8 +114,27 @@ pub enum LoadError { }, } +impl LoadError { + /// Returns `true` if the load error is [`Encrypted`]. + /// + /// [`Encrypted`]: LoadError::Encrypted + #[must_use] + pub fn is_encrypted(&self) -> bool { + matches!(self, Self::Encrypted) + } + + /// Returns `true` if the load error is [`Unencrypted`]. + /// + /// [`Unencrypted`]: LoadError::Unencrypted + #[must_use] + pub fn is_unencrypted(&self) -> bool { + matches!(self, Self::Unencrypted) + } +} + /// A single private key #[non_exhaustive] +#[derive(Debug)] pub enum PrivateKey { Rsa(Box), EcP256(Box>), @@ -278,7 +297,7 @@ impl PrivateKey { || sec1::EcPrivateKey::from_der(der).is_ok() || pkcs1::RsaPrivateKey::from_der(der).is_ok() { - return Err(LoadError::Encrypted); + return Err(LoadError::Unencrypted); } Err(LoadError::UnsupportedFormat) diff --git a/crates/keystore/tests/load.rs b/crates/keystore/tests/keystore.rs similarity index 84% rename from crates/keystore/tests/load.rs rename to crates/keystore/tests/keystore.rs index 4ee48077..1779c440 100644 --- a/crates/keystore/tests/load.rs +++ b/crates/keystore/tests/keystore.rs @@ -20,6 +20,8 @@ use mas_keystore::PrivateKey; static PASSWORD: &str = "hunter2"; +/// Generate a test which loads a key, and then tries signing and verifying a +/// JWT for each available algorithm macro_rules! plain_test { ($name:ident, $kind:ident, $path:literal) => { #[test] @@ -43,6 +45,8 @@ macro_rules! plain_test { }; } +/// Generate a test which loads an encrypted key, and then tries signing and +/// verifying a JWT for each available algorithm macro_rules! enc_test { ($name:ident, $kind:ident, $path:literal) => { #[test] @@ -66,6 +70,7 @@ macro_rules! enc_test { }; } +/// Generate a PEM decoding and encoding test macro_rules! pem_test { ($name:ident, $path:literal) => { pem_test!($name, $path, compare = true); @@ -84,6 +89,7 @@ macro_rules! pem_test { }; } +/// Generate a DER decoding and encoding test macro_rules! der_test { ($name:ident, $path:literal) => { der_test!($name, $path, compare = true); @@ -138,3 +144,25 @@ pem_test!(serialize_ec_p384_sec1_pem, "ec-p384.sec1"); der_test!(serialize_ec_p384_sec1_der, "ec-p384.sec1", compare = false); pem_test!(serialize_ec_k256_sec1_pem, "ec-k256.sec1"); der_test!(serialize_ec_k256_sec1_der, "ec-k256.sec1", compare = false); + +#[test] +fn load_encrypted_as_unencrypted_error() { + let pem = include_str!("./keys/rsa.pkcs8.encrypted.pem"); + assert!(PrivateKey::load_pem(pem).unwrap_err().is_encrypted()); + + let der = include_bytes!("./keys/rsa.pkcs8.encrypted.der"); + assert!(PrivateKey::load_der(der).unwrap_err().is_encrypted()); +} + +#[test] +fn load_unencrypted_as_encrypted_error() { + let pem = include_str!("./keys/rsa.pkcs8.pem"); + assert!(PrivateKey::load_encrypted_pem(pem, PASSWORD) + .unwrap_err() + .is_unencrypted()); + + let der = include_bytes!("./keys/rsa.pkcs8.der"); + assert!(PrivateKey::load_encrypted_der(der, PASSWORD) + .unwrap_err() + .is_unencrypted()); +}