From be40f881b82b365bc97159557d67883696ad60fb Mon Sep 17 00:00:00 2001 From: arckoor <33837362+arckoor@users.noreply.github.com> Date: Wed, 18 Mar 2026 00:45:20 +0100 Subject: [PATCH] Make Algorithm enum non_exhaustive, allow thumbprint computation to fail --- src/algorithms.rs | 1 + src/crypto/aws_lc/mod.rs | 4 ++-- src/crypto/mod.rs | 2 +- src/crypto/rust_crypto/mod.rs | 6 +++--- src/jwk.rs | 10 ++++++---- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/algorithms.rs b/src/algorithms.rs index edb1d3ab..2d28bebb 100644 --- a/src/algorithms.rs +++ b/src/algorithms.rs @@ -39,6 +39,7 @@ impl AlgorithmFamily { /// The algorithms supported for signing/verifying JWTs #[allow(clippy::upper_case_acronyms)] #[derive(Debug, Default, PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize)] +#[non_exhaustive] pub enum Algorithm { /// HMAC using SHA-256 #[default] diff --git a/src/crypto/aws_lc/mod.rs b/src/crypto/aws_lc/mod.rs index 76f8a2c3..8787887f 100644 --- a/src/crypto/aws_lc/mod.rs +++ b/src/crypto/aws_lc/mod.rs @@ -48,13 +48,13 @@ fn extract_ec_public_key_coordinates( Ok((curve, x.to_vec(), y.to_vec())) } -fn compute_digest(data: &[u8], hash_function: ThumbprintHash) -> Vec { +fn compute_digest(data: &[u8], hash_function: ThumbprintHash) -> errors::Result> { let algorithm = match hash_function { ThumbprintHash::SHA256 => &digest::SHA256, ThumbprintHash::SHA384 => &digest::SHA384, ThumbprintHash::SHA512 => &digest::SHA512, }; - digest::digest(algorithm, data).as_ref().to_vec() + Ok(digest::digest(algorithm, data).as_ref().to_vec()) } fn new_signer(algorithm: &Algorithm, key: &EncodingKey) -> Result, Error> { diff --git a/src/crypto/mod.rs b/src/crypto/mod.rs index 2be728b1..488f217d 100644 --- a/src/crypto/mod.rs +++ b/src/crypto/mod.rs @@ -144,7 +144,7 @@ pub struct JwkUtils { pub extract_ec_public_key_coordinates: fn(&[u8], Algorithm) -> Result<(EllipticCurve, Vec, Vec)>, /// Given some data and a name of a hash function, compute hash_function(data) - pub compute_digest: fn(&[u8], ThumbprintHash) -> Vec, + pub compute_digest: fn(&[u8], ThumbprintHash) -> Result>, } impl JwkUtils { diff --git a/src/crypto/rust_crypto/mod.rs b/src/crypto/rust_crypto/mod.rs index cd0c9bdc..cdb31c60 100644 --- a/src/crypto/rust_crypto/mod.rs +++ b/src/crypto/rust_crypto/mod.rs @@ -55,12 +55,12 @@ fn extract_ec_public_key_coordinates( } } -fn compute_digest(data: &[u8], hash_function: ThumbprintHash) -> Vec { - match hash_function { +fn compute_digest(data: &[u8], hash_function: ThumbprintHash) -> errors::Result> { + Ok(match hash_function { ThumbprintHash::SHA256 => Sha256::digest(data).to_vec(), ThumbprintHash::SHA384 => Sha384::digest(data).to_vec(), ThumbprintHash::SHA512 => Sha512::digest(data).to_vec(), - } + }) } fn new_signer(algorithm: &Algorithm, key: &EncodingKey) -> Result, Error> { diff --git a/src/jwk.rs b/src/jwk.rs index a6ab15cc..4fa0247f 100644 --- a/src/jwk.rs +++ b/src/jwk.rs @@ -496,7 +496,7 @@ impl Jwk { /// Compute the thumbprint of the JWK. /// /// Per [RFC-7638](https://datatracker.ietf.org/doc/html/rfc7638) - pub fn thumbprint(&self, hash_function: ThumbprintHash) -> String { + pub fn thumbprint(&self, hash_function: ThumbprintHash) -> crate::errors::Result { let pre = match &self.algorithm { AlgorithmParameters::EllipticCurve(a) => match a.curve { EllipticCurve::P256 | EllipticCurve::P384 | EllipticCurve::P521 => { @@ -540,10 +540,10 @@ impl Jwk { }, }; - b64_encode((CryptoProvider::get_default().jwk_utils.compute_digest)( + Ok(b64_encode((CryptoProvider::get_default().jwk_utils.compute_digest)( pre.as_bytes(), hash_function, - )) + )?)) } } @@ -624,7 +624,9 @@ mod tests { e: "AQAB".to_string(), }), } - .thumbprint(ThumbprintHash::SHA256); + .thumbprint(ThumbprintHash::SHA256) + .unwrap(); + assert_eq!(tp.as_str(), "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs"); } }