diff --git a/Cargo.lock b/Cargo.lock index 9a174a3..585f97b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,12 +41,29 @@ dependencies = [ "libc", ] +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + [[package]] name = "anyhow" version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.2.0" @@ -107,6 +124,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cc" version = "1.0.95" @@ -133,6 +156,33 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "cipher" version = "0.4.4" @@ -143,6 +193,27 @@ dependencies = [ "inout", ] +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "bitflags", + "clap_lex", + "indexmap", + "textwrap", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "colored" version = "2.1.0" @@ -174,6 +245,75 @@ dependencies = [ "libc", ] +[[package]] +name = "criterion" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" +dependencies = [ + "anes", + "atty", + "cast", + "ciborium", + "clap", + "criterion-plot", + "futures", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "tokio", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -233,6 +373,12 @@ dependencies = [ "spki", ] +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" + [[package]] name = "elliptic-curve" version = "0.13.8" @@ -392,12 +538,37 @@ dependencies = [ "subtle", ] +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.3.9" @@ -445,6 +616,16 @@ dependencies = [ "cc", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "indoc" version = "2.0.5" @@ -460,6 +641,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -553,7 +743,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] @@ -573,6 +763,7 @@ dependencies = [ "anyhow", "chrono", "colored", + "criterion", "elliptic-curve", "futures", "hkdf", @@ -606,6 +797,18 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" + [[package]] name = "p256" version = "0.13.2" @@ -693,6 +896,34 @@ dependencies = [ "spki", ] +[[package]] +name = "plotters" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" + +[[package]] +name = "plotters-svg" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +dependencies = [ + "plotters-backend", +] + [[package]] name = "portable-atomic" version = "1.6.0" @@ -825,6 +1056,26 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -909,6 +1160,15 @@ dependencies = [ "cipher", ] +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -1066,6 +1326,12 @@ version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" + [[package]] name = "thiserror" version = "1.0.59" @@ -1086,6 +1352,16 @@ dependencies = [ "syn", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tokio" version = "1.37.0" @@ -1146,6 +1422,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1206,6 +1492,47 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 27b3e13..39b38ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,9 @@ pyo3 = { version = "0.20", optional = true } elliptic-curve = { version = "0.13", features = ["sec1"], optional = true } p256 = { version = "0.13", features = ["ecdh"], optional = true } +[dev-dependencies] +criterion = { version = "0.4", features = ["async_tokio", "html_reports"] } + [lib] name = "oblivion" @@ -40,8 +43,16 @@ name = "oblivion" name = "main" [profile.release] -lto = true +panic = "abort" # Strip expensive panic clean-up logic +codegen-units = 1 # Compile crates one after another so the compiler can optimize better +lto = true # Enables link to optimizations +opt-level = 3 +strip = true # Remove debug symbols [features] unsafe = ["elliptic-curve", "p256"] python = ["pyo3"] + +[[bench]] +name = "keygen" +harness = false diff --git a/benches/keygen.rs b/benches/keygen.rs new file mode 100644 index 0000000..5b873b8 --- /dev/null +++ b/benches/keygen.rs @@ -0,0 +1,82 @@ +use anyhow::Result; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use oblivion::utils::generator::{generate_key_pair, generate_random_salt, SharedKey}; +use tokio::runtime::Runtime; + +#[cfg(feature = "unsafe")] +use p256::{ecdh::EphemeralSecret, PublicKey}; +#[cfg(not(feature = "unsafe"))] +use ring::agreement::{EphemeralPrivateKey, PublicKey, UnparsedPublicKey, X25519}; + +async fn generate() { + generate_key_pair().unwrap(); +} + +async fn hkdf( + #[cfg(feature = "unsafe")] private_key: EphemeralSecret, + #[cfg(not(feature = "unsafe"))] private_key: EphemeralPrivateKey, + public_key: PublicKey, + salt: Vec, +) -> Result<()> { + #[cfg(feature = "unsafe")] + let mut shared_key = SharedKey::new(&private_key, &public_key); + #[cfg(not(feature = "unsafe"))] + let mut shared_key = SharedKey::new( + private_key, + &UnparsedPublicKey::new(&X25519, public_key.as_ref().to_vec()), + )?; + shared_key.hkdf(&salt)?; + Ok(()) +} + +async fn scrypt( + #[cfg(feature = "unsafe")] private_key: EphemeralSecret, + #[cfg(not(feature = "unsafe"))] private_key: EphemeralPrivateKey, + public_key: PublicKey, + salt: Vec, +) -> Result<()> { + #[cfg(feature = "unsafe")] + let mut shared_key = SharedKey::new(&private_key, &public_key); + #[cfg(not(feature = "unsafe"))] + let mut shared_key = SharedKey::new( + private_key, + &UnparsedPublicKey::new(&X25519, public_key.as_ref().to_vec()), + )?; + shared_key.scrypt(&salt)?; + Ok(()) +} + +fn criterion_benchmark_keygen(c: &mut Criterion) { + c.bench_function("keygen", |b| { + b.to_async(Runtime::new().unwrap()) + .iter(|| async { generate().await }) + }); +} + +fn criterion_benchmark_kdf(c: &mut Criterion) { + c.bench_function("kdf", |b| { + b.to_async(Runtime::new().unwrap()).iter(|| async { + let (prk, puk) = generate_key_pair().unwrap(); + let salt = generate_random_salt(); + hkdf(black_box(prk), black_box(puk), black_box(salt.to_vec())).await + }) + }); +} + +fn criterion_benchmark_scrypt(c: &mut Criterion) { + c.bench_function("scrypt", |b| { + b.to_async(Runtime::new().unwrap()).iter(|| async { + let (prk, puk) = generate_key_pair().unwrap(); + let salt = generate_random_salt(); + scrypt(black_box(prk), black_box(puk), black_box(salt)).await + }) + }); +} + +criterion_group!( + benches, + criterion_benchmark_keygen, + criterion_benchmark_kdf, + criterion_benchmark_scrypt +); +criterion_main!(benches); diff --git a/src/bin/main.rs b/src/bin/main.rs index 4065b84..b877b0d 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,20 +1,18 @@ use anyhow::Result; use oblivion::models::client::Client; -use oblivion::models::render::{BaseResponse, Response}; +use oblivion::models::render::BaseResponse; use oblivion::models::router::{RoutePath, RouteType, Router}; use oblivion::models::server::Server; use oblivion::models::session::Session; use oblivion::path_route; -use oblivion::utils::generator::{generate_key_pair, generate_random_salt, SharedKey}; +use oblivion::types::server; use oblivion_codegen::async_route; -#[cfg(not(feature = "unsafe"))] -use ring::agreement::{UnparsedPublicKey, X25519}; use serde_json::json; use std::env::args; use std::time::Instant; #[async_route] -fn handler(_sess: Session) -> Response { +fn handler(_sess: Session) -> server::Result { Ok(BaseResponse::TextResponse( "每一个人都应该拥有守护信息与获得真实信息的神圣权利, 任何与之对抗的都是我们的敌人" .to_string(), @@ -23,7 +21,7 @@ fn handler(_sess: Session) -> Response { } #[async_route] -fn welcome(mut sess: Session) -> Response { +fn welcome(mut sess: Session) -> server::Result { Ok(BaseResponse::TextResponse( format!( "欢迎进入信息绝对安全区, 来自[{}]的朋友", @@ -34,7 +32,7 @@ fn welcome(mut sess: Session) -> Response { } #[async_route] -fn json(_sess: Session) -> Response { +fn json(_sess: Session) -> server::Result { Ok(BaseResponse::JsonResponse( json!({"status": true, "msg": "只身堕入极暗之永夜, 以期再世涅槃之阳光"}), 200, @@ -42,7 +40,7 @@ fn json(_sess: Session) -> Response { } #[async_route] -async fn alive(sess: Session) -> Response { +async fn alive(sess: Session) -> server::Result { sess.send("test".into(), 200).await?; assert_eq!(sess.recv().await?.text()?, "test"); Ok(BaseResponse::JsonResponse( @@ -61,35 +59,6 @@ async fn main() -> Result<()> { args.push("/welcome".to_string()); } match args[1].as_str() { - "keygen" => { - let now = Instant::now(); - generate_key_pair()?; - println!("执行时间: {}", now.elapsed().as_millis()); - } - "dh" => { - let now = Instant::now(); - let (pr, pu) = generate_key_pair()?; - let (alice_pr, alice_pu) = generate_key_pair()?; - let salt = generate_random_salt(); - #[cfg(feature = "unsafe")] - let mut shared_bob = SharedKey::new(&pr, &alice_pu); - #[cfg(not(feature = "unsafe"))] - let mut shared_bob = SharedKey::new( - pr, - &UnparsedPublicKey::new(&X25519, alice_pu.as_ref().to_vec()), - ); - #[cfg(feature = "unsafe")] - let mut shared_alice = SharedKey::new(&alice_pr, &pu); - #[cfg(not(feature = "unsafe"))] - let mut shared_alice = SharedKey::new( - alice_pr, - &UnparsedPublicKey::new(&X25519, pu.as_ref().to_vec()), - ); - let bob_key = shared_bob.hkdf(&salt)?; - let alice_key = shared_alice.hkdf(&salt)?; - assert_eq!(bob_key, alice_key); - println!("执行时间: {}", now.elapsed().as_millis()); - } "bench" => loop { let now = Instant::now(); let client = Client::connect(&format!("127.0.0.1:7076{}", args[2])).await?;