diff --git a/src/crypto/ecdsa.rs b/src/crypto/ecdsa.rs index eb7aa05..ba2f0ff 100644 --- a/src/crypto/ecdsa.rs +++ b/src/crypto/ecdsa.rs @@ -1,17 +1,27 @@ use ring::{rand, signature}; +use crate::algorithms::Algorithm; use crate::errors::Result; use crate::pem_decoder::PemEncodedKey; use crate::serialization::b64_encode; -use crate::algorithms::Algorithm; - /// Only used internally when validating EC, to map from our enum to the Ring EcdsaVerificationAlgorithm structs. -pub(crate) fn alg_to_ec_verification(alg: Algorithm) -> &'static signature::EcdsaVerificationAlgorithm { +pub(crate) fn alg_to_ec_verification( + alg: Algorithm, +) -> &'static signature::EcdsaVerificationAlgorithm { match alg { Algorithm::ES256 => &signature::ECDSA_P256_SHA256_FIXED, Algorithm::ES384 => &signature::ECDSA_P384_SHA384_FIXED, - _ => unreachable!("Tried to get EC signature for a non-EC algorithm"), + _ => unreachable!("Tried to get EC alg for a non-EC algorithm"), + } +} + +/// Only used internally when signing EC, to map from our enum to the Ring EcdsaVerificationAlgorithm structs. +pub(crate) fn alg_to_ec_signing(alg: Algorithm) -> &'static signature::EcdsaSigningAlgorithm { + match alg { + Algorithm::ES256 => &signature::ECDSA_P256_SHA256_FIXED_SIGNING, + Algorithm::ES384 => &signature::ECDSA_P384_SHA384_FIXED_SIGNING, + _ => unreachable!("Tried to get EC alg for a non-EC algorithm"), } } diff --git a/src/crypto/mod.rs b/src/crypto/mod.rs index 4c1132d..6667ee4 100644 --- a/src/crypto/mod.rs +++ b/src/crypto/mod.rs @@ -27,19 +27,33 @@ pub fn sign(message: &str, key: &[u8], algorithm: Algorithm) -> Result { Algorithm::HS384 => sign_hmac(hmac::HMAC_SHA384, key, message), Algorithm::HS512 => sign_hmac(hmac::HMAC_SHA512, key, message), - Algorithm::ES256 => ecdsa::sign(&signature::ECDSA_P256_SHA256_FIXED_SIGNING, key, message), - Algorithm::ES384 => ecdsa::sign(&signature::ECDSA_P384_SHA384_FIXED_SIGNING, key, message), + Algorithm::ES256 | Algorithm::ES384 => { + ecdsa::sign(ecdsa::alg_to_ec_signing(algorithm), key, message) + } - Algorithm::RS256 => rsa::sign(&signature::RSA_PKCS1_SHA256, key, message), - Algorithm::RS384 => rsa::sign(&signature::RSA_PKCS1_SHA384, key, message), - Algorithm::RS512 => rsa::sign(&signature::RSA_PKCS1_SHA512, key, message), - - Algorithm::PS256 => rsa::sign(&signature::RSA_PSS_SHA256, key, message), - Algorithm::PS384 => rsa::sign(&signature::RSA_PSS_SHA384, key, message), - Algorithm::PS512 => rsa::sign(&signature::RSA_PSS_SHA512, key, message), + Algorithm::RS256 + | Algorithm::RS384 + | Algorithm::RS512 + | Algorithm::PS256 + | Algorithm::PS384 + | Algorithm::PS512 => rsa::sign(rsa::alg_to_rsa_signing(algorithm), key, message), } } +/// See Ring docs for more details +fn verify_ring( + alg: &'static dyn signature::VerificationAlgorithm, + signature: &str, + message: &str, + key: &[u8], +) -> Result { + let signature_bytes = b64_decode(signature)?; + let public_key = signature::UnparsedPublicKey::new(alg, key); + let res = public_key.verify(message.as_bytes(), &signature_bytes); + + Ok(res.is_ok()) +} + /// Compares the signature given with a re-computed signature for HMAC or using the public key /// for RSA/EC. /// @@ -59,31 +73,30 @@ pub fn verify(signature: &str, message: &str, key: &[u8], algorithm: Algorithm) } Algorithm::ES256 | Algorithm::ES384 => { let pem_key = PemEncodedKey::new(key)?; - verify_ring(ecdsa::alg_to_ec_verification(algorithm), signature, message, pem_key.as_ec_public_key()?) + verify_ring( + ecdsa::alg_to_ec_verification(algorithm), + signature, + message, + pem_key.as_ec_public_key()?, + ) } - // only RSAs left - _ => { + Algorithm::RS256 + | Algorithm::RS384 + | Algorithm::RS512 + | Algorithm::PS256 + | Algorithm::PS384 + | Algorithm::PS512 => { let pem_key = PemEncodedKey::new(key)?; - verify_ring(rsa::alg_to_rsa_parameters(algorithm), signature, message, pem_key.as_rsa_key()?) - }, + verify_ring( + rsa::alg_to_rsa_parameters(algorithm), + signature, + message, + pem_key.as_rsa_key()?, + ) + } } } - -/// See Ring docs for more details -fn verify_ring( - alg: &'static dyn signature::VerificationAlgorithm, - signature: &str, - message: &str, - key: &[u8], -) -> Result { - let signature_bytes = b64_decode(signature)?; - let public_key = signature::UnparsedPublicKey::new(alg, key); - let res = public_key.verify(message.as_bytes(), &signature_bytes); - - Ok(res.is_ok()) -} - /// Verify the signature given using the (n, e) components of a RSA public key. /// /// `signature` is the signature part of a jwt (text after the second '.') @@ -96,5 +109,5 @@ pub fn verify_rsa_components( alg: Algorithm, ) -> Result { let signature_bytes = b64_decode(signature)?; - rsa::verify_from_components(&signature_bytes, message, components, alg) + rsa::verify_from_components(rsa::alg_to_rsa_parameters(alg), &signature_bytes, message, components) } diff --git a/src/crypto/rsa.rs b/src/crypto/rsa.rs index a7241a2..95e946b 100644 --- a/src/crypto/rsa.rs +++ b/src/crypto/rsa.rs @@ -1,11 +1,10 @@ use ring::{rand, signature}; use simple_asn1::BigUint; +use crate::algorithms::Algorithm; use crate::errors::{ErrorKind, Result}; use crate::pem_decoder::PemEncodedKey; -use crate::serialization::{b64_encode, b64_decode}; -use crate::algorithms::Algorithm; - +use crate::serialization::{b64_decode, b64_encode}; /// Only used internally when validating RSA, to map from our enum to the Ring param structs. pub(crate) fn alg_to_rsa_parameters(alg: Algorithm) -> &'static signature::RsaParameters { @@ -20,6 +19,18 @@ pub(crate) fn alg_to_rsa_parameters(alg: Algorithm) -> &'static signature::RsaPa } } +/// Only used internally when signing with RSA, to map from our enum to the Ring signing structs. +pub(crate) fn alg_to_rsa_signing(alg: Algorithm) -> &'static dyn signature::RsaEncoding { + match alg { + Algorithm::RS256 => &signature::RSA_PKCS1_SHA256, + Algorithm::RS384 => &signature::RSA_PKCS1_SHA384, + Algorithm::RS512 => &signature::RSA_PKCS1_SHA512, + Algorithm::PS256 => &signature::RSA_PSS_SHA256, + Algorithm::PS384 => &signature::RSA_PSS_SHA384, + Algorithm::PS512 => &signature::RSA_PSS_SHA512, + _ => unreachable!("Tried to get RSA signature for a non-rsa algorithm"), + } +} /// The actual RSA signing + encoding /// Taken from Ring doc https://briansmith.org/rustdoc/ring/signature/index.html @@ -42,13 +53,14 @@ pub(crate) fn sign( } pub(crate) fn verify_from_components( + alg: &'static signature::RsaParameters, signature_bytes: &[u8], message: &str, components: (&str, &str), - alg: Algorithm) -> Result { +) -> Result { let n = BigUint::from_bytes_be(&b64_decode(components.0)?).to_bytes_be(); let e = BigUint::from_bytes_be(&b64_decode(components.1)?).to_bytes_be(); let pubkey = signature::RsaPublicKeyComponents { n, e }; - let res = pubkey.verify(alg_to_rsa_parameters(alg), message.as_ref(), &signature_bytes); + let res = pubkey.verify(alg, message.as_ref(), &signature_bytes); Ok(res.is_ok()) } diff --git a/src/decoding.rs b/src/decoding.rs index c2934cc..e79847d 100644 --- a/src/decoding.rs +++ b/src/decoding.rs @@ -118,8 +118,8 @@ pub fn dangerous_unsafe_decode(token: &str) -> Result