|
10 | 10 | //! [`CryptoProvider`]: crate::crypto::CryptoProvider |
11 | 11 |
|
12 | 12 | use crate::algorithms::Algorithm; |
13 | | -use crate::errors::Result; |
| 13 | +use crate::errors::{self, ErrorKind, Result}; |
14 | 14 | use crate::jwk::{EllipticCurve, ThumbprintHash}; |
15 | 15 | use crate::{DecodingKey, EncodingKey}; |
16 | 16 |
|
| 17 | +const NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR: &'static str = r###" |
| 18 | +Could not automatically determine the process-level CryptoProvider from jsonwebtoken crate features, or your CryptoProvider does not support JWKs. |
| 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 | +"###; |
17 | 22 | /// `aws_lc_rs` based CryptoProvider. |
18 | 23 | #[cfg(feature = "aws_lc_rs")] |
19 | 24 | pub mod aws_lc; |
@@ -85,8 +90,13 @@ pub struct CryptoProvider { |
85 | 90 | pub signer_factory: fn(&Algorithm, &EncodingKey) -> Result<Box<dyn JwtSigner>>, |
86 | 91 | /// A function that produces a [`JwtVerifier`] for a given [`Algorithm`] |
87 | 92 | pub verifier_factory: fn(&Algorithm, &DecodingKey) -> Result<Box<dyn JwtVerifier>>, |
88 | | - /// Struct with utility functions for JWK processing. |
89 | | - pub jwk_utils: JwkUtils, |
| 93 | + /// Functions to extract RSA public key components from private and public keys |
| 94 | + pub rsa_public_components: RsaPublicComponents, |
| 95 | + /// Functions to extract EC public key components from private and public keys |
| 96 | + pub ec_public_components: EcPublicComponents, |
| 97 | + |
| 98 | + /// Given some data and a name of a hash function, compute hash_function(data) |
| 99 | + pub compute_digest: fn(&[u8], ThumbprintHash) -> Vec<u8>, |
90 | 100 | } |
91 | 101 |
|
92 | 102 | impl CryptoProvider { |
@@ -123,51 +133,81 @@ See the documentation of the CryptoProvider type for more information. |
123 | 133 | static INSTANCE: CryptoProvider = CryptoProvider { |
124 | 134 | signer_factory: |_, _| panic!("{}", NOT_INSTALLED_ERROR), |
125 | 135 | verifier_factory: |_, _| panic!("{}", NOT_INSTALLED_ERROR), |
126 | | - jwk_utils: JwkUtils::new_unimplemented(), |
| 136 | + rsa_public_components: RsaPublicComponents::new_unimplemented(), |
| 137 | + ec_public_components: EcPublicComponents::new_unimplemented(), |
| 138 | + compute_digest: |_, _| panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR), |
127 | 139 | }; |
128 | 140 |
|
129 | 141 | &INSTANCE |
130 | 142 | } |
131 | 143 | } |
132 | 144 | } |
133 | 145 |
|
134 | | -/// Holds utility functions required for JWK processing. |
135 | | -/// Use the [`JwkUtils::new_unimplemented`] function to initialize all values to dummies. |
| 146 | +/// Holds utility functions to extract RSA public key components from private and public keys |
| 147 | +/// Use the [`RsaPublicComponents::new_unimplemented`] function to initialize all values to dummies. |
136 | 148 | #[derive(Clone, Debug)] |
137 | | -pub struct JwkUtils { |
| 149 | +pub struct RsaPublicComponents { |
138 | 150 | /// Given a DER encoded private key, extract the RSA public key components (n, e) |
139 | 151 | #[allow(clippy::type_complexity)] |
140 | | - pub extract_rsa_public_key_components: fn(&[u8]) -> Result<(Vec<u8>, Vec<u8>)>, |
| 152 | + pub from_private_key: fn(&[u8]) -> Result<(Vec<u8>, Vec<u8>)>, |
| 153 | + /// Given a DER encoded public key, extract the RSA public key components (n, e) |
| 154 | + #[allow(clippy::type_complexity)] |
| 155 | + pub from_public_key: fn(&[u8]) -> Result<(Vec<u8>, Vec<u8>)>, |
| 156 | +} |
| 157 | + |
| 158 | +impl RsaPublicComponents { |
| 159 | + /// Creates an instance filled with dummy functions that always panic |
| 160 | + pub const fn new_unimplemented() -> Self { |
| 161 | + Self { |
| 162 | + from_private_key: |_| panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR), |
| 163 | + |
| 164 | + from_public_key: |_| panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR), |
| 165 | + } |
| 166 | + } |
| 167 | +} |
| 168 | + |
| 169 | +/// Holds utility functions to extract EC public key components from private and public keys |
| 170 | +/// Use the [`EcPublicComponents::new_unimplemented`] function to initialize all values to dummies. |
| 171 | +#[derive(Clone, Debug)] |
| 172 | +pub struct EcPublicComponents { |
141 | 173 | /// Given a DER encoded private key and an algorithm, extract the associated curve |
142 | 174 | /// and the EC public key components (x, y) |
143 | 175 | #[allow(clippy::type_complexity)] |
144 | | - pub extract_ec_public_key_coordinates: |
145 | | - fn(&[u8], Algorithm) -> Result<(EllipticCurve, Vec<u8>, Vec<u8>)>, |
146 | | - /// Given some data and a name of a hash function, compute hash_function(data) |
147 | | - pub compute_digest: fn(&[u8], ThumbprintHash) -> Vec<u8>, |
| 176 | + pub from_private_key: fn(&[u8], Algorithm) -> Result<(EllipticCurve, Vec<u8>, Vec<u8>)>, |
| 177 | + /// Given a DER encoded public key and an algorithm, extract the associated curve |
| 178 | + /// and the EC public key components (x, y) |
| 179 | + #[allow(clippy::type_complexity)] |
| 180 | + pub from_public_key: fn(&[u8]) -> Result<(EllipticCurve, Vec<u8>, Vec<u8>)>, |
148 | 181 | } |
149 | 182 |
|
150 | | -impl JwkUtils { |
151 | | - /// Initialises all values to dummies. |
152 | | - /// Will lead to a panic when JWKs are required, so only use it if you don't want to support JWKs. |
| 183 | +impl EcPublicComponents { |
| 184 | + /// Creates a instance filled with dummy functions that always panic |
153 | 185 | pub const fn new_unimplemented() -> Self { |
154 | | - const NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR: &str = r###" |
155 | | -Could not automatically determine the process-level CryptoProvider from jsonwebtoken crate features, or your CryptoProvider does not support JWKs. |
156 | | -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. |
157 | | -See the documentation of the CryptoProvider type for more information. |
158 | | -"###; |
159 | 186 | 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), |
| 187 | + from_private_key: |_, _| panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR), |
| 188 | + |
| 189 | + from_public_key: |_| panic!("{}", NOT_INSTALLED_OR_UNIMPLEMENTED_ERROR), |
167 | 190 | } |
168 | 191 | } |
169 | 192 | } |
170 | 193 |
|
| 194 | +pub(crate) fn ec_components_from_public_key( |
| 195 | + pub_bytes: &[u8], |
| 196 | +) -> errors::Result<(EllipticCurve, Vec<u8>, Vec<u8>)> { |
| 197 | + let (curve, pub_elem_bytes) = match pub_bytes.len() { |
| 198 | + 65 => (EllipticCurve::P256, 32), |
| 199 | + 97 => (EllipticCurve::P384, 48), |
| 200 | + _ => return Err(ErrorKind::InvalidEcdsaKey.into()), |
| 201 | + }; |
| 202 | + |
| 203 | + if pub_bytes[0] != 4 { |
| 204 | + return Err(ErrorKind::InvalidEcdsaKey.into()); |
| 205 | + } |
| 206 | + |
| 207 | + let (x, y) = pub_bytes[1..].split_at(pub_elem_bytes); |
| 208 | + Ok((curve, x.to_vec(), y.to_vec())) |
| 209 | +} |
| 210 | + |
171 | 211 | mod static_default { |
172 | 212 | use std::sync::OnceLock; |
173 | 213 |
|
|
0 commit comments