Skip to content
Open
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
23 changes: 15 additions & 8 deletions src/crypto/aws_lc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use aws_lc_rs::{

use crate::{
Algorithm, DecodingKey, EncodingKey,
crypto::{CryptoProvider, JwkUtils, JwtSigner, JwtVerifier},
crypto::{CryptoProvider, JwtSigner, JwtVerifier},
errors::{self, Error, ErrorKind},
jwk::{EllipticCurve, ThumbprintHash},
};
Expand All @@ -18,15 +18,23 @@ mod eddsa;
mod hmac;
mod rsa;

fn extract_rsa_public_key_components(key_content: &[u8]) -> errors::Result<(Vec<u8>, Vec<u8>)> {
fn rsa_components_from_private_key(key_content: &[u8]) -> errors::Result<(Vec<u8>, Vec<u8>)> {
let key_pair = aws_sig::RsaKeyPair::from_der(key_content)
.map_err(|e| ErrorKind::InvalidRsaKey(e.to_string()))?;
let public = key_pair.public_key();
let components = aws_sig::RsaPublicKeyComponents::<Vec<u8>>::from(public);
Ok((components.n, components.e))
}

fn extract_ec_public_key_coordinates(
fn rsa_components_from_public_key(key_content: &[u8]) -> errors::Result<(Vec<u8>, Vec<u8>)> {
let public = aws_lc_rs::rsa::PublicKey::from_der(key_content)
.map_err(|e| ErrorKind::InvalidRsaKey(e.to_string()))?;

let components = aws_sig::RsaPublicKeyComponents::<Vec<u8>>::from(&public);
Ok((components.n, components.e))
}

fn ec_components_from_private_key(
key_content: &[u8],
alg: Algorithm,
) -> errors::Result<(EllipticCurve, Vec<u8>, Vec<u8>)> {
Expand Down Expand Up @@ -102,9 +110,8 @@ fn new_verifier(
pub static DEFAULT_PROVIDER: CryptoProvider = CryptoProvider {
signer_factory: new_signer,
verifier_factory: new_verifier,
jwk_utils: JwkUtils {
extract_rsa_public_key_components,
extract_ec_public_key_coordinates,
compute_digest,
},
rsa_pub_components_from_private_key: rsa_components_from_private_key,
rsa_pub_components_from_public_key: rsa_components_from_public_key,
ec_pub_components_from_private_key: ec_components_from_private_key,
compute_digest,
};
81 changes: 43 additions & 38 deletions src/crypto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@
//! [`CryptoProvider`]: crate::crypto::CryptoProvider

use crate::algorithms::Algorithm;
use crate::errors::Result;
use crate::errors::{self, ErrorKind, Result};
use crate::jwk::{EllipticCurve, ThumbprintHash};
use crate::{DecodingKey, EncodingKey};

const NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR: &'static str = r###"
Could not automatically determine the process-level CryptoProvider from jsonwebtoken crate features, or your CryptoProvider does not support JWKs.
Call CryptoProvider::install_default() before this point to select a provider manually, or make sure exactly one of the 'rust_crypto' and 'aws_lc_rs' features is enabled.
See the documentation of the CryptoProvider type for more information.
"###;
/// `aws_lc_rs` based CryptoProvider.
#[cfg(feature = "aws_lc_rs")]
pub mod aws_lc;
Expand Down Expand Up @@ -85,8 +90,19 @@ pub struct CryptoProvider {
pub signer_factory: fn(&Algorithm, &EncodingKey) -> Result<Box<dyn JwtSigner>>,
/// A function that produces a [`JwtVerifier`] for a given [`Algorithm`]
pub verifier_factory: fn(&Algorithm, &DecodingKey) -> Result<Box<dyn JwtVerifier>>,
/// Struct with utility functions for JWK processing.
pub jwk_utils: JwkUtils,
/// Given a DER encoded private key, extract the RSA public key components (n, e)
#[allow(clippy::type_complexity)]
pub rsa_pub_components_from_private_key: fn(&[u8]) -> Result<(Vec<u8>, Vec<u8>)>,
/// Given a DER encoded public key, extract the RSA public key components (n, e)
#[allow(clippy::type_complexity)]
pub rsa_pub_components_from_public_key: fn(&[u8]) -> Result<(Vec<u8>, Vec<u8>)>,
/// Given a DER encoded private key and an algorithm, extract the associated curve
/// and the EC public key components (x, y)
#[allow(clippy::type_complexity)]
pub ec_pub_components_from_private_key:
fn(&[u8], Algorithm) -> Result<(EllipticCurve, Vec<u8>, Vec<u8>)>,
/// Given some data and a name of a hash function, compute hash_function(data)
pub compute_digest: fn(&[u8], ThumbprintHash) -> Vec<u8>,
}

impl CryptoProvider {
Expand Down Expand Up @@ -123,49 +139,38 @@ See the documentation of the CryptoProvider type for more information.
static INSTANCE: CryptoProvider = CryptoProvider {
signer_factory: |_, _| panic!("{}", NOT_INSTALLED_ERROR),
verifier_factory: |_, _| panic!("{}", NOT_INSTALLED_ERROR),
jwk_utils: JwkUtils::new_unimplemented(),
rsa_pub_components_from_private_key: |_| {
panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
},
rsa_pub_components_from_public_key: |_| {
panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
},
ec_pub_components_from_private_key: |_, _| {
panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
},
compute_digest: |_, _| panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR),
};

&INSTANCE
}
}
}

/// Holds utility functions required for JWK processing.
/// Use the [`JwkUtils::new_unimplemented`] function to initialize all values to dummies.
#[derive(Clone, Debug)]
pub struct JwkUtils {
/// Given a DER encoded private key, extract the RSA public key components (n, e)
#[allow(clippy::type_complexity)]
pub extract_rsa_public_key_components: fn(&[u8]) -> Result<(Vec<u8>, Vec<u8>)>,
/// Given a DER encoded private key and an algorithm, extract the associated curve
/// and the EC public key components (x, y)
#[allow(clippy::type_complexity)]
pub extract_ec_public_key_coordinates:
fn(&[u8], Algorithm) -> Result<(EllipticCurve, Vec<u8>, Vec<u8>)>,
/// Given some data and a name of a hash function, compute hash_function(data)
pub compute_digest: fn(&[u8], ThumbprintHash) -> Vec<u8>,
}

impl JwkUtils {
/// Initialises all values to dummies.
/// Will lead to a panic when JWKs are required, so only use it if you don't want to support JWKs.
pub const fn new_unimplemented() -> Self {
const NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR: &str = r###"
Could not automatically determine the process-level CryptoProvider from jsonwebtoken crate features, or your CryptoProvider does not support JWKs.
Call CryptoProvider::install_default() before this point to select a provider manually, or make sure exactly one of the 'rust_crypto' and 'aws_lc_rs' features is enabled.
See the documentation of the CryptoProvider type for more information.
"###;
Self {
extract_rsa_public_key_components: |_| {
panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
},
extract_ec_public_key_coordinates: |_, _| {
panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
},
compute_digest: |_, _| panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR),
}
pub(crate) fn ec_components_from_public_key(
pub_bytes: &[u8],
) -> errors::Result<(EllipticCurve, Vec<u8>, Vec<u8>)> {
let (curve, pub_elem_bytes) = match pub_bytes.len() {
65 => (EllipticCurve::P256, 32),
97 => (EllipticCurve::P384, 48),
_ => return Err(ErrorKind::InvalidEcdsaKey.into()),
};

if pub_bytes[0] != 4 {
return Err(ErrorKind::InvalidEcdsaKey.into());
}

let (x, y) = pub_bytes[1..].split_at(pub_elem_bytes);
Ok((curve, x.to_vec(), y.to_vec()))
}

mod static_default {
Expand Down
27 changes: 18 additions & 9 deletions src/crypto/rust_crypto/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use ::rsa::{RsaPrivateKey, pkcs1::DecodeRsaPrivateKey, traits::PublicKeyParts};
use ::rsa::{
RsaPrivateKey, RsaPublicKey,
pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey},
traits::PublicKeyParts,
};
use p256::{ecdsa::SigningKey as P256SigningKey, pkcs8::DecodePrivateKey};
use p384::ecdsa::SigningKey as P384SigningKey;
use sha2::{Digest, Sha256, Sha384, Sha512};

use crate::{
Algorithm, DecodingKey, EncodingKey,
crypto::{CryptoProvider, JwkUtils, JwtSigner, JwtVerifier},
crypto::{CryptoProvider, JwtSigner, JwtVerifier},
errors::{self, Error, ErrorKind},
jwk::{EllipticCurve, ThumbprintHash},
};
Expand All @@ -15,14 +19,20 @@ mod eddsa;
mod hmac;
mod rsa;

fn extract_rsa_public_key_components(key_content: &[u8]) -> errors::Result<(Vec<u8>, Vec<u8>)> {
fn rsa_components_from_private_key(key_content: &[u8]) -> errors::Result<(Vec<u8>, Vec<u8>)> {
let private_key = RsaPrivateKey::from_pkcs1_der(key_content)
.map_err(|e| ErrorKind::InvalidRsaKey(e.to_string()))?;
let public_key = private_key.to_public_key();
Ok((public_key.n().to_bytes_be(), public_key.e().to_bytes_be()))
}

fn extract_ec_public_key_coordinates(
fn rsa_components_from_public_key(key_content: &[u8]) -> errors::Result<(Vec<u8>, Vec<u8>)> {
let public_key = RsaPublicKey::from_pkcs1_der(key_content)
.map_err(|e| ErrorKind::InvalidRsaKey(e.to_string()))?;
Ok((public_key.n().to_bytes_be(), public_key.e().to_bytes_be()))
}

fn ec_components_from_private_key(
key_content: &[u8],
alg: Algorithm,
) -> errors::Result<(EllipticCurve, Vec<u8>, Vec<u8>)> {
Expand Down Expand Up @@ -108,9 +118,8 @@ fn new_verifier(
pub static DEFAULT_PROVIDER: CryptoProvider = CryptoProvider {
signer_factory: new_signer,
verifier_factory: new_verifier,
jwk_utils: JwkUtils {
extract_rsa_public_key_components,
extract_ec_public_key_coordinates,
compute_digest,
},
rsa_pub_components_from_private_key: rsa_components_from_private_key,
rsa_pub_components_from_public_key: rsa_components_from_public_key,
ec_pub_components_from_private_key: ec_components_from_private_key,
compute_digest,
};
Loading
Loading