Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decoupled crypto backends #410

Draft
wants to merge 9 commits into
base: new-backends
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ base64 = "0.22"
pem = { version = "3", optional = true }
simple_asn1 = { version = "0.6", optional = true }

hmac = "0.12.1"
rsa = "0.9.6"
sha2 = { version = "0.10.7", features = ["oid"] }
getrandom = { version = "0.2.10", features = ["js"] }
Expand All @@ -36,6 +35,14 @@ ed25519-dalek = { version = "2.1.1" }
p256 = { version = "0.13.2", features = ["ecdsa"] }
p384 = { version = "0.13.0", features = ["ecdsa"] }
rand_core = "0.6.4"
signature = "2.2.0"

# "rust_crypto" feature
hmac = { version = "0.12.1", optional = true }

# "aws_lc_rs" feature
aws-lc-rs = { version = "1.10.0", optional = true }

[target.'cfg(target_arch = "wasm32")'.dependencies]
js-sys = "0.3"

Expand All @@ -53,8 +60,10 @@ time = { version = "0.3", features = ["wasm-bindgen"] }
criterion = { version = "0.4", default-features = false }

[features]
default = ["use_pem"]
default = ["use_pem", "aws_lc_rs"]
use_pem = ["pem", "simple_asn1", 'p256/pem', 'p384/pem']
rust_crypto = ["hmac"]
aws_lc_rs = ["aws-lc-rs"]

[[bench]]
name = "jwt"
Expand Down
150 changes: 150 additions & 0 deletions src/crypto/aws_lc/hmac.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
//! Implementations of the [`JwtSigner`] and [`JwtVerifier`] traits for the
//! HMAC family of algorithms using [`aws_lc_rs`]

use aws_lc_rs::hmac;
use signature::{Signer, Verifier};

use crate::crypto::utils::{
try_get_hmac_secret_from_decoding_key, try_get_hmac_secret_from_encoding_key,
};
use crate::crypto::{JwtSigner, JwtVerifier};
use crate::errors::Result;
use crate::{Algorithm, DecodingKey, EncodingKey};

pub struct Hs256Signer(hmac::Key);

impl Hs256Signer {
pub(crate) fn new(encoding_key: &EncodingKey) -> Result<Self> {
Ok(Self(hmac::Key::new(
hmac::HMAC_SHA256,
try_get_hmac_secret_from_encoding_key(encoding_key)?,
)))
}
}

impl Signer<Vec<u8>> for Hs256Signer {
fn try_sign(&self, msg: &[u8]) -> std::result::Result<Vec<u8>, signature::Error> {
Ok(hmac::sign(&self.0, msg).as_ref().to_vec())
}
}

impl JwtSigner for Hs256Signer {
fn algorithm(&self) -> Algorithm {
Algorithm::HS256
}
}

pub struct Hs256Verifier(hmac::Key);

impl Hs256Verifier {
pub(crate) fn new(decoding_key: &DecodingKey) -> Result<Self> {
Ok(Self(hmac::Key::new(
hmac::HMAC_SHA256,
try_get_hmac_secret_from_decoding_key(decoding_key)?,
)))
}
}

impl Verifier<Vec<u8>> for Hs256Verifier {
fn verify(&self, msg: &[u8], signature: &Vec<u8>) -> std::result::Result<(), signature::Error> {
hmac::verify(&self.0, msg, &signature).map_err(|err| signature::Error::from_source(err))
}
}

impl JwtVerifier for Hs256Verifier {
fn algorithm(&self) -> Algorithm {
Algorithm::HS256
}
}

pub struct Hs384Signer(hmac::Key);

impl Hs384Signer {
pub(crate) fn new(encoding_key: &EncodingKey) -> Result<Self> {
Ok(Self(hmac::Key::new(
hmac::HMAC_SHA384,
try_get_hmac_secret_from_encoding_key(encoding_key)?,
)))
}
}

impl Signer<Vec<u8>> for Hs384Signer {
fn try_sign(&self, msg: &[u8]) -> std::result::Result<Vec<u8>, signature::Error> {
Ok(hmac::sign(&self.0, msg).as_ref().to_vec())
}
}

impl JwtSigner for Hs384Signer {
fn algorithm(&self) -> Algorithm {
Algorithm::HS384
}
}

pub struct Hs384Verifier(hmac::Key);

impl Hs384Verifier {
pub(crate) fn new(decoding_key: &DecodingKey) -> Result<Self> {
Ok(Self(hmac::Key::new(
hmac::HMAC_SHA384,
try_get_hmac_secret_from_decoding_key(decoding_key)?,
)))
}
}

impl Verifier<Vec<u8>> for Hs384Verifier {
fn verify(&self, msg: &[u8], signature: &Vec<u8>) -> std::result::Result<(), signature::Error> {
hmac::verify(&self.0, msg, &signature).map_err(|err| signature::Error::from_source(err))
}
}

impl JwtVerifier for Hs384Verifier {
fn algorithm(&self) -> Algorithm {
Algorithm::HS384
}
}

pub struct Hs512Signer(hmac::Key);

impl Hs512Signer {
pub(crate) fn new(encoding_key: &EncodingKey) -> Result<Self> {
Ok(Self(hmac::Key::new(
hmac::HMAC_SHA512,
try_get_hmac_secret_from_encoding_key(encoding_key)?,
)))
}
}

impl Signer<Vec<u8>> for Hs512Signer {
fn try_sign(&self, msg: &[u8]) -> std::result::Result<Vec<u8>, signature::Error> {
Ok(hmac::sign(&self.0, msg).as_ref().to_vec())
}
}

impl JwtSigner for Hs512Signer {
fn algorithm(&self) -> Algorithm {
Algorithm::HS512
}
}

pub struct Hs512Verifier(hmac::Key);

impl Hs512Verifier {
pub(crate) fn new(decoding_key: &DecodingKey) -> Result<Self> {
Ok(Self(hmac::Key::new(
hmac::HMAC_SHA512,
try_get_hmac_secret_from_decoding_key(decoding_key)?,
)))
}
}

impl Verifier<Vec<u8>> for Hs512Verifier {
fn verify(&self, msg: &[u8], signature: &Vec<u8>) -> std::result::Result<(), signature::Error> {
hmac::verify(&self.0, msg, &signature).map_err(|err| signature::Error::from_source(err))
}
}

impl JwtVerifier for Hs512Verifier {
fn algorithm(&self) -> Algorithm {
Algorithm::HS512
}
}
2 changes: 2 additions & 0 deletions src/crypto/aws_lc/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub(crate) mod hmac;
pub(crate) mod rsa;
200 changes: 200 additions & 0 deletions src/crypto/aws_lc/rsa.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
//! Implementations of the [`JwtSigner`] and [`JwtVerifier`] traits for the
//! RSA family of algorithms using [`aws_lc_rs`]

use aws_lc_rs::{rand, signature as crypto_sig};
use signature::{Signer, Verifier};

use crate::algorithms::AlgorithmFamily;
use crate::crypto::{JwtSigner, JwtVerifier};
use crate::decoding::DecodingKeyKind;
use crate::errors::{new_error, ErrorKind, Result};
use crate::{Algorithm, DecodingKey, EncodingKey};

/// Try to sign the `message` using an `RSA` `algorithm`.
fn try_sign_rsa(
algorithm: &'static dyn crypto_sig::RsaEncoding,
encoding_key: &EncodingKey,
msg: &[u8],
) -> std::result::Result<Vec<u8>, signature::Error> {
let key_pair = crypto_sig::RsaKeyPair::from_der(encoding_key.inner())
.map_err(|err| signature::Error::from_source(err))?;

let mut signature = vec![0; key_pair.public_modulus_len()];
let rng = rand::SystemRandom::new();
key_pair
.sign(algorithm, &rng, msg, &mut signature)
.map_err(|err| signature::Error::from_source(err))?;

Ok(signature)
}

/// Return a `aws_lc_rs` RSA public key from a [`DecodingKey`]
///
/// # Errors
///
/// - If `decoding_key` is not from the RSA family.
fn verify_rsa(
algorithm: &'static crypto_sig::RsaParameters,
decoding_key: &DecodingKey,
msg: &[u8],
signature: &[u8],
) -> std::result::Result<(), signature::Error> {
match &decoding_key.kind {
DecodingKeyKind::SecretOrDer(bytes) => {
let public_key = crypto_sig::UnparsedPublicKey::new(algorithm, bytes);
public_key.verify(msg, signature).map_err(|err| signature::Error::from_source(err))?;
}
DecodingKeyKind::RsaModulusExponent { n, e } => {
let public_key = crypto_sig::RsaPublicKeyComponents { n, e };
public_key
.verify(algorithm, msg, &signature)
.map_err(|err| signature::Error::from_source(err))?;
}
};

Ok(())
}

pub struct Rsa256Signer(EncodingKey);

impl Rsa256Signer {
pub(crate) fn new(encoding_key: &EncodingKey) -> Result<Self> {
if encoding_key.family != AlgorithmFamily::Rsa {
return Err(new_error(ErrorKind::InvalidKeyFormat));
}

Ok(Self(encoding_key.clone()))
}
}

impl Signer<Vec<u8>> for Rsa256Signer {
fn try_sign(&self, msg: &[u8]) -> std::result::Result<Vec<u8>, signature::Error> {
try_sign_rsa(&crypto_sig::RSA_PKCS1_SHA256, &self.0, msg)
}
}

impl JwtSigner for Rsa256Signer {
fn algorithm(&self) -> Algorithm {
Algorithm::RS256
}
}

pub struct Rsa256Verifier(DecodingKey);

impl Rsa256Verifier {
pub(crate) fn new(decoding_key: &DecodingKey) -> Result<Self> {
if decoding_key.family != AlgorithmFamily::Rsa {
return Err(new_error(ErrorKind::InvalidKeyFormat));
}

Ok(Self(decoding_key.clone()))
}
}

impl Verifier<Vec<u8>> for Rsa256Verifier {
fn verify(&self, msg: &[u8], signature: &Vec<u8>) -> std::result::Result<(), signature::Error> {
verify_rsa(&crypto_sig::RSA_PKCS1_2048_8192_SHA256, &self.0, msg, signature)
}
}

impl JwtVerifier for Rsa256Verifier {
fn algorithm(&self) -> Algorithm {
Algorithm::RS256
}
}

pub struct Rsa384Signer(EncodingKey);

impl Rsa384Signer {
pub(crate) fn new(encoding_key: &EncodingKey) -> Result<Self> {
if encoding_key.family != AlgorithmFamily::Rsa {
return Err(new_error(ErrorKind::InvalidKeyFormat));
}

Ok(Self(encoding_key.clone()))
}
}

impl Signer<Vec<u8>> for Rsa384Signer {
fn try_sign(&self, msg: &[u8]) -> std::result::Result<Vec<u8>, signature::Error> {
try_sign_rsa(&crypto_sig::RSA_PKCS1_SHA384, &self.0, msg)
}
}

impl JwtSigner for Rsa384Signer {
fn algorithm(&self) -> Algorithm {
Algorithm::RS384
}
}

pub struct Rsa384Verifier(DecodingKey);

impl Rsa384Verifier {
pub(crate) fn new(decoding_key: &DecodingKey) -> Result<Self> {
if decoding_key.family != AlgorithmFamily::Rsa {
return Err(new_error(ErrorKind::InvalidKeyFormat));
}

Ok(Self(decoding_key.clone()))
}
}

impl Verifier<Vec<u8>> for Rsa384Verifier {
fn verify(&self, msg: &[u8], signature: &Vec<u8>) -> std::result::Result<(), signature::Error> {
verify_rsa(&crypto_sig::RSA_PKCS1_2048_8192_SHA384, &self.0, msg, signature)
}
}

impl JwtVerifier for Rsa384Verifier {
fn algorithm(&self) -> Algorithm {
Algorithm::RS384
}
}

pub struct Rsa512Signer(EncodingKey);

impl Rsa512Signer {
pub(crate) fn new(encoding_key: &EncodingKey) -> Result<Self> {
if encoding_key.family != AlgorithmFamily::Rsa {
return Err(new_error(ErrorKind::InvalidKeyFormat));
}

Ok(Self(encoding_key.clone()))
}
}

impl Signer<Vec<u8>> for Rsa512Signer {
fn try_sign(&self, msg: &[u8]) -> std::result::Result<Vec<u8>, signature::Error> {
try_sign_rsa(&crypto_sig::RSA_PKCS1_SHA512, &self.0, msg)
}
}

impl JwtSigner for Rsa512Signer {
fn algorithm(&self) -> Algorithm {
Algorithm::RS512
}
}

pub struct Rsa512Verifier(DecodingKey);

impl Rsa512Verifier {
pub(crate) fn new(decoding_key: &DecodingKey) -> Result<Self> {
if decoding_key.family != AlgorithmFamily::Rsa {
return Err(new_error(ErrorKind::InvalidKeyFormat));
}

Ok(Self(decoding_key.clone()))
}
}

impl Verifier<Vec<u8>> for Rsa512Verifier {
fn verify(&self, msg: &[u8], signature: &Vec<u8>) -> std::result::Result<(), signature::Error> {
verify_rsa(&crypto_sig::RSA_PKCS1_2048_8192_SHA512, &self.0, msg, signature)
}
}

impl JwtVerifier for Rsa512Verifier {
fn algorithm(&self) -> Algorithm {
Algorithm::RS512
}
}
Loading
Loading