diff --git a/Cargo.lock b/Cargo.lock index 3bf99b4..11eba23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -216,6 +216,16 @@ dependencies = [ "heapless", ] +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + [[package]] name = "aes" version = "0.8.3" @@ -227,13 +237,27 @@ dependencies = [ "cpufeatures 0.2.12", ] +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead 0.5.2", + "aes", + "cipher 0.4.4", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "ahash" version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.14", "once_cell", "version_check", ] @@ -245,7 +269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if 1.0.0", - "getrandom 0.2.12", + "getrandom 0.2.14", "once_cell", "version_check", "zerocopy", @@ -284,6 +308,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + [[package]] name = "arrayvec" version = "0.4.12" @@ -559,7 +589,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" dependencies = [ - "sha2", + "sha2 0.10.8", "tinyvec", ] @@ -692,7 +722,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1580317203210c517b6d44794abfbe600698276db18127e37ad3e69bf5e848e5" dependencies = [ - "aead", + "aead 0.4.3", "chacha20", "cipher 0.3.0", "poly1305", @@ -770,7 +800,7 @@ dependencies = [ "hmac", "k256", "serde", - "sha2", + "sha2 0.10.8", "thiserror", ] @@ -786,7 +816,7 @@ dependencies = [ "once_cell", "pbkdf2 0.12.2", "rand 0.8.5", - "sha2", + "sha2 0.10.8", "thiserror", ] @@ -805,7 +835,7 @@ dependencies = [ "ripemd", "serde", "serde_derive", - "sha2", + "sha2 0.10.8", "sha3 0.10.8", "thiserror", ] @@ -961,6 +991,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core 0.6.4", "typenum", ] @@ -1106,6 +1137,23 @@ dependencies = [ "spki", ] +[[package]] +name = "ecies" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0206e602d2645ec8b24ed8307fadbc6c3110e2b11ab2f806fc02fee49327079" +dependencies = [ + "getrandom 0.2.14", + "hkdf", + "libsecp256k1", + "once_cell", + "openssl", + "parking_lot", + "rand_core 0.6.4", + "sha2 0.10.8", + "wasm-bindgen", +] + [[package]] name = "either" version = "1.9.0" @@ -1212,7 +1260,7 @@ dependencies = [ "scrypt", "serde", "serde_json", - "sha2", + "sha2 0.10.8", "sha3 0.10.8", "thiserror", "uuid", @@ -1478,7 +1526,7 @@ dependencies = [ "eth-keystore", "ethers-core", "rand 0.8.5", - "sha2", + "sha2 0.10.8", "thiserror", "tracing", ] @@ -1545,7 +1593,7 @@ dependencies = [ "fawkes-crypto-zkbob-bellman_ce", "fawkes-crypto_derive", "ff-uint", - "getrandom 0.2.12", + "getrandom 0.2.14", "impl-trait-for-tuples 0.1.3", "itertools 0.10.5", "linked-list", @@ -1900,13 +1948,25 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if 1.0.0", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", ] [[package]] @@ -2057,6 +2117,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" version = "0.12.1" @@ -2153,6 +2222,19 @@ dependencies = [ "tokio-rustls", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "idna" version = "0.4.0" @@ -2355,7 +2437,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", - "sha2", + "sha2 0.10.8", "signature", ] @@ -2431,6 +2513,52 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64 0.13.1", + "digest 0.9.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.5", + "serde", + "sha2 0.9.9", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + [[package]] name = "libzeropool-zkbob" version = "1.3.0" @@ -2536,6 +2664,23 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "new_debug_unreachable" version = "1.0.4" @@ -2652,6 +2797,10 @@ name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +dependencies = [ + "critical-section", + "portable-atomic", +] [[package]] name = "opaque-debug" @@ -2686,9 +2835,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.63" +version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ "bitflags 2.4.2", "cfg-if 1.0.0", @@ -2710,6 +2859,12 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + [[package]] name = "openssl-src" version = "300.2.2+3.2.1" @@ -2721,9 +2876,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.99" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -2766,9 +2921,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -2819,7 +2974,7 @@ dependencies = [ "digest 0.10.7", "hmac", "password-hash", - "sha2", + "sha2 0.10.8", ] [[package]] @@ -2974,9 +3129,27 @@ checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" dependencies = [ "cpufeatures 0.2.12", "opaque-debug", - "universal-hash", + "universal-hash 0.4.1", +] + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures 0.2.12", + "opaque-debug", + "universal-hash 0.5.1", ] +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + [[package]] name = "powerfmt" version = "0.2.0" @@ -3251,7 +3424,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.14", ] [[package]] @@ -3316,7 +3489,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.14", "libredox", "thiserror", ] @@ -3392,10 +3565,12 @@ dependencies = [ "http-body", "hyper", "hyper-rustls", + "hyper-tls", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -3407,6 +3582,7 @@ dependencies = [ "sync_wrapper", "system-configuration", "tokio", + "tokio-native-tls", "tokio-rustls", "tower-service", "url", @@ -3449,7 +3625,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ "cc", - "getrandom 0.2.12", + "getrandom 0.2.14", "libc", "spin 0.9.8", "untrusted 0.9.0", @@ -3606,6 +3782,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -3621,7 +3806,7 @@ dependencies = [ "hmac", "pbkdf2 0.11.0", "salsa20", - "sha2", + "sha2 0.10.8", ] [[package]] @@ -3666,6 +3851,29 @@ dependencies = [ "cc", ] +[[package]] +name = "security-framework" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "seedbox" version = "0.2.0" @@ -3761,6 +3969,19 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures 0.2.12", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.10.8" @@ -3968,7 +4189,7 @@ dependencies = [ "semver", "serde", "serde_json", - "sha2", + "sha2 0.10.8", "thiserror", "url", "zip", @@ -4198,6 +4419,16 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.24.1" @@ -4455,6 +4686,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "untrusted" version = "0.7.1" @@ -4490,7 +4731,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.12", + "getrandom 0.2.14", "serde", ] @@ -4587,9 +4828,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -4597,9 +4838,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -4624,9 +4865,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote 1.0.35", "wasm-bindgen-macro-support", @@ -4634,9 +4875,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2 1.0.78", "quote 1.0.35", @@ -4647,9 +4888,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" @@ -4934,7 +5175,9 @@ name = "zkbob_generator" version = "0.1.0" dependencies = [ "actix-web", + "aes-gcm", "dotenv", + "ecies", "env_logger", "ethers", "foundry-contracts", @@ -4942,6 +5185,7 @@ dependencies = [ "libzeropool-zkbob", "log", "openssl", + "reqwest", "secp256k1", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 79a1508..4e98219 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,9 @@ hex = "0.4" secp256k1 = "0.28.0" libzeropool-zkbob="1.3.0" ethers ={version = "2.0.10", features = ["abigen", "ws", "rustls"] } +reqwest = { version = "0.11", features = ["json"] } +ecies = {version = "0.2.6", features = ["std"]} +aes-gcm = "0.10.3" [[bin]] diff --git a/tests/ivs_tests.rs b/tests/ivs_tests.rs new file mode 100644 index 0000000..c3816f0 --- /dev/null +++ b/tests/ivs_tests.rs @@ -0,0 +1,120 @@ +#[cfg(test)] +mod tests { + use reqwest::Client; + use std::process::{Child, Command}; + use std::thread; + use std::time::Duration; + + fn spawn_server() -> Child { + let server = Command::new("cargo") + .args(&["run", "--bin", "ivs"]) // Replace with your actual binary name + .spawn() + .expect("Server failed to start"); + + // Give the server a few seconds to start + thread::sleep(Duration::from_secs(2)); + server + } + + #[tokio::test] + async fn test_basic_endpoint() { + let mut server = spawn_server(); + + let client = Client::new(); + let response = client + .get("http://127.0.0.1:3030/api/test") + .send() + .await + .expect("Failed to send request"); + + assert_eq!(response.status(), 200); + + let body = response.text().await.expect("Failed to read response body"); + assert_eq!( + body, + "{\"message\":\"The zkbob ivs is running!!\",\"data\":null}" + ); + + // Terminate the server process + server.kill().expect("Failed to kill server process"); + } + + #[tokio::test] + async fn test_check_inputs() { + use serde::{Deserialize, Serialize}; + + let mut server = spawn_server(); + + #[derive(Debug, Serialize, Deserialize, Clone)] + pub struct InputPayload { + pub public: String, + pub secrets: Option, + } + + let client = Client::new(); + let payload = InputPayload { + public: "some_public_data".into(), + secrets: Some("some_secret_data".into()), + }; + + let response = client + .post("http://127.0.0.1:3030/api/checkInputs") + .json(&payload) + .send() + .await + .expect("Failed to send request"); + + assert_eq!(response.status(), 200); + let body = response.text().await.expect("Failed to read response body"); + assert_eq!(body, "true"); + + // Terminate the server process + server.kill().expect("Failed to kill server process"); + } + + #[tokio::test] + async fn test_check_encrypted_inputs() { + use serde::{Deserialize, Serialize}; + + let mut server = spawn_server(); + + #[derive(Debug, Serialize, Deserialize, Clone)] + pub struct EncryptedInputPayload { + pub acl: String, + pub encrypted_secrets: String, + pub me_decryption_url: String, + pub market_id: String, + } + + let client = Client::new(); + + + let encrypted_data = "e87a1e02d89aae5eb8e497dbdc72e5bd58fc509522283f699ac31972041b4b80"; + let acl_data = "\u{4}�1�RcB\u{5}�\u{2}V�c\u{e}\0�q�LQ\u{6}o.M6��&R��U�Iw�ż�\u{1a}��1MA`�\u{7}��\u{c}��9_\u{7}C��l�us\u{1b}���F�\u{5}��\u{6}�z��\u{7f}�V)R �O$�&\u{1c}o����-�w�\u{8}�.����\u{19}�Ύ \u{f}YfѺ-��f<\u{33b}��m���"; + let payload = EncryptedInputPayload { + acl: acl_data.to_string(), + encrypted_secrets: encrypted_data.to_string(), + me_decryption_url: "http://localhost:3000/decryptRequest".to_string(), + market_id: "1".to_string(), + }; + + let response = client + .post("http://127.0.0.1:3030/api/checkEncryptedInputs") + .json(&payload) + .send() + .await + .expect("Failed to send request"); + + assert_eq!(response.status(), 200); + let body = response.text().await.expect("Failed to read response body"); + assert_eq!(body, "true"); + + // Terminate the server process + server.kill().expect("Failed to kill server process"); + // Terminate the server process + server.kill().expect("Failed to kill server process"); + } + + + +} diff --git a/tools/ivs.rs b/tools/ivs.rs index 08bbd23..d97a86d 100644 --- a/tools/ivs.rs +++ b/tools/ivs.rs @@ -1,15 +1,30 @@ use actix_web::http::StatusCode; use actix_web::{get, post, web, Responder}; use actix_web::{App, HttpResponse, HttpServer}; +use secp256k1::{PublicKey, Secp256k1, SecretKey}; +use secret_inputs_helpers::decrypt_ecies; use serde::{Deserialize, Serialize}; use std::time::Duration; +use ethers::core::k256::ecdsa::{SigningKey, VerifyingKey}; +use ethers::core::rand::thread_rng; +use ethers::signers::LocalWallet; +use ethers::types::{Bytes, Signature, U256}; +use ethers::utils::keccak256; +use hex::encode; +use reqwest::Client; +use std::fs::File; +use std::io::Read; +use std::str::FromStr; + +mod secret_inputs_helpers; + #[actix_web::main] async fn main() -> std::io::Result<()> { println!("Ivs pending"); env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); - let port: u16 = 3030; + let port: u16 = 3040; let server = HttpServer::new(move || App::new().configure(routes)) .client_request_timeout(Duration::new(0, 0)) @@ -27,7 +42,8 @@ async fn main() -> std::io::Result<()> { pub fn routes(conf: &mut web::ServiceConfig) { let scope = web::scope("/api") .service(test) - .service(check_input_handler); + .service(check_input_handler) + .service(check_encrypted_input_handler); conf.service(scope); } @@ -72,14 +88,17 @@ async fn check_input_handler(payload: web::Json) -> impl Responder #[derive(Debug, Serialize, Deserialize, Clone)] pub struct EncryptedInputPayload { - pub public: String, + pub acl: String, pub encrypted_secrets: String, + pub me_decryption_url: String, + pub market_id: String, } + #[post("/checkEncryptedInputs")] async fn check_encrypted_input_handler( payload: web::Json, ) -> impl Responder { - #[derive(Deserialize)] + #[derive(Debug, Serialize, Deserialize)] pub struct DecryptRequest { market_id: String, private_input: String, @@ -87,10 +106,229 @@ async fn check_encrypted_input_handler( signature: String, ivs_pubkey: String, } + + #[derive(Debug, Deserialize)] + struct GetRequestResponse { + encrpyted_data: String, + } + + let market_id: &str = payload.market_id.as_ref(); + let signature = sign_message_hash(market_id.to_string()); + let ivs_pubkey = read_private_key_and_generate_public(); + let public_key_bytes = hex::decode(ivs_pubkey.trim()).expect("Invalid hex string"); + let ivs_pubkey_string = hex::encode(&public_key_bytes); + + let decrypt_request = DecryptRequest { + market_id: market_id.to_string(), + private_input: payload.clone().encrypted_secrets, + acl: payload.clone().acl, + signature, + ivs_pubkey: ivs_pubkey_string, + }; + + // Create a reqwest Client + let client = Client::new(); + + // Define the URL for the request + // let url = "http://localhost:3000/decryptRequest"; // send request to matching engine `/decryptRequest from here` - return zkbob_generator::response::response( - "not implemented", - StatusCode::NOT_IMPLEMENTED, - None, - ); + let url: &str = payload.me_decryption_url.as_ref(); + + let response: Result = + client.post(url).json(&decrypt_request).send().await; + + match response { + Ok(ref resp) => { + match resp.status() { + reqwest::StatusCode::OK => { + // Handle the success case + println!("Request was successful"); + } + reqwest::StatusCode::BAD_REQUEST => { + // Handle the bad request case + return zkbob_generator::response::response( + "Request failed", + StatusCode::BAD_REQUEST, + None, + ); + } + reqwest::StatusCode::UNAUTHORIZED => { + // Handle the unauthorized case + return zkbob_generator::response::response( + "Request failed", + StatusCode::UNAUTHORIZED, + None, + ); + } + reqwest::StatusCode::NOT_FOUND => { + // Handle the not found case + return zkbob_generator::response::response( + "Request failed", + StatusCode::NOT_FOUND, + None, + ); + } + status => { + // Handle other status codes + println!("Received response with status code: {}", status); + } + } + } + Err(e) => { + eprintln!("Request failed: {}", e); + return zkbob_generator::response::response( + "Request failed", + StatusCode::BAD_REQUEST, + None, + ); + } + } + + let response_body: GetRequestResponse = response.unwrap().json().await.expect("Failed to deserialize response body"); + + let mut file = File::open("./app.secp").expect("file not found"); + let mut private_key_hex = String::new(); + let _ = file.read_to_string(&mut private_key_hex); + + // Step 2: Convert the hexadecimal private key to bytes + let private_key_bytes = hex::decode(private_key_hex.trim()).expect("Invalid hex string"); + let encrypted_data = response_body.encrpyted_data; + let encrypted_data_bytes: Vec = serde_json::from_str(&encrypted_data).unwrap(); + + let decrypted = decrypt_ecies( &private_key_bytes, &encrypted_data_bytes).unwrap(); + let bytes: Bytes = Bytes::from(decrypted.clone()); + + let result = zkbob_generator::verification::verify_zkbob_secret(&bytes, &decrypted).await; + if result.is_err() { + return zkbob_generator::response::response( + "invalid inputs!!", + StatusCode::BAD_REQUEST, + None, + ); + } + + let result = result.unwrap(); + if result { + return zkbob_generator::response::response( + "valid inputs.", + StatusCode::OK, + None, + ); + } else { + return zkbob_generator::response::response( + "invalid inputs!!", + StatusCode::BAD_REQUEST, + None, + ); + } +} + +pub fn generate_key() { + // Generate a random signing key (private key) + let signing_key = SigningKey::random(&mut thread_rng()); + + // Derive the verifying key (public key) from the signing key (private key) + let verifying_key = VerifyingKey::from(&signing_key); + + // Print the private key in hexadecimal format + let private_key_bytes = signing_key.to_bytes(); + println!("Private Key: 0x{}", encode(private_key_bytes)); + + // Print the public key in uncompressed format + let binding = verifying_key.to_encoded_point(false); + let public_key_bytes = binding.as_bytes(); + println!("Public Key: 0x{}", encode(public_key_bytes)); +} + +pub fn read_private_key_and_generate_public() -> String { + // Step 1: Read the private key from the file + let mut file = File::open("./app.secp").expect("file not found"); + let mut private_key_hex = String::new(); + let _ = file.read_to_string(&mut private_key_hex); + + // Step 2: Convert the hexadecimal private key to bytes + let private_key_bytes = hex::decode(private_key_hex.trim()).expect("Invalid hex string"); + + // Step 3: Generate the public key using secp256k1 + let secp = Secp256k1::new(); + let sk = SecretKey::from_slice(&private_key_bytes).expect("32 bytes, within curve order"); + let pk = PublicKey::from_secret_key(&secp, &sk); + + // Convert the public key to uncompressed and compressed formats + let uncompressed_public_key = hex::encode(pk.serialize_uncompressed()); + uncompressed_public_key } + +pub fn sign_message_hash(market_id: String) -> String { + // Generate a random wallet (private key) + let mut file = File::open("./app.secp").expect("file not found"); + let mut private_key_hex = String::new(); + let _ = file.read_to_string(&mut private_key_hex); + + // Initialize the wallet from the private key + let wallet: LocalWallet = private_key_hex.parse().expect("Invalid private key"); + + // Example message + let message = market_id; + + // Create a Keccak-256 hash of the message + let message_hash = keccak256(&message); + + let signature: Signature = wallet + .sign_hash(ethers::types::TxHash(message_hash)) + .unwrap(); + + signature_to_str(signature) + // Concatenate the hexadecimal strings + // let signature_hex = format!("{}{}{}", r_hex, s_hex, v_hex); +} + +pub fn signature_to_str(signature: Signature) -> String { + let r_hex = <[u8; 32]>::try_from(signature.r).unwrap(); + let s_hex = <[u8; 32]>::try_from(signature.s).unwrap(); + let v_hex = signature.v.to_string(); + + let signature_hex = format!("{}{}{}", hex::encode(r_hex), hex::encode(s_hex), v_hex); + signature_hex +} + + +#[cfg(test)] +mod tests { + + use ethers::types::U256; + use openssl::base64; + + use crate::secret_inputs_helpers::{self, decrypt_data_with_ecies_and_aes, encrypt_data_with_ecies_and_aes, SecretData}; + use std::{fs::File, io::Read}; + + use super::read_private_key_and_generate_public; + #[tokio::test] + async fn key_generation(){ + let public_key = read_private_key_and_generate_public(); + let data = "some_data".to_string(); + let public_key_bytes = hex::decode(public_key.trim()).expect("Invalid hex string"); + let secret_data: SecretData = encrypt_data_with_ecies_and_aes(&public_key_bytes, &data.clone().into_bytes()).unwrap(); + // Access the fields using dot notation + println!("data {:?}",&data.clone().into_bytes()); + println!("Encrypted data: {:?}", hex::encode(&secret_data.encrypted_data)); + println!("ACL data: {:?}", hex::encode(&secret_data.acl_data)); + println!("len{:?}", public_key_bytes); + let str1 = hex::encode(&secret_data.encrypted_data); + let str2 = hex::encode(&secret_data.acl_data); + + let mut file = File::open("./app.secp").expect("file not found"); + let mut private_key_hex = String::new(); + let _ = file.read_to_string(&mut private_key_hex); + let market_id_u256: U256 = U256::from_dec_str(&"1").expect("Failed to parse string"); + // Step 2: Convert the hexadecimal private key to bytes + let private_key_bytes = hex::decode(private_key_hex.trim()).expect("Invalid hex string"); + let decrypted_data = decrypt_data_with_ecies_and_aes(&hex::decode(str1).expect(""),&hex::decode(str2).expect(""), &private_key_bytes,market_id_u256).unwrap(); + println!("ACL data: {:?}", String::from_utf8_lossy(&decrypted_data)); + + let encrypted_ecies_data = + secret_inputs_helpers::encrypt_ecies(&data.into_bytes(),&public_key_bytes) + .unwrap(); + println!("ACL data: {:?}", String::from_utf8_lossy(&decrypted_data)); + } +} \ No newline at end of file diff --git a/tools/secret_inputs_helpers.rs b/tools/secret_inputs_helpers.rs new file mode 100644 index 0000000..a0e59de --- /dev/null +++ b/tools/secret_inputs_helpers.rs @@ -0,0 +1,324 @@ +use aes_gcm::KeyInit; +use aes_gcm::{ + aead::{Aead, Payload}, + Aes256Gcm, Key, Nonce, +}; +use ecies::{decrypt, encrypt}; +use ethers::core::types::U256; +use openssl::rand; +use openssl::rand::rand_bytes; +use openssl::symm; +use openssl::symm::{Cipher, Crypter, Mode}; +use serde::Serialize; +use std::error::Error; + +#[derive(Serialize)] +pub struct SecretData { + #[allow(unused)] + encrypted_data: Vec, + #[allow(unused)] + acl_data: Vec, +} + +#[allow(unused)] +pub fn decrypt_ecies(receiver_priv: &[u8], msg: &[u8]) -> Result, Box> { + let result = decrypt(receiver_priv, msg).unwrap(); + Ok(result) +} + +#[allow(unused)] +pub fn encrypt_ecies(receiver_pub: &[u8], msg: &[u8]) -> Result, Box> { + let result = encrypt(receiver_pub, msg).unwrap(); + Ok(result) +} + +pub fn decrypt_aes(encrypted_data: &[u8], secret_key: &[u8]) -> Result, Box> { + if encrypted_data.len() <= 16 { + return Err(Box::new(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Invalid encrypted data format.", + ))); + } + + let iv = &encrypted_data[0..16]; + let encrypted_text = &encrypted_data[16..]; + + let cipher = Cipher::aes_256_cbc(); + let mut decrypter = Crypter::new(cipher, Mode::Decrypt, secret_key, Some(iv))?; + let mut decrypted = vec![0; encrypted_text.len() + cipher.block_size()]; + let count = decrypter.update(encrypted_text, &mut decrypted)?; + let rest = decrypter.finalize(&mut decrypted[count..])?; + decrypted.truncate(count + rest); + + Ok(decrypted) +} + +#[allow(unused)] +pub fn decrypt_aes_gcm( + encrypted_data: &[u8], + secret_key: &[u8], + market_id: U256, +) -> Result, Box> { + let iv_length = 12; // GCM recommends a 12-byte IV + let auth_tag_length = 16; // GCM uses a 16-byte authentication tag + let mut aad = vec![0; 32]; // additional athenticated data + let aad = u256_to_u8_vector(market_id); + if encrypted_data.len() <= (iv_length + auth_tag_length) { + return Err(Box::new(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Invalid encrypted data format.", + ))); + } + + let iv = &encrypted_data[0..iv_length]; + let encrypted_text = &encrypted_data[iv_length..encrypted_data.len()]; + + let nonce = Nonce::from_slice(&iv[..]); + let key = Key::::from_slice(&secret_key[..]); + let cipher = aes_gcm::Aes256Gcm::new(&key); + let payload = Payload { + msg: &encrypted_text[..], + aad: &aad[..], + }; + + let decrypted = cipher.decrypt(&nonce, payload); + + match decrypted { + Ok(decrypted) => Ok(decrypted), + Err(_) => Err("Failed to decrypt".into()), + } +} + +pub fn encrypt_aes(data: &[u8], key: &[u8]) -> Result, Box> { + let cipher = symm::Cipher::aes_256_cbc(); + let mut iv = vec![0; 16]; + rand::rand_bytes(&mut iv)?; + let mut encrypter = symm::Crypter::new(cipher, symm::Mode::Encrypt, key, Some(&iv))?; + let mut encrypted = vec![0; data.len() + cipher.block_size()]; + let count = encrypter.update(data, &mut encrypted)?; + let rest = encrypter.finalize(&mut encrypted[count..])?; + encrypted.truncate(count + rest); + + // Concatenate the IV and encrypted data into a single Vec + iv.extend_from_slice(&encrypted); + Ok(iv) +} + +#[allow(unused)] +pub fn encrypt_aes_gcm( + data: &[u8], + key: &[u8], + market_id: U256, +) -> Result, Box> { + // let cipher = symm::Cipher::aes_256_gcm(); + let mut iv = vec![0; 12]; // GCM recommends a 12-byte IV + rand::rand_bytes(&mut iv)?; + + let key = Key::::from_slice(&key[..]); + let cipher = aes_gcm::Aes256Gcm::new(&key); + let nonce = Nonce::from_slice(&iv[..]); + + let mut aad = vec![0; 32]; // additional athenticated data + let add = u256_to_u8_vector(market_id); + + let payload = Payload { + msg: &data[..], + aad: &aad[..], + }; + + let encrypted = cipher.encrypt(&nonce, payload).expect("Decryption failed"); + // let mut encrypter = symm::Crypter::new(cipher, symm::Mode::Encrypt, key, Some(&iv))?; + // let mut encrypted = vec![0; data.len() + cipher.block_size()]; + // let count = encrypter.update(data, &mut encrypted)?; + // let rest = encrypter.finalize(&mut encrypted[count..])?; + // encrypted.truncate(count + rest); + + // // Append the authentication tag to the encrypted data + // let mut auth_tag = vec![0; 16]; + // encrypter.get_tag(&mut auth_tag)?; + + // Concatenate the IV, encrypted data, and authentication tag into a single Vec + iv.extend_from_slice(&encrypted); + // iv.extend_from_slice(&auth_tag); + + Ok(iv) +} + +#[allow(unused)] +pub fn encrypt_data_with_ecies_and_aes( + receiver_pub: &[u8], + data: &[u8], +) -> Result> { + let mut key = vec![0u8; 32]; + rand_bytes(&mut key)?; + + let encrypted_data = encrypt_aes(data, &key).unwrap(); + + let encrypted_secret_key = encrypt(receiver_pub, &key).unwrap(); + + Ok(SecretData { + encrypted_data, + acl_data: encrypted_secret_key, + }) +} + +#[allow(unused)] +pub fn decrypt_data_with_ecies_and_aes( + encrypted_data: &[u8], + acl_data: &[u8], + private_key: &[u8], + market_id: U256, +) -> Result, Box> { + let decrypted_secret_key = decrypt(private_key, acl_data); + match decrypted_secret_key { + Ok(secret_key) => { + let decrypted_data = try_decrypt(encrypted_data, &secret_key, market_id).unwrap(); + + Ok(decrypted_data) + } + Err(_) => Err("Invalid ecies key used".into()), + } +} + +pub fn try_decrypt( + encrypted_data: &[u8], + secret_key: &[u8], + market_id: U256, +) -> Result, Box> { + decrypt_aes_gcm(encrypted_data, secret_key, market_id) + .or_else(|_| decrypt_aes(encrypted_data, secret_key)) +} + +pub fn u256_to_u8_vector(u256_num: U256) -> Vec { + let mut result = Vec::with_capacity(32); // U256 is 32 bytes in size + for i in (0..32).rev() { + result.push((u256_num >> (i * 8)).low_u64() as u8); + } + let first_non_zero_index = result.iter().position(|&x| x != 0).unwrap_or(result.len()); + result.drain(0..first_non_zero_index); + result +} + +#[cfg(test)] +mod tests { + use super::{ + decrypt_aes, decrypt_aes_gcm, decrypt_ecies, encrypt_aes, encrypt_aes_gcm, encrypt_ecies, + }; + use ecies::{PublicKey, SecretKey}; + use ethers::core::types::U256; + + #[test] + fn test_key() { + let private_key_string = "ca9cbf143a43e422a307b03ec61a82ce99c053290c3053655d0ad69e863a18c4"; + let private_key = hex::decode(private_key_string).unwrap(); + let private_key: &[u8; 32] = private_key.as_slice().try_into().unwrap(); + let sk = SecretKey::parse(private_key).unwrap(); + + let public_key = PublicKey::from_secret_key(&sk); + let public_key = public_key.serialize_compressed(); + + let decoded_vec = + hex::decode("039e61f849ca3a47c90bbb2d387e612e85c54c460286ddbf6ee339526c3dbdee39") + .expect("Failed to decode hex string"); + + // Convert Vec to [u8; 33] + let expected_key: [u8; 33] = decoded_vec.try_into().expect("Length mismatch"); + + assert_eq!(public_key, expected_key); + } + + #[test] + fn test_cipher_enc() { + let private_key_string = "ca9cbf143a43e422a307b03ec61a82ce99c053290c3053655d0ad69e863a18c4"; + let private_key = hex::decode(private_key_string).unwrap(); + let private_key: &[u8; 32] = private_key.as_slice().try_into().unwrap(); + let sk = SecretKey::parse(private_key).unwrap(); + + let public_key = PublicKey::from_secret_key(&sk); + let public_key = public_key.serialize_compressed(); + + let cipher = "0000111100001111000011110000111100001111000011110000111100001111"; + let cipher = hex::decode(cipher).unwrap(); + let encrypted_cipher = encrypt_ecies(&public_key, &cipher).unwrap(); + + let encrypted_cipher = hex::encode(encrypted_cipher).to_string(); + dbg!(encrypted_cipher); + } + + #[test] + fn test_cipher_dec() { + let encrypted_cipher = "0438f743cfbb1f980640ccdbe156f84ebccbf7eb10423e5b7a29ef0efc1d41e5bfa2484e95cf6d819c7778d06cb9ea0461ea3fa0d9119fc41f6fe80e66e9feb37fa08d9cd5524956bd7b718d6ffb9f74636336daa6590a05d1063ee24f1d6db0cc78c84e5337f3cbd4a865a90ea1e047a0e2ae5beeb2576c00e4cae8363d051b71"; + let encrypted_cipher = hex::decode(encrypted_cipher).unwrap(); + let private_key_string = "ca9cbf143a43e422a307b03ec61a82ce99c053290c3053655d0ad69e863a18c4"; + let private_key = hex::decode(private_key_string).unwrap(); + let private_key: &[u8; 32] = private_key.as_slice().try_into().unwrap(); + + let cipher = decrypt_ecies(private_key, &encrypted_cipher).unwrap(); + let cipher = hex::encode(cipher).to_string(); + let expected = "0000111100001111000011110000111100001111000011110000111100001111"; + + assert_eq!(cipher, expected); + } + + #[test] + fn test_aes_enc() { + let data = b"this is the data that we wish to encrypt"; + + let cipher = "0000111100001111000011110000111100001111000011110000111100001111"; + let cipher = hex::decode(cipher).unwrap(); + + let encrypted_aes_data = encrypt_aes(data, &cipher).unwrap(); + + let encrypted_aes_data = hex::encode(encrypted_aes_data).to_string(); + + dbg!(encrypted_aes_data); + } + + #[test] + fn test_aes_dec() { + let expected_data = b"this is the data that we wish to encrypt"; + let encrypted_data = "8b276aad40ba5572ec11516388b0ab3dec11ae4ce6488a7dfad93a4f40429befe58098a6b2a4a316d6654fd14f7eac8c9517046312a9b659d9902bbff41e75fe"; + let encrypted_data = hex::decode(encrypted_data).unwrap(); + + let cipher = "0000111100001111000011110000111100001111000011110000111100001111"; + let cipher = hex::decode(cipher).unwrap(); + + let fetched_data = decrypt_aes(&encrypted_data, &cipher).unwrap(); + + let expected_data = hex::encode(expected_data).to_string(); + let fetched_data = hex::encode(fetched_data).to_string(); + assert_eq!(expected_data, fetched_data); + } + + #[test] + fn test_aes_gcm_enc() { + let data = b"this is the data that we wish to encrypt"; + + let cipher = "0000111100001111000011110000111100001111000011110000111100001111"; + let cipher = hex::decode(cipher).unwrap(); + let market_id = U256::from(1234567890); + + let encrypted_aes_data = encrypt_aes_gcm(data, &cipher, market_id).unwrap(); + + let encrypted_aes_data = hex::encode(encrypted_aes_data).to_string(); + + dbg!(encrypted_aes_data); + } + + #[test] + fn test_aes_gcm_dec() { + let expected_data = b"this is the data that we wish to encrypt"; + let encrypted_data = "c80bbd5590cac0d3ee6a1586473539242711d3fcd1f9ea871e9efdbe07896081c37b5124e0dcc6c50bcb0d46f798f5f0bf4d31310fd7b5508277b041ced1f6ae4c1a6eeb"; + let encrypted_data = hex::decode(encrypted_data).unwrap(); + let market_id = U256::from(1234567890); + + let cipher = "0000111100001111000011110000111100001111000011110000111100001111"; + let cipher = hex::decode(cipher).unwrap(); + + let fetched_data = decrypt_aes_gcm(&encrypted_data, &cipher, market_id).unwrap(); + + let expected_data = hex::encode(expected_data).to_string(); + let fetched_data = hex::encode(fetched_data).to_string(); + assert_eq!(expected_data, fetched_data); + } +}