From 4aee8bc382aab9f69e0a2b538738b3634cdedf53 Mon Sep 17 00:00:00 2001 From: Charles Lehner Date: Tue, 17 Nov 2020 08:17:40 -0500 Subject: [PATCH] Add sign and verify on bytes (#150) --- src/crypto/ecdsa.rs | 4 ++-- src/crypto/mod.rs | 25 ++++++++++++++++++++----- src/crypto/rsa.rs | 10 ++++------ 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/crypto/ecdsa.rs b/src/crypto/ecdsa.rs index afa0f79..5425a8b 100644 --- a/src/crypto/ecdsa.rs +++ b/src/crypto/ecdsa.rs @@ -29,10 +29,10 @@ pub(crate) fn alg_to_ec_signing(alg: Algorithm) -> &'static signature::EcdsaSign pub fn sign( alg: &'static signature::EcdsaSigningAlgorithm, key: &[u8], - message: &str, + message: &[u8], ) -> Result { let signing_key = signature::EcdsaKeyPair::from_pkcs8(alg, key)?; let rng = rand::SystemRandom::new(); - let out = signing_key.sign(&rng, message.as_bytes())?; + let out = signing_key.sign(&rng, message)?; Ok(b64_encode(out.as_ref())) } diff --git a/src/crypto/mod.rs b/src/crypto/mod.rs index b4c3e91..93432b7 100644 --- a/src/crypto/mod.rs +++ b/src/crypto/mod.rs @@ -13,8 +13,8 @@ pub(crate) mod rsa; /// The actual HS signing + encoding /// Could be in its own file to match RSA/EC but it's 2 lines... -pub(crate) fn sign_hmac(alg: hmac::Algorithm, key: &[u8], message: &str) -> Result { - let digest = hmac::sign(&hmac::Key::new(alg, key), message.as_bytes()); +pub(crate) fn sign_hmac(alg: hmac::Algorithm, key: &[u8], message: &[u8]) -> Result { + let digest = hmac::sign(&hmac::Key::new(alg, key), message); Ok(b64_encode(digest.as_ref())) } @@ -23,6 +23,11 @@ pub(crate) fn sign_hmac(alg: hmac::Algorithm, key: &[u8], message: &str) -> Resu /// /// If you just want to encode a JWT, use `encode` instead. pub fn sign(message: &str, key: &EncodingKey, algorithm: Algorithm) -> Result { + sign_bytes(message.as_bytes(), key, algorithm) +} + +/// Same as sign() but for message as bytes +pub fn sign_bytes(message: &[u8], key: &EncodingKey, algorithm: Algorithm) -> Result { match algorithm { Algorithm::HS256 => sign_hmac(hmac::HMAC_SHA256, key.inner(), message), Algorithm::HS384 => sign_hmac(hmac::HMAC_SHA384, key.inner(), message), @@ -47,12 +52,12 @@ pub fn sign(message: &str, key: &EncodingKey, algorithm: Algorithm) -> Result 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); + let res = public_key.verify(message, &signature_bytes); Ok(res.is_ok()) } @@ -70,11 +75,21 @@ pub fn verify( message: &str, key: &DecodingKey, algorithm: Algorithm, +) -> Result { + Ok(verify_bytes(signature, message.as_bytes(), key, algorithm)?) +} + +/// Same as verify() but for message as bytes +pub fn verify_bytes( + signature: &str, + message: &[u8], + key: &DecodingKey, + algorithm: Algorithm, ) -> Result { match algorithm { Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => { // we just re-sign the message with the key and compare if they are equal - let signed = sign(message, &EncodingKey::from_secret(key.as_bytes()), algorithm)?; + let signed = sign_bytes(message, &EncodingKey::from_secret(key.as_bytes()), algorithm)?; Ok(verify_slices_are_equal(signature.as_ref(), signed.as_ref()).is_ok()) } Algorithm::ES256 | Algorithm::ES384 => verify_ring( diff --git a/src/crypto/rsa.rs b/src/crypto/rsa.rs index 376c13a..df93960 100644 --- a/src/crypto/rsa.rs +++ b/src/crypto/rsa.rs @@ -37,15 +37,13 @@ pub(crate) fn alg_to_rsa_signing(alg: Algorithm) -> &'static dyn signature::RsaE pub(crate) fn sign( alg: &'static dyn signature::RsaEncoding, key: &[u8], - message: &str, + message: &[u8], ) -> Result { let key_pair = signature::RsaKeyPair::from_der(key).map_err(|_| ErrorKind::InvalidRsaKey)?; let mut signature = vec![0; key_pair.public_modulus_len()]; let rng = rand::SystemRandom::new(); - key_pair - .sign(alg, &rng, message.as_bytes(), &mut signature) - .map_err(|_| ErrorKind::InvalidRsaKey)?; + key_pair.sign(alg, &rng, message, &mut signature).map_err(|_| ErrorKind::InvalidRsaKey)?; Ok(b64_encode(&signature)) } @@ -54,13 +52,13 @@ pub(crate) fn sign( pub(crate) fn verify_from_components( alg: &'static signature::RsaParameters, signature: &str, - message: &str, + message: &[u8], components: (&str, &str), ) -> Result { let signature_bytes = b64_decode(signature)?; 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, message.as_ref(), &signature_bytes); + let res = pubkey.verify(alg, message, &signature_bytes); Ok(res.is_ok()) }