jsonwebtoken/crypto/
mod.rs1use crate::algorithms::Algorithm;
13use crate::errors::{ErrorKind, 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 key_utils: KeyUtils,
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 key_utils: KeyUtils::new_unimplemented(),
127 };
128
129 &INSTANCE
130 }
131 }
132}
133
134#[derive(Clone, Debug)]
137pub struct KeyUtils {
138 #[allow(clippy::type_complexity)]
140 pub rsa_pub_components_from_private_key: fn(&[u8]) -> Result<(Vec<u8>, Vec<u8>)>,
141 #[allow(clippy::type_complexity)]
143 pub rsa_pub_components_from_public_key: fn(&[u8]) -> Result<(Vec<u8>, Vec<u8>)>,
144 #[allow(clippy::type_complexity)]
147 pub ec_pub_components_from_private_key:
148 fn(&[u8], Algorithm) -> Result<(EllipticCurve, Vec<u8>, Vec<u8>)>,
149 pub ed_pub_components_from_private_key: fn(&[u8], &EllipticCurve) -> Result<Vec<u8>>,
151 pub compute_digest: fn(&[u8], ThumbprintHash) -> Result<Vec<u8>>,
153}
154
155impl KeyUtils {
156 pub const fn new_unimplemented() -> Self {
159 const NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR: &str = r"
160Could not automatically determine the process-level CryptoProvider from jsonwebtoken crate features, or your CryptoProvider does not support JWKs.
161Call 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.
162See the documentation of the CryptoProvider type for more information.
163";
164 Self {
165 rsa_pub_components_from_private_key: |_| {
166 panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
167 },
168 rsa_pub_components_from_public_key: |_| {
169 panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
170 },
171 ec_pub_components_from_private_key: |_, _| {
172 panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
173 },
174 ed_pub_components_from_private_key: |_, _| {
175 panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR)
176 },
177 compute_digest: |_, _| panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR),
178 }
179 }
180}
181
182pub(crate) fn ec_pub_components_from_public_key(
185 pub_bytes: &[u8],
186) -> Result<(EllipticCurve, Vec<u8>, Vec<u8>)> {
187 let (curve, pub_elem_bytes) = match pub_bytes.len() {
188 65 => (EllipticCurve::P256, 32),
189 97 => (EllipticCurve::P384, 48),
190 _ => return Err(ErrorKind::InvalidEcdsaKey.into()),
191 };
192
193 if pub_bytes[0] != 4 {
194 return Err(ErrorKind::InvalidEcdsaKey.into());
195 }
196
197 let (x, y) = pub_bytes[1..].split_at(pub_elem_bytes);
198 Ok((curve, x.to_vec(), y.to_vec()))
199}
200
201mod static_default {
202 use std::sync::OnceLock;
203
204 use super::CryptoProvider;
205
206 static PROCESS_DEFAULT_PROVIDER: OnceLock<&'static CryptoProvider> = OnceLock::new();
207
208 pub(crate) fn install_default(
209 default_provider: &'static CryptoProvider,
210 ) -> Result<(), &'static CryptoProvider> {
211 PROCESS_DEFAULT_PROVIDER.set(default_provider)
212 }
213
214 pub(crate) fn get_default() -> &'static CryptoProvider {
215 PROCESS_DEFAULT_PROVIDER.get_or_init(CryptoProvider::from_crate_features)
216 }
217}