Skip to content

Commit

Permalink
feat(crypto): Add RSA family
Browse files Browse the repository at this point in the history
  • Loading branch information
sidrubs committed Oct 16, 2024
1 parent 4225e1f commit 78e84c1
Show file tree
Hide file tree
Showing 11 changed files with 412 additions and 150 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ time = { version = "0.3", features = ["wasm-bindgen"] }
criterion = { version = "0.4", default-features = false }

[features]
default = ["use_pem", "rust_crypto"]
default = ["use_pem", "aws_lc_rs"]
use_pem = ["pem", "simple_asn1", 'p256/pem', 'p384/pem']
rust_crypto = ["hmac"]
aws_lc_rs = ["aws-lc-rs"]
Expand Down
95 changes: 70 additions & 25 deletions src/crypto/aws_lc/hmac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,101 +4,146 @@
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, HmacSecret};
use crate::{Algorithm, DecodingKey, EncodingKey};

pub struct Hs256(hmac::Key);
pub struct Hs256Signer(hmac::Key);

impl Hs256 {
pub(crate) fn new(secret: HmacSecret) -> Result<Self> {
Ok(Self(hmac::Key::new(hmac::HMAC_SHA256, &secret)))
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 Hs256 {
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 Hs256 {
impl JwtSigner for Hs256Signer {
fn algorithm(&self) -> Algorithm {
Algorithm::HS256
}
}

impl Verifier<Vec<u8>> for 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 Hs256 {
impl JwtVerifier for Hs256Verifier {
fn algorithm(&self) -> Algorithm {
Algorithm::HS256
}
}

pub struct Hs384(hmac::Key);
pub struct Hs384Signer(hmac::Key);

impl Hs384 {
pub(crate) fn new(secret: HmacSecret) -> Result<Self> {
Ok(Self(hmac::Key::new(hmac::HMAC_SHA384, &secret)))
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 Hs384 {
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 Hs384 {
impl JwtSigner for Hs384Signer {
fn algorithm(&self) -> Algorithm {
Algorithm::HS384
}
}

impl Verifier<Vec<u8>> for 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 Hs384 {
impl JwtVerifier for Hs384Verifier {
fn algorithm(&self) -> Algorithm {
Algorithm::HS384
}
}

pub struct Hs512(hmac::Key);
pub struct Hs512Signer(hmac::Key);

impl Hs512 {
pub(crate) fn new(secret: HmacSecret) -> Result<Self> {
Ok(Self(hmac::Key::new(hmac::HMAC_SHA512, &secret)))
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 Hs512 {
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 Hs512 {
impl JwtSigner for Hs512Signer {
fn algorithm(&self) -> Algorithm {
Algorithm::HS512
}
}

impl Verifier<Vec<u8>> for 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 Hs512 {
impl JwtVerifier for Hs512Verifier {
fn algorithm(&self) -> Algorithm {
Algorithm::HS512
}
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/aws_lc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pub(crate) mod hmac;
// pub(crate) mod rsa;
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
}
}
1 change: 1 addition & 0 deletions src/crypto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::algorithms::Algorithm;
pub(crate) mod aws_lc;
#[cfg(feature = "rust_crypto")]
pub(crate) mod rust_crypto;
pub(crate) mod utils;

use signature::{Signer, Verifier};

Expand Down
Loading

0 comments on commit 78e84c1

Please sign in to comment.