diff --git a/Cargo.lock b/Cargo.lock index fc064166..7dd79d52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3811,7 +3811,8 @@ dependencies = [ [[package]] name = "rsa" version = "0.7.0-pre" -source = "git+https://github.com/RustCrypto/RSA.git#40242fbbb019cac4af216145bfa468a0d24d12ef" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6168b9a0f38e487db90dc109ad6d8f37fc5590183b7bfe8d8687e0b86116d53f" dependencies = [ "byteorder", "digest 0.10.3", @@ -3822,7 +3823,6 @@ dependencies = [ "pkcs1", "pkcs8", "rand_core", - "signature", "smallvec", "subtle", "zeroize", diff --git a/crates/jose/Cargo.toml b/crates/jose/Cargo.toml index f8b24a13..aaf20c9e 100644 --- a/crates/jose/Cargo.toml +++ b/crates/jose/Cargo.toml @@ -18,7 +18,7 @@ k256 = { version = "0.11.2", features = ["ecdsa"] } p256 = { version = "0.11.1", features = ["ecdsa"] } p384 = { version = "0.11.2", features = ["ecdsa"] } rand = "0.8.5" -rsa = { git = "https://github.com/RustCrypto/RSA.git" } +rsa = "0.7.0-pre" schemars = "0.8.10" sec1 = "0.3.0" serde = { version = "1.0.144", features = ["derive"] } diff --git a/crates/jose/src/jwa/rsa.rs b/crates/jose/src/jwa/rsa.rs index f8e7ea99..e9b1b100 100644 --- a/crates/jose/src/jwa/rsa.rs +++ b/crates/jose/src/jwa/rsa.rs @@ -15,6 +15,8 @@ // This is a temporary wrapper until the RSA crate actually hashes the input // See +use super::signature::Signature; + pub trait RsaHashIdentifier { const HASH: rsa::Hash; } @@ -39,67 +41,62 @@ pub(crate) mod pkcs1v15 { use std::marker::PhantomData; use digest::Digest; - use rsa::{RsaPrivateKey, RsaPublicKey}; + use rsa::{PaddingScheme, PublicKey, RsaPrivateKey, RsaPublicKey}; - use super::RsaHashIdentifier; + use super::{RsaHashIdentifier, Signature}; pub struct VerifyingKey { - inner: rsa::pkcs1v15::VerifyingKey, + inner: RsaPublicKey, hash: PhantomData, } - impl From for VerifyingKey - where - H: RsaHashIdentifier, - { - fn from(key: RsaPublicKey) -> Self { - let inner = rsa::pkcs1v15::VerifyingKey::new_with_hash(key, H::HASH); + impl From for VerifyingKey { + fn from(inner: RsaPublicKey) -> Self { Self { inner, - hash: PhantomData::default(), + hash: PhantomData, } } } - impl signature::Verifier for VerifyingKey + impl signature::Verifier for VerifyingKey where - H: Digest, + H: Digest + RsaHashIdentifier, { - fn verify( - &self, - msg: &[u8], - signature: &rsa::pkcs1v15::Signature, - ) -> Result<(), signature::Error> { + fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), signature::Error> { let digest = H::digest(msg); - self.inner.verify(&digest, signature) + let padding = PaddingScheme::new_pkcs1v15_sign(Some(H::HASH)); + self.inner + .verify(padding, &digest, signature.as_ref()) + .map_err(signature::Error::from_source) } } pub struct SigningKey { - inner: rsa::pkcs1v15::SigningKey, + inner: RsaPrivateKey, hash: PhantomData, } - impl From for SigningKey - where - H: RsaHashIdentifier, - { - fn from(key: RsaPrivateKey) -> Self { - let inner = rsa::pkcs1v15::SigningKey::new_with_hash(key, H::HASH); + impl From for SigningKey { + fn from(inner: RsaPrivateKey) -> Self { Self { inner, - hash: PhantomData::default(), + hash: PhantomData, } } } - impl signature::Signer for SigningKey + impl signature::Signer for SigningKey where - H: Digest, + H: Digest + RsaHashIdentifier, { - fn try_sign(&self, msg: &[u8]) -> Result { + fn try_sign(&self, msg: &[u8]) -> Result { let digest = H::digest(msg); - self.inner.try_sign(&digest) + let padding = PaddingScheme::new_pkcs1v15_sign(Some(H::HASH)); + self.inner + .sign(padding, &digest) + .map_err(signature::Error::from_source) + .map(Signature::new) } } } @@ -109,66 +106,62 @@ pub(crate) mod pss { use digest::{Digest, DynDigest}; use rand::thread_rng; - use rsa::{RsaPrivateKey, RsaPublicKey}; - use signature::RandomizedSigner; + use rsa::{PaddingScheme, PublicKey, RsaPrivateKey, RsaPublicKey}; + + use super::Signature; pub struct VerifyingKey { - inner: rsa::pss::VerifyingKey, + inner: RsaPublicKey, hash: PhantomData, } - impl From for VerifyingKey - where - H: DynDigest + Default + 'static, - { - fn from(key: RsaPublicKey) -> Self { - let inner = rsa::pss::VerifyingKey::new(key, Box::new(H::default())); + impl From for VerifyingKey { + fn from(inner: RsaPublicKey) -> Self { Self { inner, - hash: PhantomData::default(), + hash: PhantomData, } } } - impl signature::Verifier for VerifyingKey + impl signature::Verifier for VerifyingKey where - H: Digest, + H: Digest + DynDigest + 'static, { - fn verify( - &self, - msg: &[u8], - signature: &rsa::pss::Signature, - ) -> Result<(), signature::Error> { + fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), signature::Error> { let digest = H::digest(msg); - self.inner.verify(&digest, signature) + let padding = PaddingScheme::new_pss::(thread_rng()); + self.inner + .verify(padding, &digest, signature.as_ref()) + .map_err(signature::Error::from_source) } } pub struct SigningKey { - inner: rsa::pss::SigningKey, + inner: RsaPrivateKey, hash: PhantomData, } - impl From for SigningKey - where - H: DynDigest + Default + 'static, - { - fn from(key: RsaPrivateKey) -> Self { - let inner = rsa::pss::SigningKey::new(key, Box::new(H::default())); + impl From for SigningKey { + fn from(inner: RsaPrivateKey) -> Self { Self { inner, - hash: PhantomData::default(), + hash: PhantomData, } } } - impl signature::Signer for SigningKey + impl signature::Signer for SigningKey where - H: Digest, + H: Digest + DynDigest + 'static, { - fn try_sign(&self, msg: &[u8]) -> Result { + fn try_sign(&self, msg: &[u8]) -> Result { let digest = H::digest(msg); - self.inner.try_sign_with_rng(thread_rng(), &digest) + let padding = PaddingScheme::new_pss::(thread_rng()); + self.inner + .sign(padding, &digest) + .map_err(signature::Error::from_source) + .map(Signature::new) } } } diff --git a/crates/jose/src/jwa/signature.rs b/crates/jose/src/jwa/signature.rs index ea77b0c5..4a97a24b 100644 --- a/crates/jose/src/jwa/signature.rs +++ b/crates/jose/src/jwa/signature.rs @@ -34,6 +34,10 @@ impl signature::Signature for Signature { } impl Signature { + pub fn new(bytes: Vec) -> Self { + Self { bytes } + } + pub fn from_signature(signature: &S) -> Self where S: signature::Signature, diff --git a/crates/jose/src/jwk/private_parameters.rs b/crates/jose/src/jwk/private_parameters.rs index e96f437a..ee0c62aa 100644 --- a/crates/jose/src/jwk/private_parameters.rs +++ b/crates/jose/src/jwk/private_parameters.rs @@ -298,7 +298,11 @@ mod rsa_impls { .map(|i| BigUint::from_bytes_be(i)) .collect(); - RsaPrivateKey::from_components(n, e, d, primes) + let key = RsaPrivateKey::from_components(n, e, d, primes); + + key.validate()?; + + Ok(key) } } } diff --git a/crates/keystore/Cargo.toml b/crates/keystore/Cargo.toml index 43163d51..0fa5be97 100644 --- a/crates/keystore/Cargo.toml +++ b/crates/keystore/Cargo.toml @@ -20,7 +20,7 @@ pem-rfc7468 = { version = "0.6.0", features = ["std"] } pkcs1 = { version = "0.4.0", features = ["std"] } pkcs8 = { version = "0.9.0", features = ["std", "pkcs5", "encryption"] } rand = "0.8.5" -rsa = { git = "https://github.com/RustCrypto/RSA.git", features = ["std", "pem"] } +rsa = { version = "0.7.0-pre", features = ["std", "pem"] } sec1 = { version = "0.3.0", features = ["std"] } spki = { version = "0.6.0", features = ["std"] } thiserror = "1.0.32" diff --git a/crates/keystore/src/lib.rs b/crates/keystore/src/lib.rs index 42b3b395..c075a73a 100644 --- a/crates/keystore/src/lib.rs +++ b/crates/keystore/src/lib.rs @@ -144,7 +144,7 @@ impl PrivateKey { let first_prime = BigUint::from_bytes_be(pkcs1_key.prime1.as_bytes()); let second_prime = BigUint::from_bytes_be(pkcs1_key.prime2.as_bytes()); let primes = vec![first_prime, second_prime]; - let key = rsa::RsaPrivateKey::from_components(n, e, d, primes)?; + let key = rsa::RsaPrivateKey::from_components(n, e, d, primes); Ok(Self::Rsa(Box::new(key))) } diff --git a/crates/keystore/tests/load.rs b/crates/keystore/tests/load.rs index 7bc68cd2..c2fe4696 100644 --- a/crates/keystore/tests/load.rs +++ b/crates/keystore/tests/load.rs @@ -20,22 +20,22 @@ use mas_keystore::PrivateKey; static PASSWORD: &str = "hunter2"; -macro_rules! load_test { +macro_rules! plain_test { ($name:ident, $kind:ident, $path:literal) => { #[test] fn $name() { - let bytes = include_bytes!($path); + let bytes = include_bytes!(concat!("./keys/", $path)); let key = PrivateKey::load(bytes).unwrap(); assert!(matches!(key, PrivateKey::$kind(_)), "wrong key type"); } }; } -macro_rules! load_encrypted_test { +macro_rules! enc_test { ($name:ident, $kind:ident, $path:literal) => { #[test] fn $name() { - let bytes = include_bytes!($path); + let bytes = include_bytes!(concat!("./keys/", $path)); let key = PrivateKey::load_encrypted(bytes, PASSWORD).unwrap(); assert!(matches!(key, PrivateKey::$kind(_)), "wrong key type"); @@ -54,60 +54,28 @@ macro_rules! load_encrypted_test { }; } -load_test!(load_rsa_pkcs1_pem, Rsa, "./keys/rsa.pkcs1.pem"); -load_test!(load_rsa_pkcs1_der, Rsa, "./keys/rsa.pkcs1.der"); -load_test!(load_rsa_pkcs8_pem, Rsa, "./keys/rsa.pkcs8.pem"); -load_test!(load_rsa_pkcs8_der, Rsa, "./keys/rsa.pkcs8.der"); -load_test!(load_ec_p256_sec1_pem, EcP256, "./keys/ec-p256.sec1.pem"); -load_test!(load_ec_p256_sec1_der, EcP256, "./keys/ec-p256.sec1.der"); -load_test!(load_ec_p256_pkcs8_pem, EcP256, "./keys/ec-p256.pkcs8.pem"); -load_test!(load_ec_p256_pkcs8_der, EcP256, "./keys/ec-p256.pkcs8.der"); -load_test!(load_ec_p384_sec1_pem, EcP384, "./keys/ec-p384.sec1.pem"); -load_test!(load_ec_p384_sec1_der, EcP384, "./keys/ec-p384.sec1.der"); -load_test!(load_ec_p384_pkcs8_pem, EcP384, "./keys/ec-p384.pkcs8.pem"); -load_test!(load_ec_p384_pkcs8_der, EcP384, "./keys/ec-p384.pkcs8.der"); -load_test!(load_ec_k256_sec1_pem, EcK256, "./keys/ec-k256.sec1.pem"); -load_test!(load_ec_k256_sec1_der, EcK256, "./keys/ec-k256.sec1.der"); -load_test!(load_ec_k256_pkcs8_pem, EcK256, "./keys/ec-k256.pkcs8.pem"); -load_test!(load_ec_k256_pkcs8_der, EcK256, "./keys/ec-k256.pkcs8.der"); +plain_test!(plain_rsa_pkcs1_pem, Rsa, "rsa.pkcs1.pem"); +plain_test!(plain_rsa_pkcs1_der, Rsa, "rsa.pkcs1.der"); +plain_test!(plain_rsa_pkcs8_pem, Rsa, "rsa.pkcs8.pem"); +plain_test!(plain_rsa_pkcs8_der, Rsa, "rsa.pkcs8.der"); +plain_test!(plain_ec_p256_sec1_pem, EcP256, "ec-p256.sec1.pem"); +plain_test!(plain_ec_p256_sec1_der, EcP256, "ec-p256.sec1.der"); +plain_test!(plain_ec_p256_pkcs8_pem, EcP256, "ec-p256.pkcs8.pem"); +plain_test!(plain_ec_p256_pkcs8_der, EcP256, "ec-p256.pkcs8.der"); +plain_test!(plain_ec_p384_sec1_pem, EcP384, "ec-p384.sec1.pem"); +plain_test!(plain_ec_p384_sec1_der, EcP384, "ec-p384.sec1.der"); +plain_test!(plain_ec_p384_pkcs8_pem, EcP384, "ec-p384.pkcs8.pem"); +plain_test!(plain_ec_p384_pkcs8_der, EcP384, "ec-p384.pkcs8.der"); +plain_test!(plain_ec_k256_sec1_pem, EcK256, "ec-k256.sec1.pem"); +plain_test!(plain_ec_k256_sec1_der, EcK256, "ec-k256.sec1.der"); +plain_test!(plain_ec_k256_pkcs8_pem, EcK256, "ec-k256.pkcs8.pem"); +plain_test!(plain_ec_k256_pkcs8_der, EcK256, "ec-k256.pkcs8.der"); -load_encrypted_test!( - load_encrypted_rsa_pkcs8_pem, - Rsa, - "./keys/rsa.pkcs8.encrypted.pem" -); -load_encrypted_test!( - load_encrypted_rsa_pkcs8_der, - Rsa, - "./keys/rsa.pkcs8.encrypted.der" -); -load_encrypted_test!( - load_encrypted_ec_p256_pkcs8_pem, - EcP256, - "./keys/ec-p256.pkcs8.encrypted.pem" -); -load_encrypted_test!( - load_encrypted_ec_p256_pkcs8_der, - EcP256, - "./keys/ec-p256.pkcs8.encrypted.der" -); -load_encrypted_test!( - load_encrypted_ec_p384_pkcs8_pem, - EcP384, - "./keys/ec-p384.pkcs8.encrypted.pem" -); -load_encrypted_test!( - load_encrypted_ec_p384_pkcs8_der, - EcP384, - "./keys/ec-p384.pkcs8.encrypted.der" -); -load_encrypted_test!( - load_encrypted_ec_k256_pkcs8_pem, - EcK256, - "./keys/ec-k256.pkcs8.encrypted.pem" -); -load_encrypted_test!( - load_encrypted_ec_k256_pkcs8_der, - EcK256, - "./keys/ec-k256.pkcs8.encrypted.der" -); +enc_test!(enc_rsa_pkcs8_pem, Rsa, "rsa.pkcs8.encrypted.pem"); +enc_test!(enc_rsa_pkcs8_der, Rsa, "rsa.pkcs8.encrypted.der"); +enc_test!(enc_ec_p256_pkcs8_pem, EcP256, "ec-p256.pkcs8.encrypted.pem"); +enc_test!(enc_ec_p256_pkcs8_der, EcP256, "ec-p256.pkcs8.encrypted.der"); +enc_test!(enc_ec_p384_pkcs8_pem, EcP384, "ec-p384.pkcs8.encrypted.pem"); +enc_test!(enc_ec_p384_pkcs8_der, EcP384, "ec-p384.pkcs8.encrypted.der"); +enc_test!(enc_ec_k256_pkcs8_pem, EcK256, "ec-k256.pkcs8.encrypted.pem"); +enc_test!(enc_ec_k256_pkcs8_der, EcK256, "ec-k256.pkcs8.encrypted.der");