Skip to content

Commit 5edada7

Browse files
committed
Refactoring to remove Arc/Option and delay panic to actual use of the provider
1 parent f273be8 commit 5edada7

7 files changed

Lines changed: 97 additions & 72 deletions

File tree

src/crypto/aws_lc/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ fn new_verifier(
9999
}
100100

101101
/// The default [`CryptoProvider`] backed by [`aws_lc_rs`].
102-
pub const DEFAULT_PROVIDER: CryptoProvider = CryptoProvider {
102+
pub static DEFAULT_PROVIDER: CryptoProvider = CryptoProvider {
103103
signer_factory: new_signer,
104104
verifier_factory: new_verifier,
105105
jwk_utils: JwkUtils {

src/crypto/mod.rs

Lines changed: 82 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@
99
//! [`Verifier`]: signature::Verifier
1010
//! [`CryptoProvider`]: crate::crypto::CryptoProvider
1111
12-
use std::sync::Arc;
13-
1412
use crate::algorithms::Algorithm;
1513
use crate::errors::Result;
1614
use crate::jwk::{EllipticCurve, ThumbprintHash};
1715
use crate::{DecodingKey, EncodingKey};
1816

17+
const NOT_INSTALLED_ERROR: &str = r###"
18+
Could not automatically determine the process-level CryptoProvider from jsonwebtoken crate features.
19+
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.
20+
See the documentation of the CryptoProvider type for more information.
21+
"###;
22+
1923
/// `aws_lc_rs` based CryptoProvider.
2024
#[cfg(feature = "aws_lc_rs")]
2125
pub mod aws_lc;
@@ -48,9 +52,7 @@ pub trait JwtVerifier: Verifier<Vec<u8>> {
4852
///
4953
/// If you just want to encode a JWT, use `encode` instead.
5054
pub fn sign(message: &[u8], key: &EncodingKey, algorithm: Algorithm) -> Result<String> {
51-
let provider = (CryptoProvider::get_default_or_install_from_crate_features().signer_factory)(
52-
&algorithm, key,
53-
)?;
55+
let provider = (CryptoProvider::get_default().signer_factory)(&algorithm, key)?;
5456
Ok(b64_encode(provider.sign(message)))
5557
}
5658

@@ -68,9 +70,7 @@ pub fn verify(
6870
key: &DecodingKey,
6971
algorithm: Algorithm,
7072
) -> Result<bool> {
71-
let provider = (CryptoProvider::get_default_or_install_from_crate_features().verifier_factory)(
72-
&algorithm, key,
73-
)?;
73+
let provider = (CryptoProvider::get_default().verifier_factory)(&algorithm, key)?;
7474
Ok(provider.verify(message, &b64_decode(signature)?).is_ok())
7575
}
7676

@@ -96,50 +96,56 @@ pub struct CryptoProvider {
9696
}
9797

9898
impl CryptoProvider {
99-
/// Set this `CryptoProvider` as the default for this process.
99+
/// Retrieve automatically selected instance
100100
///
101-
/// This can be called successfully at most once in any process execution.
102-
pub fn install_default(self) -> std::result::Result<(), Arc<Self>> {
103-
static_default::install_default(self)
104-
}
105-
106-
/// Get the default `CryptoProvider` for this process.
101+
/// If `rust_crypto` or `aws_lc_rs` are enabled then it returns selected provider
107102
///
108-
/// This will be `None` if no default has been set yet.
109-
pub fn get_default() -> Option<&'static Arc<Self>> {
110-
static_default::get_default()
111-
}
112-
113-
/// Get the default if it has been set yet, or determine one from the crate features if possible.
114-
pub(crate) fn get_default_or_install_from_crate_features() -> &'static Arc<Self> {
115-
if let Some(provider) = Self::get_default() {
116-
return provider;
117-
}
118-
119-
let provider = Self::from_crate_features()
120-
.expect(r###"
121-
Could not automatically determine the process-level CryptoProvider from jsonwebtoken crate features.
122-
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.
123-
See the documentation of the CryptoProvider type for more information.
124-
"###);
125-
let _ = provider.install_default();
126-
Self::get_default().unwrap()
127-
}
128-
129-
/// Determine a `CryptoProvider` based on crate features.
130-
pub fn from_crate_features() -> Option<Self> {
103+
/// Otherwise returns default unimplemented instance
104+
pub const fn new_from_features() -> &'static Self {
131105
#[cfg(all(feature = "rust_crypto", not(feature = "aws_lc_rs")))]
132106
{
133-
return Some(rust_crypto::DEFAULT_PROVIDER);
107+
return &rust_crypto::DEFAULT_PROVIDER;
134108
}
135109

136110
#[cfg(all(feature = "aws_lc_rs", not(feature = "rust_crypto")))]
137111
{
138-
return Some(aws_lc::DEFAULT_PROVIDER);
112+
return &aws_lc::DEFAULT_PROVIDER;
139113
}
140114

141-
#[allow(unreachable_code)]
142-
None
115+
#[allow(unused)]
116+
Self::new_unimplemented()
117+
}
118+
119+
/// Returns unimplemented instance
120+
pub const fn new_unimplemented() -> &'static Self {
121+
fn signer_factory(_: &Algorithm, _: &EncodingKey) -> Result<Box<dyn JwtSigner>> {
122+
panic!("{}", NOT_INSTALLED_ERROR);
123+
}
124+
fn verifier_factory(_: &Algorithm, _: &DecodingKey) -> Result<Box<dyn JwtVerifier>> {
125+
panic!("{}", NOT_INSTALLED_ERROR);
126+
}
127+
128+
static INSTANCE: CryptoProvider = CryptoProvider {
129+
signer_factory,
130+
verifier_factory,
131+
jwk_utils: JwkUtils::new_unimplemented(),
132+
};
133+
134+
&INSTANCE
135+
}
136+
137+
/// Set this `CryptoProvider` as the default for this process.
138+
///
139+
/// This can be called successfully at most once in any process execution.
140+
pub fn install_default(&'static self) -> std::result::Result<(), &'static Self> {
141+
static_default::install_default(self)
142+
}
143+
144+
/// Get the default `CryptoProvider` for this process.
145+
///
146+
/// This will be `None` if no default has been set yet.
147+
pub fn get_default() -> &'static Self {
148+
static_default::get_default()
143149
}
144150
}
145151

@@ -159,30 +165,52 @@ pub struct JwkUtils {
159165
pub compute_digest: fn(&[u8], ThumbprintHash) -> Vec<u8>,
160166
}
161167

162-
impl Default for JwkUtils {
163-
fn default() -> Self {
168+
impl JwkUtils {
169+
///Creates unimplemented instance
170+
pub const fn new_unimplemented() -> Self {
171+
fn extract_rsa_public_key_components(_: &[u8]) -> Result<(Vec<u8>, Vec<u8>)> {
172+
panic!("{}", NOT_INSTALLED_ERROR);
173+
}
174+
175+
fn extract_ec_public_key_coordinates(
176+
_: &[u8],
177+
_: Algorithm,
178+
) -> Result<(EllipticCurve, Vec<u8>, Vec<u8>)> {
179+
panic!("{}", NOT_INSTALLED_ERROR);
180+
}
181+
182+
fn compute_digest(_: &[u8], _: ThumbprintHash) -> Vec<u8> {
183+
panic!("{}", NOT_INSTALLED_ERROR);
184+
}
185+
164186
Self {
165-
extract_rsa_public_key_components: |_| unimplemented!(),
166-
extract_ec_public_key_coordinates: |_, _| unimplemented!(),
167-
compute_digest: |_, _| unimplemented!(),
187+
extract_rsa_public_key_components,
188+
extract_ec_public_key_coordinates,
189+
compute_digest,
168190
}
169191
}
170192
}
171193

194+
impl Default for JwkUtils {
195+
fn default() -> Self {
196+
Self::new_unimplemented()
197+
}
198+
}
199+
172200
mod static_default {
173-
use std::sync::{Arc, OnceLock};
201+
use std::sync::OnceLock;
174202

175203
use super::CryptoProvider;
176204

177-
static PROCESS_DEFAULT_PROVIDER: OnceLock<Arc<CryptoProvider>> = OnceLock::new();
205+
static PROCESS_DEFAULT_PROVIDER: OnceLock<&'static CryptoProvider> = OnceLock::new();
178206

179207
pub(crate) fn install_default(
180-
default_provider: CryptoProvider,
181-
) -> Result<(), Arc<CryptoProvider>> {
182-
PROCESS_DEFAULT_PROVIDER.set(Arc::new(default_provider))
208+
default_provider: &'static CryptoProvider,
209+
) -> Result<(), &'static CryptoProvider> {
210+
PROCESS_DEFAULT_PROVIDER.set(default_provider)
183211
}
184212

185-
pub(crate) fn get_default() -> Option<&'static Arc<CryptoProvider>> {
186-
PROCESS_DEFAULT_PROVIDER.get()
213+
pub(crate) fn get_default() -> &'static CryptoProvider {
214+
PROCESS_DEFAULT_PROVIDER.get_or_init(CryptoProvider::new_from_features)
187215
}
188216
}

src/crypto/rust_crypto/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ fn new_verifier(
105105
}
106106

107107
/// The default [`CryptoProvider`] backed by [`rust_crypto`](https://github.com/RustCrypto).
108-
pub const DEFAULT_PROVIDER: CryptoProvider = CryptoProvider {
108+
pub static DEFAULT_PROVIDER: CryptoProvider = CryptoProvider {
109109
signer_factory: new_signer,
110110
verifier_factory: new_verifier,
111111
jwk_utils: JwkUtils {

src/decoding.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,7 @@ pub fn decode<T: DeserializeOwned>(
282282
return Err(new_error(ErrorKind::InvalidAlgorithm));
283283
}
284284

285-
let verifying_provider = (CryptoProvider::get_default_or_install_from_crate_features()
286-
.verifier_factory)(&header.alg, key)?;
285+
let verifying_provider = (CryptoProvider::get_default().verifier_factory)(&header.alg, key)?;
287286

288287
let (header, claims) = verify_signature(token, validation, verifying_provider)?;
289288

src/encoding.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,7 @@ pub fn encode<T: Serialize>(header: &Header, claims: &T, key: &EncodingKey) -> R
158158
return Err(new_error(ErrorKind::InvalidAlgorithm));
159159
}
160160

161-
let signing_provider = (CryptoProvider::get_default_or_install_from_crate_features()
162-
.signer_factory)(&header.alg, key)?;
161+
let signing_provider = (CryptoProvider::get_default().signer_factory)(&header.alg, key)?;
163162

164163
if signing_provider.algorithm() != header.alg {
165164
return Err(new_error(ErrorKind::InvalidAlgorithm));

src/jwk.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ impl Jwk {
462462
})
463463
}
464464
crate::algorithms::AlgorithmFamily::Rsa => {
465-
let (n, e) = (CryptoProvider::get_default_or_install_from_crate_features()
465+
let (n, e) = (CryptoProvider::get_default()
466466
.jwk_utils
467467
.extract_rsa_public_key_components)(
468468
key.inner()
@@ -474,12 +474,11 @@ impl Jwk {
474474
})
475475
}
476476
crate::algorithms::AlgorithmFamily::Ec => {
477-
let (curve, x, y) =
478-
(CryptoProvider::get_default_or_install_from_crate_features()
479-
.jwk_utils
480-
.extract_ec_public_key_coordinates)(
481-
key.inner(), alg
482-
)?;
477+
let (curve, x, y) = (CryptoProvider::get_default()
478+
.jwk_utils
479+
.extract_ec_public_key_coordinates)(
480+
key.inner(), alg
481+
)?;
483482
AlgorithmParameters::EllipticCurve(EllipticCurveKeyParameters {
484483
key_type: EllipticCurveKeyType::EC,
485484
curve,
@@ -541,9 +540,10 @@ impl Jwk {
541540
},
542541
};
543542

544-
b64_encode((CryptoProvider::get_default_or_install_from_crate_features()
545-
.jwk_utils
546-
.compute_digest)(pre.as_bytes(), hash_function))
543+
b64_encode((CryptoProvider::get_default().jwk_utils.compute_digest)(
544+
pre.as_bytes(),
545+
hash_function,
546+
))
547547
}
548548
}
549549

src/jws.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ pub fn decode<T: DeserializeOwned>(
6767
let header = Header::from_encoded(&jws.protected)?;
6868
let message = [jws.protected.as_str(), jws.payload.as_str()].join(".");
6969

70-
let verifying_provider = (CryptoProvider::get_default_or_install_from_crate_features()
71-
.verifier_factory)(&header.alg, key)?;
70+
let verifying_provider = (CryptoProvider::get_default().verifier_factory)(&header.alg, key)?;
7271
verify_signature_body(
7372
message.as_bytes(),
7473
jws.signature.as_bytes(),

0 commit comments

Comments
 (0)