diff --git a/zino-core/Cargo.toml b/zino-core/Cargo.toml index 5948a721..907824a3 100644 --- a/zino-core/Cargo.toml +++ b/zino-core/Cargo.toml @@ -238,7 +238,7 @@ version = "0.9.1" features = ["macros"] [dependencies.utoipa] -version = "3.5.0" +version = "4.0.0" features = [ "non_strict_integers", "preserve_order", @@ -259,7 +259,10 @@ features = [ anyhow = "1.0.75" base64-simd = "0.8.0" criterion = "0.5.1" +data-encoding = "2.4.0" +libsm = "0.5.1" ryu = "1.0.15" +sm3 = "0.4.2" tinyvec = { version = "1.6.0", features = ["alloc"] } uuid-simd = "0.8.0" diff --git a/zino-core/benches/base64_simd.rs b/zino-core/benches/base64_simd.rs index c2341de9..a87351b1 100644 --- a/zino-core/benches/base64_simd.rs +++ b/zino-core/benches/base64_simd.rs @@ -13,6 +13,12 @@ pub fn bench(c: &mut criterion::Criterion) { base64_simd::STANDARD_NO_PAD.encode_to_string(bytes) }) }); + c.bench_function("data_encoding_base64_encode", |b| { + b.iter(|| { + let bytes = b"hello world"; + data_encoding::BASE64_NOPAD.encode(bytes) + }) + }); c.bench_function("base64_decode", |b| { b.iter(|| { let encoded = "Er/DkSLyeOsUiHXHK4hO7E8fdl1g8Qwy2Ef8mR1/4BQ"; @@ -31,4 +37,10 @@ pub fn bench(c: &mut criterion::Criterion) { base64_simd::forgiving_decode_to_vec(encoded.as_bytes()) }) }); + c.bench_function("data_encoding_base64_decode", |b| { + b.iter(|| { + let encoded = "Er/DkSLyeOsUiHXHK4hO7E8fdl1g8Qwy2Ef8mR1/4BQ"; + data_encoding::BASE64_NOPAD.decode(encoded.as_bytes()) + }) + }); } diff --git a/zino-core/benches/criterion_main.rs b/zino-core/benches/criterion_main.rs index e77a07a2..9baca481 100644 --- a/zino-core/benches/criterion_main.rs +++ b/zino-core/benches/criterion_main.rs @@ -4,6 +4,7 @@ mod format_duration; mod hashmap_vec; mod json_raw_value; mod serde_map; +mod sha256_sm3; mod str_join; mod uuid_simd; @@ -15,6 +16,7 @@ criterion::criterion_group!( hashmap_vec::bench, json_raw_value::bench, serde_map::bench, + sha256_sm3::bench, str_join::bench, uuid_simd::bench, ); diff --git a/zino-core/benches/sha256_sm3.rs b/zino-core/benches/sha256_sm3.rs new file mode 100644 index 00000000..3aa4eaf7 --- /dev/null +++ b/zino-core/benches/sha256_sm3.rs @@ -0,0 +1,30 @@ +pub fn bench(c: &mut criterion::Criterion) { + c.bench_function("sha256_digest", |b| { + b.iter(|| { + use sha2::{Digest, Sha256}; + + let data = b"Hellow, world!"; + let mut hasher = Sha256::new(); + hasher.update(data); + hasher.finalize() + }) + }); + c.bench_function("sm3_digest", |b| { + b.iter(|| { + use sm3::{Digest, Sm3}; + + let data = b"Hellow, world!"; + let mut hasher = Sm3::new(); + hasher.update(data); + hasher.finalize() + }) + }); + c.bench_function("libsm_digest", |b| { + b.iter(|| { + use libsm::sm3::hash::Sm3Hash; + + let data = b"Hellow, world!"; + Sm3Hash::new(data).get_hash() + }) + }); +} diff --git a/zino-core/benches/uuid_simd.rs b/zino-core/benches/uuid_simd.rs index bbcfa30f..579f6f33 100644 --- a/zino-core/benches/uuid_simd.rs +++ b/zino-core/benches/uuid_simd.rs @@ -2,7 +2,7 @@ use uuid::Uuid; use uuid_simd::UuidExt; pub fn bench(c: &mut criterion::Criterion) { - c.bench_function("formt_uuid", |b| { + c.bench_function("format_uuid", |b| { b.iter(|| { let value = Uuid::new_v4(); value.to_string() diff --git a/zino-core/src/auth/jwt_claims.rs b/zino-core/src/auth/jwt_claims.rs index 920c8f37..fb59d3e2 100644 --- a/zino-core/src/auth/jwt_claims.rs +++ b/zino-core/src/auth/jwt_claims.rs @@ -7,7 +7,7 @@ use crate::{ JsonValue, Map, }; use jwt_simple::{ - algorithms::{HS256Key, MACLike}, + algorithms::MACLike, claims::{self, Claims, JWTClaims}, common::VerificationOptions, }; @@ -130,9 +130,9 @@ impl JwtClaims { } impl JwtClaims<()> { - /// Returns the shared secret access key for the `HS256` JWT algorithm. + /// Returns the shared secret access key for the HMAC algorithm. #[inline] - pub fn shared_key() -> &'static HS256Key { + pub fn shared_key() -> &'static JwtHmacKey { LazyLock::force(&SECRET_KEY) } } @@ -190,8 +190,8 @@ static DEFAULT_REFRESH_INTERVAL: LazyLock = LazyLock::new(|| { .unwrap_or_else(|| Duration::from_secs(60 * 60 * 24 * 30)) }); -/// Shared secret access key for the `HS256` JWT algorithm. -static SECRET_KEY: LazyLock = LazyLock::new(|| { +/// Shared secret access key for the HMAC algorithm. +static SECRET_KEY: LazyLock = LazyLock::new(|| { let config = State::shared().config(); let checksum: [u8; 32] = config .get_table("jwt") @@ -210,5 +210,90 @@ static SECRET_KEY: LazyLock = LazyLock::new(|| { crypto::digest(app_name.as_bytes()) }); let secret_key = crypto::derive_key("ZINO:JWT", &checksum); - HS256Key::from_bytes(&secret_key) + JwtHmacKey::from_bytes(&secret_key) }); + +cfg_if::cfg_if! { + if #[cfg(feature = "crypto-sm")] { + use hmac::{Hmac, Mac}; + use jwt_simple::{algorithms::HMACKey, common::KeyMetadata}; + use sm3::Sm3; + + /// HMAC-SM3 key type. + #[derive(Debug, Clone)] + pub struct HSm3Key { + /// key. + key: HMACKey, + /// Key ID. + key_id: Option, + } + + impl HSm3Key { + /// Creates a new instance from bytes. + pub fn from_bytes(raw_key: &[u8]) -> Self { + Self { + key: HMACKey::from_bytes(raw_key), + key_id: None, + } + } + + /// Returns the bytes. + pub fn to_bytes(&self) -> Vec { + self.key.to_bytes() + } + + /// Generates a new instance with random bytes. + pub fn generate() -> Self { + Self { + key: HMACKey::generate(), + key_id: None, + } + } + + /// Set the key ID. + pub fn with_key_id(mut self, key_id: &str) -> Self { + self.key_id = Some(key_id.to_owned()); + self + } + } + + impl MACLike for HSm3Key { + fn jwt_alg_name() -> &'static str { + "HSM3" + } + + fn key(&self) -> &HMACKey { + &self.key + } + + fn key_id(&self) -> &Option { + &self.key_id + } + + fn set_key_id(&mut self, key_id: String) { + self.key_id = Some(key_id); + } + + fn metadata(&self) -> &Option { + &None + } + + fn attach_metadata(&mut self, _metadata: KeyMetadata) -> Result<(), jwt_simple::Error> { + Ok(()) + } + + fn authentication_tag(&self, authenticated: &str) -> Vec { + let mut mac = Hmac::::new_from_slice(self.key().as_ref()) + .expect("HMAC can take key of any size"); + mac.update(authenticated.as_bytes()); + mac.finalize().into_bytes().to_vec() + } + } + + /// HMAC key type for JWT. + pub type JwtHmacKey = HSm3Key; + } else { + /// HMAC key type for JWT. + pub type JwtHmacKey = jwt_simple::algorithms::HS256Key; + } +} diff --git a/zino-core/src/auth/mod.rs b/zino-core/src/auth/mod.rs index b876c06f..cb197d18 100644 --- a/zino-core/src/auth/mod.rs +++ b/zino-core/src/auth/mod.rs @@ -16,7 +16,7 @@ pub use access_key::{AccessKeyId, SecretAccessKey}; pub use authentication::Authentication; pub use authorization_provider::AuthorizationProvider; pub use client_credentials::ClientCredentials; -pub use jwt_claims::JwtClaims; +pub use jwt_claims::{JwtClaims, JwtHmacKey}; pub use security_token::SecurityToken; pub use session_id::SessionId; pub use user_session::UserSession; diff --git a/zino-core/src/lib.rs b/zino-core/src/lib.rs index 4d854968..be0821e0 100644 --- a/zino-core/src/lib.rs +++ b/zino-core/src/lib.rs @@ -10,6 +10,7 @@ //! //! [`zino`]: https://github.com/photino/zino +#![allow(async_fn_in_trait)] #![doc(html_favicon_url = "https://photino.github.io/zino-docs-zh/assets/zino-logo.png")] #![doc(html_logo_url = "https://photino.github.io/zino-docs-zh/assets/zino-logo.svg")] #![feature(associated_type_defaults)] diff --git a/zino-model/src/lib.rs b/zino-model/src/lib.rs index f9c303c3..2cdf1b90 100644 --- a/zino-model/src/lib.rs +++ b/zino-model/src/lib.rs @@ -10,6 +10,7 @@ //! //! [`zino`]: https://github.com/photino/zino +#![allow(async_fn_in_trait)] #![doc(html_favicon_url = "https://photino.github.io/zino-docs-zh/assets/zino-logo.png")] #![doc(html_logo_url = "https://photino.github.io/zino-docs-zh/assets/zino-logo.svg")] #![feature(async_fn_in_trait)] diff --git a/zino/Cargo.toml b/zino/Cargo.toml index 2f3ddc3e..a1de1c80 100644 --- a/zino/Cargo.toml +++ b/zino/Cargo.toml @@ -144,7 +144,7 @@ version = "3.5.0" optional = true [dependencies.utoipa-rapidoc] -version = "0.1.0" +version = "1.0.0" optional = true [dependencies.zino-core] diff --git a/zino/src/lib.rs b/zino/src/lib.rs index 10ae98da..9c058103 100644 --- a/zino/src/lib.rs +++ b/zino/src/lib.rs @@ -49,6 +49,7 @@ //! [`axum-app`]: https://github.com/photino/zino/tree/main/examples/axum-app //! [`dioxus-desktop`]: https://github.com/photino/zino/tree/main/examples/dioxus-desktop +#![allow(async_fn_in_trait)] #![doc(html_favicon_url = "https://photino.github.io/zino-docs-zh/assets/zino-logo.png")] #![doc(html_logo_url = "https://photino.github.io/zino-docs-zh/assets/zino-logo.svg")] #![feature(async_fn_in_trait)]