jsonwebtoken/crypto/
mod.rs1use crate::algorithms::Algorithm;
13use crate::errors::Result;
14use crate::jwk::{EllipticCurve, ThumbprintHash};
15use crate::{DecodingKey, EncodingKey};
16
17#[cfg(feature = "aws_lc_rs")]
19pub mod aws_lc;
20
21#[cfg(feature = "rust_crypto")]
23pub mod rust_crypto;
24
25use crate::serialization::{b64_decode, b64_encode};
26use signature::{Signer, Verifier};
27
28pub trait JwtSigner: Signer<Vec<u8>> {
32 fn algorithm(&self) -> Algorithm;
34}
35
36pub trait JwtVerifier: Verifier<Vec<u8>> {
40 fn algorithm(&self) -> Algorithm;
42}
43
44pub fn sign(message: &[u8], key: &EncodingKey, algorithm: Algorithm) -> Result<String> {
49 let provider = (CryptoProvider::get_default().signer_factory)(&algorithm, key)?;
50 Ok(b64_encode(provider.try_sign(message)?))
51}
52
53pub fn verify(
62 signature: &str,
63 message: &[u8],
64 key: &DecodingKey,
65 algorithm: Algorithm,
66) -> Result<bool> {
67 let provider = (CryptoProvider::get_default().verifier_factory)(&algorithm, key)?;
68 Ok(provider.verify(message, &b64_decode(signature)?).is_ok())
69}
70
71#[derive(Clone, Debug)]
83pub struct CryptoProvider {
84 pub signer_factory: fn(&Algorithm, &EncodingKey) -> Result<Box<dyn JwtSigner>>,
86 pub verifier_factory: fn(&Algorithm, &DecodingKey) -> Result<Box<dyn JwtVerifier>>,
88 pub jwk_utils: JwkUtils,
90}
91
92impl CryptoProvider {
93 pub fn install_default(&'static self) -> std::result::Result<(), &'static Self> {
97 static_default::install_default(self)
98 }
99
100 pub(crate) fn get_default() -> &'static Self {
101 static_default::get_default()
102 }
103
104 fn from_crate_features() -> &'static Self {
105 #[cfg(all(feature = "rust_crypto", not(feature = "aws_lc_rs")))]
106 {
107 return &rust_crypto::DEFAULT_PROVIDER;
108 }
109
110 #[cfg(all(feature = "aws_lc_rs", not(feature = "rust_crypto")))]
111 {
112 return &aws_lc::DEFAULT_PROVIDER;
113 }
114
115 #[allow(unreachable_code)]
116 {
117 const NOT_INSTALLED_ERROR: &str = r###"
118Could not automatically determine the process-level CryptoProvider from jsonwebtoken crate features.
119Call 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.
120See the documentation of the CryptoProvider type for more information.
121"###;
122
123 static INSTANCE: CryptoProvider = CryptoProvider {
124 signer_factory: |_, _| panic!("{}", NOT_INSTALLED_ERROR),
125 verifier_factory: |_, _| panic!("{}", NOT_INSTALLED_ERROR),
126 jwk_utils: JwkUtils::new_unimplemented(),
127 };
128
129 &INSTANCE
130 }
131 }
132}
133
134#[derive(Clone, Debug)]
137pub struct JwkUtils {
138 #[allow(clippy::type_complexity)]
140 pub extract_rsa_public_key_components: fn(&[u8]) -> Result<(Vec<u8>, Vec<u8>)>,
141 #[allow(clippy::type_complexity)]
144 pub extract_ec_public_key_coordinates:
145 fn(&[u8], Algorithm) -> Result<(EllipticCurve, Vec<u8>, Vec<u8>)>,
146 pub compute_digest: fn(&[u8], ThumbprintHash) -> Vec<u8>,
148}
149
150impl JwkUtils {
151 pub const fn new_unimplemented() -> Self {
154 const NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR: &str = r###"
155Could not automatically determine the process-level CryptoProvider from jsonwebtoken crate features, or your CryptoProvider does not support JWKs.
156Call 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.
157See the documentation of the CryptoProvider type for more information.
158"###;
159 Self {
160 extract_rsa_public_key_components: |_| {
161 panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
162 },
163 extract_ec_public_key_coordinates: |_, _| {
164 panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
165 },
166 compute_digest: |_, _| panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR),
167 }
168 }
169}
170
171mod static_default {
172 use std::sync::OnceLock;
173
174 use super::CryptoProvider;
175
176 static PROCESS_DEFAULT_PROVIDER: OnceLock<&'static CryptoProvider> = OnceLock::new();
177
178 pub(crate) fn install_default(
179 default_provider: &'static CryptoProvider,
180 ) -> Result<(), &'static CryptoProvider> {
181 PROCESS_DEFAULT_PROVIDER.set(default_provider)
182 }
183
184 pub(crate) fn get_default() -> &'static CryptoProvider {
185 PROCESS_DEFAULT_PROVIDER.get_or_init(CryptoProvider::from_crate_features)
186 }
187}