From 1ab1363233a4d0ab996037dbe15a729eaa1b40e9 Mon Sep 17 00:00:00 2001 From: Jan Cibulka Date: Thu, 7 Nov 2024 15:01:12 +0200 Subject: [PATCH] bump: Merge 'hidekatsu-izuno:master' --- Cargo.toml | 9 ++--- README.md | 2 +- src/jose_header.rs | 10 ++++- src/jwe.rs | 4 +- src/jwe/alg/aesgcmkw.rs | 4 +- src/jwe/alg/pbes2_hmac_aeskw.rs | 15 ++++++- src/jwe/enc/aescbc_hmac.rs | 14 +++++-- src/jwe/enc/aesgcm.rs | 22 +++++------ src/jwe/jwe_header.rs | 13 ++++++ src/jwe/jwe_header_set.rs | 13 ++++++ src/jwk/alg/ec.rs | 31 ++++++++++++--- src/jwk/alg/rsa.rs | 19 ++------- src/jwk/alg/rsapss.rs | 18 +-------- src/jws.rs | 6 +-- src/jws/alg/ecdsa.rs | 17 ++++++-- src/jws/alg/hmac.rs | 17 ++++++-- src/jws/alg/rsassa.rs | 17 ++++++-- src/jws/alg/rsassa_pss.rs | 17 ++++++-- src/jws/jws_header.rs | 13 ++++++ src/jws/jws_header_set.rs | 13 ++++++ src/jwt.rs | 27 +++++++++++-- src/util.rs | 28 ++++--------- src/util/hash_algorithm.rs | 10 ----- src/util/oid.rs | 70 ++++++++++++++++----------------- 24 files changed, 254 insertions(+), 155 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7f9b8f5..e34763c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "josekit" -version = "0.8.5" +version = "0.10.0" description = "JOSE (Javascript Object Signing and Encryption) library for Rust." repository = "https://github.com/hidekatsu-izuno/josekit-rs" readme = "README.md" @@ -17,16 +17,15 @@ default = [] vendored = ["openssl/vendored"] [dependencies] -thiserror = "1" +thiserror = "2" anyhow = "1" -once_cell = "1" regex = "1" serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["preserve_order"] } -base64 = "0.21" +base64 = "0.22" flate2 = "1" -openssl = "0.10.62" time = "0.3" +openssl = { version = "0.10.66" } [dev-dependencies] doc-comment = "0.3.3" diff --git a/README.md b/README.md index 72af0d3..4a0fa12 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ JOSE (Javascript Object Signing and Encryption: JWT, JWS, JWE, JWA, JWK) library ```toml [dependencies] -josekit = "0.8.5" +josekit = "0.10.0" ``` This library depends on OpenSSL 1.1.1 or above DLL. Read more about [Crate openssl](https://docs.rs/openssl/). diff --git a/src/jose_header.rs b/src/jose_header.rs index 4424b43..3b1c74f 100644 --- a/src/jose_header.rs +++ b/src/jose_header.rs @@ -1,8 +1,8 @@ use crate::Value; -use std::fmt::Debug; +use std::{any::Any, fmt::Debug}; -pub trait JoseHeader: Send + Sync + Debug { +pub trait JoseHeader: Any + Send + Sync + Debug { /// Return claim count. fn len(&self) -> usize; @@ -14,6 +14,12 @@ pub trait JoseHeader: Send + Sync + Debug { fn claim(&self, key: &str) -> Option<&Value>; fn box_clone(&self) -> Box; + + fn as_any(&self) -> &dyn Any; + + fn as_any_mut(&mut self) -> &mut dyn Any; + + fn into_any(self: Box) -> Box; } impl Clone for Box { diff --git a/src/jwe.rs b/src/jwe.rs index 1538dfc..db41ad0 100644 --- a/src/jwe.rs +++ b/src/jwe.rs @@ -10,7 +10,7 @@ mod jwe_header; mod jwe_header_set; pub mod zip; -use once_cell::sync::Lazy; +use std::sync::LazyLock; use crate::JoseError; @@ -54,7 +54,7 @@ pub use RsaesJweAlgorithm::RsaOaep256 as RSA_OAEP_256; pub use RsaesJweAlgorithm::RsaOaep384 as RSA_OAEP_384; pub use RsaesJweAlgorithm::RsaOaep512 as RSA_OAEP_512; -static DEFAULT_CONTEXT: Lazy = Lazy::new(|| JweContext::new()); +static DEFAULT_CONTEXT: LazyLock = LazyLock::new(|| JweContext::new()); /// Return a representation of the data that is formatted by compact serialization. /// diff --git a/src/jwe/alg/aesgcmkw.rs b/src/jwe/alg/aesgcmkw.rs index cecc033..f17db5c 100644 --- a/src/jwe/alg/aesgcmkw.rs +++ b/src/jwe/alg/aesgcmkw.rs @@ -240,7 +240,7 @@ impl JweEncrypter for AesgcmkwJweEncrypter { out_header: &mut JweHeader, ) -> Result>, JoseError> { (|| -> anyhow::Result>> { - let iv = util::random_bytes(32); + let iv = util::random_bytes(12); let cipher = self.algorithm.cipher(); let mut tag = [0; 16]; @@ -315,7 +315,7 @@ impl JweDecrypter for AesgcmkwJweDecrypter { None => bail!("A encrypted_key is required."), }; - let iv = match header.claim("iv") { + let iv: Vec = match header.claim("iv") { Some(Value::String(val)) => util::decode_base64_urlsafe_no_pad(val)?, Some(_) => bail!("The iv header claim must be string."), None => bail!("The iv header claim is required."), diff --git a/src/jwe/alg/pbes2_hmac_aeskw.rs b/src/jwe/alg/pbes2_hmac_aeskw.rs index cffd4c3..ff351ad 100644 --- a/src/jwe/alg/pbes2_hmac_aeskw.rs +++ b/src/jwe/alg/pbes2_hmac_aeskw.rs @@ -5,6 +5,7 @@ use std::ops::Deref; use anyhow::bail; use openssl::aes::{self, AesKey}; +use openssl::hash::MessageDigest; use openssl::pkcs5; use crate::jwe::{JweAlgorithm, JweContentEncryption, JweDecrypter, JweEncrypter, JweHeader}; @@ -288,7 +289,12 @@ impl JweEncrypter for Pbes2HmacAeskwJweEncrypter { salt.push(0); salt.extend_from_slice(&p2s); - let md = self.algorithm.hash_algorithm().message_digest(); + let md = match &self.algorithm.hash_algorithm() { + HashAlgorithm::Sha1 => MessageDigest::sha1(), + HashAlgorithm::Sha256 => MessageDigest::sha256(), + HashAlgorithm::Sha384 => MessageDigest::sha384(), + HashAlgorithm::Sha512 => MessageDigest::sha512(), + }; let mut derived_key = vec![0; self.algorithm.derived_key_len()]; pkcs5::pbkdf2_hmac(&self.private_key, &salt, p2c, md, &mut derived_key)?; @@ -398,7 +404,12 @@ impl JweDecrypter for Pbes2HmacAeskwJweDecrypter { salt.push(0); salt.extend_from_slice(&p2s); - let md = self.algorithm.hash_algorithm().message_digest(); + let md = match &self.algorithm.hash_algorithm() { + HashAlgorithm::Sha1 => MessageDigest::sha1(), + HashAlgorithm::Sha256 => MessageDigest::sha256(), + HashAlgorithm::Sha384 => MessageDigest::sha384(), + HashAlgorithm::Sha512 => MessageDigest::sha512(), + }; let mut derived_key = vec![0; self.algorithm.derived_key_len()]; pkcs5::pbkdf2_hmac(&self.private_key, &salt, p2c, md, &mut derived_key)?; diff --git a/src/jwe/enc/aescbc_hmac.rs b/src/jwe/enc/aescbc_hmac.rs index 882501d..5c39743 100644 --- a/src/jwe/enc/aescbc_hmac.rs +++ b/src/jwe/enc/aescbc_hmac.rs @@ -109,8 +109,11 @@ impl JweContentEncryption for AescbcHmacJweEncryption { let mac_key_len = expected_len / 2; let mac_key = &key[0..mac_key_len]; let enc_key = &key[mac_key_len..]; - - let cipher = self.cipher(); + let cipher = match self { + AescbcHmacJweEncryption::A128cbcHs256 => Cipher::aes_128_cbc(), + AescbcHmacJweEncryption::A192cbcHs384 => Cipher::aes_192_cbc(), + AescbcHmacJweEncryption::A256cbcHs512 => Cipher::aes_256_cbc(), + }; let encrypted_message = symm::encrypt(cipher, enc_key, iv, message)?; Ok((encrypted_message, mac_key)) })() @@ -142,8 +145,11 @@ impl JweContentEncryption for AescbcHmacJweEncryption { let mac_key_len = expected_len / 2; let mac_key = &key[0..mac_key_len]; let enc_key = &key[mac_key_len..]; - - let cipher = self.cipher(); + let cipher = match self { + AescbcHmacJweEncryption::A128cbcHs256 => Cipher::aes_128_cbc(), + AescbcHmacJweEncryption::A192cbcHs384 => Cipher::aes_192_cbc(), + AescbcHmacJweEncryption::A256cbcHs512 => Cipher::aes_256_cbc(), + }; let message = symm::decrypt(cipher, enc_key, iv, encrypted_message)?; Ok((message, mac_key)) })() diff --git a/src/jwe/enc/aesgcm.rs b/src/jwe/enc/aesgcm.rs index 50930d9..2b3fff4 100644 --- a/src/jwe/enc/aesgcm.rs +++ b/src/jwe/enc/aesgcm.rs @@ -17,16 +17,6 @@ pub enum AesgcmJweEncryption { A256gcm, } -impl AesgcmJweEncryption { - fn cipher(&self) -> Cipher { - match self { - Self::A128gcm => Cipher::aes_128_gcm(), - Self::A192gcm => Cipher::aes_192_gcm(), - Self::A256gcm => Cipher::aes_256_gcm(), - } - } -} - impl JweContentEncryption for AesgcmJweEncryption { fn name(&self) -> &str { match self { @@ -65,7 +55,11 @@ impl JweContentEncryption for AesgcmJweEncryption { ); } - let cipher = self.cipher(); + let cipher = match self { + AesgcmJweEncryption::A128gcm => Cipher::aes_128_gcm(), + AesgcmJweEncryption::A192gcm => Cipher::aes_192_gcm(), + AesgcmJweEncryption::A256gcm => Cipher::aes_256_gcm(), + }; let mut tag = [0; 16]; let encrypted_message = symm::encrypt_aead(cipher, key, iv, aad, message, &mut tag)?; Ok((encrypted_message, Some(tag.to_vec()))) @@ -96,7 +90,11 @@ impl JweContentEncryption for AesgcmJweEncryption { None => bail!("A tag value is required."), }; - let cipher = self.cipher(); + let cipher = match self { + AesgcmJweEncryption::A128gcm => Cipher::aes_128_gcm(), + AesgcmJweEncryption::A192gcm => Cipher::aes_192_gcm(), + AesgcmJweEncryption::A256gcm => Cipher::aes_256_gcm(), + }; let message = symm::decrypt_aead(cipher, key, iv, aad, encrypted_message, tag)?; Ok(message) })() diff --git a/src/jwe/jwe_header.rs b/src/jwe/jwe_header.rs index 33a5b11..d534321 100644 --- a/src/jwe/jwe_header.rs +++ b/src/jwe/jwe_header.rs @@ -1,3 +1,4 @@ +use std::any::Any; use std::cmp::Eq; use std::convert::Into; use std::fmt::{Debug, Display}; @@ -612,6 +613,18 @@ impl JoseHeader for JweHeader { fn box_clone(&self) -> Box { Box::new(self.clone()) } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } + + fn into_any(self: Box) -> Box { + self + } } impl AsRef> for JweHeader { diff --git a/src/jwe/jwe_header_set.rs b/src/jwe/jwe_header_set.rs index 521af43..d00d80a 100644 --- a/src/jwe/jwe_header_set.rs +++ b/src/jwe/jwe_header_set.rs @@ -1,3 +1,4 @@ +use std::any::Any; use std::fmt::{Debug, Display}; use std::ops::Deref; @@ -672,6 +673,18 @@ impl JoseHeader for JweHeaderSet { fn box_clone(&self) -> Box { Box::new(self.clone()) } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } + + fn into_any(self: Box) -> Box { + self + } } impl Display for JweHeaderSet { diff --git a/src/jwk/alg/ec.rs b/src/jwk/alg/ec.rs index da48c22..910cab6 100644 --- a/src/jwk/alg/ec.rs +++ b/src/jwk/alg/ec.rs @@ -2,7 +2,7 @@ use std::fmt::Display; use std::ops::Deref; use anyhow::bail; -use openssl::bn::{BigNum, BigNumContext}; +use openssl::bn::{BigNum, BigNumContext, BigNumRef}; use openssl::ec::{EcGroup, EcKey}; use openssl::nid::Nid; use openssl::pkey::{PKey, Private}; @@ -106,7 +106,14 @@ impl EcKeyPair { /// Generate EC key pair. pub fn generate(curve: EcCurve) -> Result { (|| -> anyhow::Result { - let ec_group = EcGroup::from_curve_name(curve.nid())?; + let nid = match curve { + EcCurve::P256 => Nid::X9_62_PRIME256V1, + EcCurve::P384 => Nid::SECP384R1, + EcCurve::P521 => Nid::SECP521R1, + EcCurve::Secp256k1 => Nid::SECP256K1, + EcCurve::BP256R1 => Nid::BRAINPOOL_P256R1, + }; + let ec_group = EcGroup::from_curve_name(nid)?; let ec_key = EcKey::generate(&ec_group)?; let private_key = PKey::from_ec_key(ec_key)?; @@ -337,7 +344,7 @@ impl EcKeyPair { .unwrap(); if private { let d = ec_key.private_key(); - let d = util::num_to_vec(&d, self.curve.coordinate_size()); + let d = Self::num_to_vec(&d, self.curve.coordinate_size()); let d = util::encode_base64_urlsafe_nopad(&d); jwk.set_parameter("d", Some(Value::String(d))).unwrap(); @@ -351,10 +358,10 @@ impl EcKeyPair { .affine_coordinates_gfp(ec_key.group(), &mut x, &mut y, &mut ctx) .unwrap(); - let x = util::num_to_vec(&x, self.curve.coordinate_size()); + let x = Self::num_to_vec(&x, self.curve.coordinate_size()); let x = util::encode_base64_urlsafe_nopad(&x); - let y = util::num_to_vec(&y, self.curve.coordinate_size()); + let y = Self::num_to_vec(&y, self.curve.coordinate_size()); let y = util::encode_base64_urlsafe_nopad(&y); jwk.set_parameter("x", Some(Value::String(x))).unwrap(); @@ -494,6 +501,20 @@ impl EcKeyPair { builder.build() } + + fn num_to_vec(num: &BigNumRef, len: usize) -> Vec { + let vec = num.to_vec(); + if vec.len() < len { + let mut tmp = Vec::with_capacity(len); + for _ in 0..(len - vec.len()) { + tmp.push(0); + } + tmp.extend_from_slice(&vec); + tmp + } else { + vec + } + } } impl KeyPair for EcKeyPair { diff --git a/src/jwk/alg/rsa.rs b/src/jwk/alg/rsa.rs index 578d940..d88b1cb 100644 --- a/src/jwk/alg/rsa.rs +++ b/src/jwk/alg/rsa.rs @@ -13,14 +13,13 @@ use crate::{JoseError, Value}; #[derive(Debug, Clone)] pub struct RsaKeyPair { private_key: PKey, - key_len: u32, algorithm: Option, key_id: Option, } impl RsaKeyPair { pub fn key_len(&self) -> u32 { - self.key_len + self.private_key.size().try_into().unwrap() } pub fn set_algorithm(&mut self, value: Option<&str>) { @@ -44,13 +43,12 @@ impl RsaKeyPair { mgf1_hash: HashAlgorithm, salt_len: u8, ) -> RsaPssKeyPair { - RsaPssKeyPair::from_private_key(self.private_key, self.key_len, hash, mgf1_hash, salt_len) + RsaPssKeyPair::from_private_key(self.private_key, hash, mgf1_hash, salt_len) } - pub(crate) fn from_private_key(private_key: PKey, key_len: u32) -> Self { + pub(crate) fn from_private_key(private_key: PKey) -> Self { Self { private_key, - key_len, algorithm: None, key_id: None, } @@ -67,12 +65,10 @@ impl RsaKeyPair { pub fn generate(bits: u32) -> Result { (|| -> anyhow::Result { let rsa = Rsa::generate(bits)?; - let key_len = rsa.size(); let private_key = PKey::from_rsa(rsa)?; Ok(RsaKeyPair { private_key, - key_len, algorithm: None, key_id: None, }) @@ -96,12 +92,9 @@ impl RsaKeyPair { }; let private_key = PKey::private_key_from_der(pkcs8_der)?; - let rsa = private_key.rsa()?; - let key_len = rsa.size(); Ok(Self { private_key, - key_len, algorithm: None, key_id: None, }) @@ -137,12 +130,9 @@ impl RsaKeyPair { }; let private_key = PKey::private_key_from_der(&pkcs8_der)?; - let rsa = private_key.rsa()?; - let key_len = rsa.size(); Ok(Self { private_key, - key_len, algorithm: None, key_id: None, }) @@ -218,14 +208,11 @@ impl RsaKeyPair { let pkcs8 = Self::to_pkcs8(&builder.build(), false); let private_key = PKey::private_key_from_der(&pkcs8)?; - let rsa = private_key.rsa()?; - let key_len = rsa.size(); let algorithm = jwk.algorithm().map(|val| val.to_string()); let key_id = jwk.key_id().map(|val| val.to_string()); Ok(Self { private_key, - key_len, algorithm, key_id, }) diff --git a/src/jwk/alg/rsapss.rs b/src/jwk/alg/rsapss.rs index 187860b..e4c05e4 100644 --- a/src/jwk/alg/rsapss.rs +++ b/src/jwk/alg/rsapss.rs @@ -13,7 +13,6 @@ use crate::{JoseError, Value}; #[derive(Debug, Clone)] pub struct RsaPssKeyPair { private_key: PKey, - key_len: u32, hash: HashAlgorithm, mgf1_hash: HashAlgorithm, salt_len: u8, @@ -23,7 +22,7 @@ pub struct RsaPssKeyPair { impl RsaPssKeyPair { pub fn key_len(&self) -> u32 { - self.key_len + self.private_key.size().try_into().unwrap() } pub fn set_algorithm(&mut self, value: Option<&str>) { @@ -42,19 +41,17 @@ impl RsaPssKeyPair { } pub fn into_rsa_key_pair(self) -> RsaKeyPair { - RsaKeyPair::from_private_key(self.private_key, self.key_len) + RsaKeyPair::from_private_key(self.private_key) } pub(crate) fn from_private_key( private_key: PKey, - key_len: u32, hash: HashAlgorithm, mgf1_hash: HashAlgorithm, salt_len: u8, ) -> Self { Self { private_key, - key_len, hash, mgf1_hash, salt_len, @@ -79,12 +76,10 @@ impl RsaPssKeyPair { ) -> Result { (|| -> anyhow::Result { let rsa = Rsa::generate(bits)?; - let key_len = rsa.size(); let private_key = PKey::from_rsa(rsa)?; Ok(RsaPssKeyPair { private_key, - key_len, hash, mgf1_hash, salt_len, @@ -165,12 +160,9 @@ impl RsaPssKeyPair { }; let private_key = PKey::private_key_from_der(pkcs8_der)?; - let rsa = private_key.rsa()?; - let key_len = rsa.size(); Ok(RsaPssKeyPair { private_key, - key_len, hash, mgf1_hash, salt_len, @@ -258,12 +250,9 @@ impl RsaPssKeyPair { }; let private_key = PKey::private_key_from_der(pkcs8_der)?; - let rsa = private_key.rsa()?; - let key_len = rsa.size(); Ok(RsaPssKeyPair { private_key, - key_len, hash, mgf1_hash, salt_len, @@ -350,14 +339,11 @@ impl RsaPssKeyPair { let pkcs8 = RsaPssKeyPair::to_pkcs8(&builder.build(), false, hash, mgf1_hash, salt_len); let private_key = PKey::private_key_from_der(&pkcs8)?; - let rsa = private_key.rsa()?; - let key_len = rsa.size(); let algorithm = jwk.algorithm().map(|val| val.to_string()); let key_id = jwk.key_id().map(|val| val.to_string()); Ok(Self { private_key, - key_len, hash, mgf1_hash, salt_len, diff --git a/src/jws.rs b/src/jws.rs index 10ecd64..04d2dd0 100644 --- a/src/jws.rs +++ b/src/jws.rs @@ -6,7 +6,7 @@ mod jws_context; mod jws_header; mod jws_header_set; -use once_cell::sync::Lazy; +use std::sync::LazyLock; use crate::JoseError; @@ -42,7 +42,7 @@ pub use EcdsaJwsAlgorithm::BP256R1; use crate::jws::alg::eddsa::EddsaJwsAlgorithm; pub use EddsaJwsAlgorithm::Eddsa as EdDSA; -static DEFAULT_CONTEXT: Lazy = Lazy::new(|| JwsContext::new()); +static DEFAULT_CONTEXT: LazyLock = LazyLock::new(|| JwsContext::new()); /// Return a representation of the data that is formatted by compact serialization. /// @@ -207,11 +207,11 @@ where #[cfg(test)] mod tests { + use std::cell::OnceCell; use std::fs; use std::path::PathBuf; use anyhow::Result; - use once_cell::sync::OnceCell; use crate::jws::{self, EdDSA, JwsHeader, JwsHeaderSet, JwsVerifier, ES256, RS256}; use crate::Value; diff --git a/src/jws/alg/ecdsa.rs b/src/jws/alg/ecdsa.rs index e4ed788..7e793ca 100644 --- a/src/jws/alg/ecdsa.rs +++ b/src/jws/alg/ecdsa.rs @@ -2,6 +2,7 @@ use std::fmt::Display; use std::ops::Deref; use anyhow::bail; +use openssl::hash::MessageDigest; use openssl::pkey::{PKey, Private, Public}; use openssl::sign::{Signer, Verifier}; @@ -351,8 +352,12 @@ impl JwsSigner for EcdsaJwsSigner { fn sign(&self, message: &[u8]) -> Result, JoseError> { (|| -> anyhow::Result> { - let md = self.algorithm.hash_algorithm().message_digest(); - + let md = match &self.algorithm.hash_algorithm() { + HashAlgorithm::Sha1 => MessageDigest::sha1(), + HashAlgorithm::Sha256 => MessageDigest::sha256(), + HashAlgorithm::Sha384 => MessageDigest::sha384(), + HashAlgorithm::Sha512 => MessageDigest::sha512(), + }; let mut signer = Signer::new(md, &self.private_key)?; signer.update(message)?; let der_signature = signer.sign_to_vec()?; @@ -450,8 +455,12 @@ impl JwsVerifier for EcdsaJwsVerifier { der_builder.end(); let der_signature = der_builder.build(); - let md = self.algorithm.hash_algorithm().message_digest(); - + let md = match &self.algorithm.hash_algorithm() { + HashAlgorithm::Sha1 => MessageDigest::sha1(), + HashAlgorithm::Sha256 => MessageDigest::sha256(), + HashAlgorithm::Sha384 => MessageDigest::sha384(), + HashAlgorithm::Sha512 => MessageDigest::sha512(), + }; let mut verifier = Verifier::new(md, &self.public_key)?; verifier.update(message)?; if !verifier.verify(&der_signature)? { diff --git a/src/jws/alg/hmac.rs b/src/jws/alg/hmac.rs index 3ef6e4f..fae739e 100644 --- a/src/jws/alg/hmac.rs +++ b/src/jws/alg/hmac.rs @@ -2,6 +2,7 @@ use std::fmt::Display; use std::ops::Deref; use anyhow::bail; +use openssl::hash::MessageDigest; use openssl::pkey::{PKey, Private}; use openssl::sign::Signer; @@ -269,8 +270,12 @@ impl JwsSigner for HmacJwsSigner { fn sign(&self, message: &[u8]) -> Result, JoseError> { (|| -> anyhow::Result> { - let md = self.algorithm.hash_algorithm().message_digest(); - + let md = match &self.algorithm.hash_algorithm() { + HashAlgorithm::Sha1 => MessageDigest::sha1(), + HashAlgorithm::Sha256 => MessageDigest::sha256(), + HashAlgorithm::Sha384 => MessageDigest::sha384(), + HashAlgorithm::Sha512 => MessageDigest::sha512(), + }; let mut signer = Signer::new(md, &self.private_key)?; signer.update(message)?; let signature = signer.sign_to_vec()?; @@ -323,8 +328,12 @@ impl JwsVerifier for HmacJwsVerifier { fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), JoseError> { (|| -> anyhow::Result<()> { - let md = self.algorithm.hash_algorithm().message_digest(); - + let md = match &self.algorithm.hash_algorithm() { + HashAlgorithm::Sha1 => MessageDigest::sha1(), + HashAlgorithm::Sha256 => MessageDigest::sha256(), + HashAlgorithm::Sha384 => MessageDigest::sha384(), + HashAlgorithm::Sha512 => MessageDigest::sha512(), + }; let mut signer = Signer::new(md, &self.private_key)?; signer.update(message)?; let new_signature = signer.sign_to_vec()?; diff --git a/src/jws/alg/rsassa.rs b/src/jws/alg/rsassa.rs index 7b9a8da..b7f6d4d 100644 --- a/src/jws/alg/rsassa.rs +++ b/src/jws/alg/rsassa.rs @@ -2,6 +2,7 @@ use std::fmt::Display; use std::ops::Deref; use anyhow::bail; +use openssl::hash::MessageDigest; use openssl::pkey::{PKey, Private, Public}; use openssl::sign::{Signer, Verifier}; @@ -374,8 +375,12 @@ impl JwsSigner for RsassaJwsSigner { fn sign(&self, message: &[u8]) -> Result, JoseError> { (|| -> anyhow::Result> { - let md = self.algorithm.hash_algorithm().message_digest(); - + let md = match &self.algorithm.hash_algorithm() { + HashAlgorithm::Sha1 => MessageDigest::sha1(), + HashAlgorithm::Sha256 => MessageDigest::sha256(), + HashAlgorithm::Sha384 => MessageDigest::sha384(), + HashAlgorithm::Sha512 => MessageDigest::sha512(), + }; let mut signer = Signer::new(md, &self.private_key)?; signer.update(message)?; let signature = signer.sign_to_vec()?; @@ -428,8 +433,12 @@ impl JwsVerifier for RsassaJwsVerifier { fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), JoseError> { (|| -> anyhow::Result<()> { - let md = self.algorithm.hash_algorithm().message_digest(); - + let md = match &self.algorithm.hash_algorithm() { + HashAlgorithm::Sha1 => MessageDigest::sha1(), + HashAlgorithm::Sha256 => MessageDigest::sha256(), + HashAlgorithm::Sha384 => MessageDigest::sha384(), + HashAlgorithm::Sha512 => MessageDigest::sha512(), + }; let mut verifier = Verifier::new(md, &self.public_key)?; verifier.update(message)?; if !verifier.verify(signature)? { diff --git a/src/jws/alg/rsassa_pss.rs b/src/jws/alg/rsassa_pss.rs index 0610d4f..b93f47f 100644 --- a/src/jws/alg/rsassa_pss.rs +++ b/src/jws/alg/rsassa_pss.rs @@ -2,6 +2,7 @@ use std::fmt::Display; use std::ops::Deref; use anyhow::bail; +use openssl::hash::MessageDigest; use openssl::pkey::{PKey, Private, Public}; use openssl::rsa::Rsa; use openssl::sign::{Signer, Verifier}; @@ -457,8 +458,12 @@ impl JwsSigner for RsassaPssJwsSigner { fn sign(&self, message: &[u8]) -> Result, JoseError> { (|| -> anyhow::Result> { - let md = self.algorithm.hash_algorithm().message_digest(); - + let md = match &self.algorithm.hash_algorithm() { + HashAlgorithm::Sha1 => MessageDigest::sha1(), + HashAlgorithm::Sha256 => MessageDigest::sha256(), + HashAlgorithm::Sha384 => MessageDigest::sha384(), + HashAlgorithm::Sha512 => MessageDigest::sha512(), + }; let mut signer = Signer::new(md, &self.private_key)?; signer.update(message)?; let signature = signer.sign_to_vec()?; @@ -511,8 +516,12 @@ impl JwsVerifier for RsassaPssJwsVerifier { fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), JoseError> { (|| -> anyhow::Result<()> { - let md = self.algorithm.hash_algorithm().message_digest(); - + let md = match &self.algorithm.hash_algorithm() { + HashAlgorithm::Sha1 => MessageDigest::sha1(), + HashAlgorithm::Sha256 => MessageDigest::sha256(), + HashAlgorithm::Sha384 => MessageDigest::sha384(), + HashAlgorithm::Sha512 => MessageDigest::sha512(), + }; let mut verifier = Verifier::new(md, &self.public_key)?; verifier.update(message)?; if !verifier.verify(signature)? { diff --git a/src/jws/jws_header.rs b/src/jws/jws_header.rs index 6c15f50..39a0f4c 100644 --- a/src/jws/jws_header.rs +++ b/src/jws/jws_header.rs @@ -1,3 +1,4 @@ +use std::any::Any; use std::fmt::{Debug, Display}; use std::ops::Deref; @@ -462,6 +463,18 @@ impl JoseHeader for JwsHeader { fn box_clone(&self) -> Box { Box::new(self.clone()) } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } + + fn into_any(self: Box) -> Box { + self + } } impl AsRef> for JwsHeader { diff --git a/src/jws/jws_header_set.rs b/src/jws/jws_header_set.rs index 31c34b2..d16ffe5 100644 --- a/src/jws/jws_header_set.rs +++ b/src/jws/jws_header_set.rs @@ -1,3 +1,4 @@ +use std::any::Any; use std::fmt::{Debug, Display}; use std::ops::Deref; @@ -480,6 +481,18 @@ impl JoseHeader for JwsHeaderSet { fn box_clone(&self) -> Box { Box::new(self.clone()) } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } + + fn into_any(self: Box) -> Box { + self + } } impl Display for JwsHeaderSet { diff --git a/src/jwt.rs b/src/jwt.rs index 4f6f4e8..5102278 100644 --- a/src/jwt.rs +++ b/src/jwt.rs @@ -11,14 +11,14 @@ pub use crate::jwt::jwt_payload_validator::JwtPayloadValidator; pub use crate::jwt::alg::unsecured::UnsecuredJwsAlgorithm::None; -use once_cell::sync::Lazy; +use std::sync::LazyLock; use crate::jwe::{JweDecrypter, JweEncrypter, JweHeader}; use crate::jwk::{Jwk, JwkSet}; use crate::jws::{JwsHeader, JwsSigner, JwsVerifier}; use crate::{JoseError, JoseHeader}; -static DEFAULT_CONTEXT: Lazy = Lazy::new(|| JwtContext::new()); +static DEFAULT_CONTEXT: LazyLock = LazyLock::new(|| JwtContext::new()); /// Return the string representation of the JWT with a "none" algorithm. /// @@ -193,8 +193,8 @@ mod tests { PS512, RS256, RS384, RS512, }; use crate::jwt::{self, JwtPayload}; - use crate::util; use crate::Value; + use crate::{util, JoseHeader}; #[test] fn test_decode_header() -> Result<()> { @@ -206,6 +206,27 @@ mod tests { Some(&Value::String("RS256".to_string())) ); + let header = jwt::decode_header(&data)?; + let jws_header = header.as_any().downcast_ref::().unwrap(); + assert_eq!( + jws_header.claim("alg"), + Some(&Value::String("RS256".to_string())) + ); + + let mut header = jwt::decode_header(&data)?; + let jws_header = header.as_any_mut().downcast_mut::().unwrap(); + assert_eq!( + jws_header.claim("alg"), + Some(&Value::String("RS256".to_string())) + ); + + let header = jwt::decode_header(&data)?; + let jws_header = header.into_any().downcast::().unwrap(); + assert_eq!( + jws_header.claim("alg"), + Some(&Value::String("RS256".to_string())) + ); + Ok(()) } diff --git a/src/util.rs b/src/util.rs index daf21f9..3930ca1 100644 --- a/src/util.rs +++ b/src/util.rs @@ -2,11 +2,11 @@ pub mod der; pub mod hash_algorithm; pub mod oid; +use std::sync::LazyLock; + use anyhow::bail; use base64::DecodeError; use base64::Engine as _; -use once_cell::sync::Lazy; -use openssl::bn::BigNumRef; use openssl::rand; use regex; @@ -28,7 +28,7 @@ pub(crate) fn ceiling(len: usize, div: usize) -> usize { } pub(crate) fn is_base64_standard(input: &str) -> bool { - static RE_BASE64_STANDARD: Lazy = Lazy::new(|| { + static RE_BASE64_STANDARD: LazyLock = LazyLock::new(|| { regex::Regex::new( r"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/][AQgw]==|[A-Za-z0-9+/]{2}[AEIMQUYcgkosw048]=)?$", ) @@ -39,7 +39,7 @@ pub(crate) fn is_base64_standard(input: &str) -> bool { } pub(crate) fn is_base64_urlsafe_nopad(input: &str) -> bool { - static RE_BASE64_URL_SAFE_NOPAD: Lazy = Lazy::new(|| { + static RE_BASE64_URL_SAFE_NOPAD: LazyLock = LazyLock::new(|| { regex::Regex::new( r"^(?:[A-Za-z0-9_-]{4})*(?:[A-Za-z0-9_-][AQgw]|[A-Za-z0-9_-]{2}[AEIMQUYcgkosw048])?$", ) @@ -72,7 +72,7 @@ pub(crate) fn decode_base64_urlsafe_no_pad( } pub(crate) fn parse_pem(input: &[u8]) -> anyhow::Result<(String, Vec)> { - static RE_PEM: Lazy = Lazy::new(|| { + static RE_PEM: LazyLock = LazyLock::new(|| { regex::bytes::Regex::new(concat!( r"^", r"-----BEGIN ([A-Z0-9 -]+)-----[\t ]*(?:\r\n|[\r\n])", @@ -83,8 +83,8 @@ pub(crate) fn parse_pem(input: &[u8]) -> anyhow::Result<(String, Vec)> { .unwrap() }); - static RE_FILTER: Lazy = - Lazy::new(|| regex::bytes::Regex::new("[\t\r\n ]").unwrap()); + static RE_FILTER: LazyLock = + LazyLock::new(|| regex::bytes::Regex::new("[\t\r\n ]").unwrap()); let result = if let Some(caps) = RE_PEM.captures(input) { match (caps.get(1), caps.get(2), caps.get(3)) { @@ -103,20 +103,6 @@ pub(crate) fn parse_pem(input: &[u8]) -> anyhow::Result<(String, Vec)> { Ok(result) } -pub(crate) fn num_to_vec(num: &BigNumRef, len: usize) -> Vec { - let vec = num.to_vec(); - if vec.len() < len { - let mut tmp = Vec::with_capacity(len); - for _ in 0..(len - vec.len()) { - tmp.push(0); - } - tmp.extend_from_slice(&vec); - tmp - } else { - vec - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/util/hash_algorithm.rs b/src/util/hash_algorithm.rs index ce7c2ac..b6b3387 100644 --- a/src/util/hash_algorithm.rs +++ b/src/util/hash_algorithm.rs @@ -1,4 +1,3 @@ -use openssl::hash::MessageDigest; use std::fmt::Display; #[derive(Debug, Clone, Copy, Eq, PartialEq)] @@ -27,15 +26,6 @@ impl HashAlgorithm { Self::Sha512 => 64, } } - - pub(crate) fn message_digest(&self) -> MessageDigest { - match self { - Self::Sha1 => MessageDigest::sha1(), - Self::Sha256 => MessageDigest::sha256(), - Self::Sha384 => MessageDigest::sha384(), - Self::Sha512 => MessageDigest::sha512(), - } - } } impl Display for HashAlgorithm { diff --git a/src/util/oid.rs b/src/util/oid.rs index a570ffb..c1c465f 100644 --- a/src/util/oid.rs +++ b/src/util/oid.rs @@ -1,55 +1,55 @@ -use once_cell::sync::Lazy; +use std::sync::LazyLock; -pub static OID_RSA_ENCRYPTION: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[1, 2, 840, 113549, 1, 1, 1])); +pub static OID_RSA_ENCRYPTION: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[1, 2, 840, 113549, 1, 1, 1])); -pub static OID_RSASSA_PSS: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[1, 2, 840, 113549, 1, 1, 10])); +pub static OID_RSASSA_PSS: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[1, 2, 840, 113549, 1, 1, 10])); -pub static OID_SHA1: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[1, 3, 14, 3, 2, 26])); +pub static OID_SHA1: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[1, 3, 14, 3, 2, 26])); -pub static OID_SHA256: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[2, 16, 840, 1, 101, 3, 4, 2, 1])); +pub static OID_SHA256: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[2, 16, 840, 1, 101, 3, 4, 2, 1])); -pub static OID_SHA384: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[2, 16, 840, 1, 101, 3, 4, 2, 2])); +pub static OID_SHA384: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[2, 16, 840, 1, 101, 3, 4, 2, 2])); -pub static OID_SHA512: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[2, 16, 840, 1, 101, 3, 4, 2, 3])); +pub static OID_SHA512: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[2, 16, 840, 1, 101, 3, 4, 2, 3])); -pub static OID_MGF1: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[1, 2, 840, 113549, 1, 1, 8])); +pub static OID_MGF1: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[1, 2, 840, 113549, 1, 1, 8])); -pub static OID_ID_EC_PUBLIC_KEY: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[1, 2, 840, 10045, 2, 1])); +pub static OID_ID_EC_PUBLIC_KEY: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[1, 2, 840, 10045, 2, 1])); -pub static OID_PRIME256V1: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[1, 2, 840, 10045, 3, 1, 7])); +pub static OID_PRIME256V1: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[1, 2, 840, 10045, 3, 1, 7])); -pub static OID_SECP384R1: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[1, 3, 132, 0, 34])); +pub static OID_SECP384R1: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[1, 3, 132, 0, 34])); -pub static OID_SECP521R1: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[1, 3, 132, 0, 35])); +pub static OID_SECP521R1: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[1, 3, 132, 0, 35])); -pub static OID_SECP256K1: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[1, 3, 132, 0, 10])); +pub static OID_SECP256K1: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[1, 3, 132, 0, 10])); -pub static OID_ED25519: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[1, 3, 101, 112])); +pub static OID_ED25519: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[1, 3, 101, 112])); -pub static OID_ED448: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[1, 3, 101, 113])); +pub static OID_ED448: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[1, 3, 101, 113])); -pub static OID_X25519: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[1, 3, 101, 110])); +pub static OID_X25519: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[1, 3, 101, 110])); -pub static OID_X448: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[1, 3, 101, 111])); +pub static OID_X448: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[1, 3, 101, 111])); -pub static OID_BP256R1: Lazy = - Lazy::new(|| ObjectIdentifier::from_slice(&[1, 3, 36, 3, 3, 2, 8, 1, 1, 7])); +pub static OID_BP256R1: LazyLock = + LazyLock::new(|| ObjectIdentifier::from_slice(&[1, 3, 36, 3, 3, 2, 8, 1, 1, 7])); #[derive(Debug, Eq, PartialEq)] pub struct ObjectIdentifier {