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
22 changes: 16 additions & 6 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, KeyUtils},
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,11 @@ 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,
key_utils: KeyUtils {
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,
ec_pub_components_from_public_key: crate::crypto::ec_components_from_public_key,
compute_digest,
},
};
51 changes: 41 additions & 10 deletions src/crypto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//! [`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};

Expand Down Expand Up @@ -86,7 +86,7 @@ pub struct CryptoProvider {
/// 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,
pub key_utils: KeyUtils,
}

impl CryptoProvider {
Expand Down Expand Up @@ -123,7 +123,7 @@ 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(),
key_utils: KeyUtils::new_unimplemented(),
};

&INSTANCE
Expand All @@ -132,22 +132,29 @@ See the documentation of the CryptoProvider type for more information.
}

/// Holds utility functions required for JWK processing.
/// Use the [`JwkUtils::new_unimplemented`] function to initialize all values to dummies.
/// Use the [`KeyUtils::new_unimplemented`] function to initialize all values to dummies.
#[derive(Clone, Debug)]
pub struct JwkUtils {
pub struct KeyUtils {
/// 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>)>,
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 extract_ec_public_key_coordinates:
pub ec_pub_components_from_private_key:
fn(&[u8], Algorithm) -> Result<(EllipticCurve, Vec<u8>, Vec<u8>)>,
/// Given bitstring from DER encoded private key, extract the associated curve
/// and the EC public key components (x, y)
#[allow(clippy::type_complexity)]
pub ec_pub_components_from_public_key: fn(&[u8]) -> 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) -> Result<Vec<u8>>,
}

impl JwkUtils {
impl KeyUtils {
/// 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 {
Expand All @@ -157,17 +164,41 @@ Call CryptoProvider::install_default() before this point to select a provider ma
See the documentation of the CryptoProvider type for more information.
"###;
Self {
extract_rsa_public_key_components: |_| {
rsa_pub_components_from_private_key: |_| {
panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
},
extract_ec_public_key_coordinates: |_, _| {
rsa_pub_components_from_public_key: |_| {
panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
},
ec_pub_components_from_private_key: |_, _| {
panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
},
ec_pub_components_from_public_key: |_| {
panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
},
compute_digest: |_, _| panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR),
}
}
}

#[allow(unused)]
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()))
}

Comment on lines +184 to +201
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still can't be part of KeyUtils / the CryptoProvider as a whole, it's completely inaccessible from the outside of the crate. What about just making it pub(crate) and referring to it directly from jwk.rs? Should also be ec_pub_components_...

mod static_default {
use std::sync::OnceLock;

Expand Down
26 changes: 19 additions & 7 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, KeyUtils},
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,11 @@ 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,
key_utils: KeyUtils {
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,
ec_pub_components_from_public_key: crate::crypto::ec_components_from_public_key,
compute_digest,
},
};
Loading
Loading