From c8d6af32e9bedc896f4267c724e4ca551de4459e Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Fri, 15 Mar 2024 15:10:30 +0100 Subject: [PATCH 01/90] add .gitignore --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8100c14 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +target/ +pkg/ +Cargo.lock +node_modules/ +dist/ From 320a2cd5bbd2becc424d4fd665c5966839bc20a0 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Thu, 15 Feb 2024 17:44:25 +0100 Subject: [PATCH 02/90] generate new key, new client, get address --- Cargo.toml | 22 ++++++++++++++++++++++ src/api.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 71 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/api.rs create mode 100644 src/lib.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..6a6eee5 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "sdk_client" +version = "0.1.0" +edition = "2021" + +[lib] +name = "sdk_client" +crate-type = ["cdylib"] + +[dependencies] +sp_backend = { git = "https://github.com/Sosthene00/sp-backend", branch = "sp_client" } +anyhow = "1.0" +serde = { version = "1.0.188", features = ["derive"] } +serde_json = "1.0" +wasm-bindgen = "0.2.91" +getrandom = { version="0.2.12", features = ["js"] } +wasm-logger = "0.2.0" +rand = "0.8.5" +log = "0.4.6" + +[dev-dependencies] +wasm-bindgen-test = "0.3" diff --git a/src/api.rs b/src/api.rs new file mode 100644 index 0000000..b24c4a1 --- /dev/null +++ b/src/api.rs @@ -0,0 +1,48 @@ +use rand::Rng; + +use wasm_bindgen::prelude::*; + +use sp_backend::spclient::{derive_keys_from_seed, SpClient}; +use sp_backend::silentpayments::sending::SilentPaymentAddress; +use sp_backend::spclient::SpendKey; + +const IS_TESTNET: bool = true; + +#[wasm_bindgen] +pub fn setup() { + wasm_logger::init(wasm_logger::Config::default()); +} + +#[wasm_bindgen] +pub fn new_key() -> Vec { + let mut seed = [0u8; 64]; + rand::thread_rng().fill(&mut seed); + seed.to_vec() +} + +#[wasm_bindgen] +pub fn clear_key(key: Vec) { + for mut b in key { + b = 0; + assert!(b == 0u8); + } +} + +#[wasm_bindgen] +pub fn generate_sp_wallet_from_key(birthday: u32, is_testnet: bool) -> Option { + let mut seed = [0u8;64]; + seed.copy_from_slice(&new_key()); + let (scan_sk, spend_sk) = derive_keys_from_seed(&seed, is_testnet).ok()?; + let sp_client = SpClient::new("".to_owned(), scan_sk, SpendKey::Secret(spend_sk), None, birthday, IS_TESTNET).ok()?; + log::info!( + "Created client for sp with address: {}", + sp_client.get_receiving_address() + ); + serde_json::to_string(&sp_client).ok() +} + +#[wasm_bindgen] +pub fn get_receiving_address(sp_client: String) -> String { + let sp_client: SpClient = serde_json::from_str(&sp_client).unwrap(); + sp_client.get_receiving_address() +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..e5fdf85 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +pub mod api; From 170e3c5bf5367456aa212b7b9c76a1018bca588b Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Mon, 18 Mar 2024 15:40:39 +0100 Subject: [PATCH 03/90] Add typescript/webpack boilerplates --- Cargo.toml | 27 +- crates/sp_client/Cargo.toml | 22 + {src => crates/sp_client/src}/api.rs | 21 +- {src => crates/sp_client/src}/lib.rs | 0 package-lock.json | 4476 ++++++++++++++++++++++++++ package.json | 23 + tsconfig.json | 110 + webpack.config.js | 39 + 8 files changed, 4684 insertions(+), 34 deletions(-) create mode 100644 crates/sp_client/Cargo.toml rename {src => crates/sp_client/src}/api.rs (76%) rename {src => crates/sp_client/src}/lib.rs (100%) create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 tsconfig.json create mode 100644 webpack.config.js diff --git a/Cargo.toml b/Cargo.toml index 6a6eee5..fc09209 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,22 +1,5 @@ -[package] -name = "sdk_client" -version = "0.1.0" -edition = "2021" - -[lib] -name = "sdk_client" -crate-type = ["cdylib"] - -[dependencies] -sp_backend = { git = "https://github.com/Sosthene00/sp-backend", branch = "sp_client" } -anyhow = "1.0" -serde = { version = "1.0.188", features = ["derive"] } -serde_json = "1.0" -wasm-bindgen = "0.2.91" -getrandom = { version="0.2.12", features = ["js"] } -wasm-logger = "0.2.0" -rand = "0.8.5" -log = "0.4.6" - -[dev-dependencies] -wasm-bindgen-test = "0.3" +[workspace] +resolver = "2" +members = [ + "crates/sp_client" +] diff --git a/crates/sp_client/Cargo.toml b/crates/sp_client/Cargo.toml new file mode 100644 index 0000000..6a6eee5 --- /dev/null +++ b/crates/sp_client/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "sdk_client" +version = "0.1.0" +edition = "2021" + +[lib] +name = "sdk_client" +crate-type = ["cdylib"] + +[dependencies] +sp_backend = { git = "https://github.com/Sosthene00/sp-backend", branch = "sp_client" } +anyhow = "1.0" +serde = { version = "1.0.188", features = ["derive"] } +serde_json = "1.0" +wasm-bindgen = "0.2.91" +getrandom = { version="0.2.12", features = ["js"] } +wasm-logger = "0.2.0" +rand = "0.8.5" +log = "0.4.6" + +[dev-dependencies] +wasm-bindgen-test = "0.3" diff --git a/src/api.rs b/crates/sp_client/src/api.rs similarity index 76% rename from src/api.rs rename to crates/sp_client/src/api.rs index b24c4a1..5aba703 100644 --- a/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -3,7 +3,6 @@ use rand::Rng; use wasm_bindgen::prelude::*; use sp_backend::spclient::{derive_keys_from_seed, SpClient}; -use sp_backend::silentpayments::sending::SilentPaymentAddress; use sp_backend::spclient::SpendKey; const IS_TESTNET: bool = true; @@ -13,7 +12,6 @@ pub fn setup() { wasm_logger::init(wasm_logger::Config::default()); } -#[wasm_bindgen] pub fn new_key() -> Vec { let mut seed = [0u8; 64]; rand::thread_rng().fill(&mut seed); @@ -21,15 +19,7 @@ pub fn new_key() -> Vec { } #[wasm_bindgen] -pub fn clear_key(key: Vec) { - for mut b in key { - b = 0; - assert!(b == 0u8); - } -} - -#[wasm_bindgen] -pub fn generate_sp_wallet_from_key(birthday: u32, is_testnet: bool) -> Option { +pub fn generate_sp_wallet(birthday: u32, is_testnet: bool) -> Option { let mut seed = [0u8;64]; seed.copy_from_slice(&new_key()); let (scan_sk, spend_sk) = derive_keys_from_seed(&seed, is_testnet).ok()?; @@ -38,7 +28,14 @@ pub fn generate_sp_wallet_from_key(birthday: u32, is_testnet: bool) -> Option=10.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz", + "integrity": "sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.23.tgz", + "integrity": "sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", + "dev": true + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.56.3", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.3.tgz", + "integrity": "sha512-PvSf1wfv2wJpVIFUMSb+i4PvqNYkB9Rkp9ZDO3oaWzq4SKhsQk4mrMBr3ZH06I0hKrVGLBacmgl8JM4WVjb9dg==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.43", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz", + "integrity": "sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.11.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz", + "integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.9.11", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", + "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001589", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001589.tgz", + "integrity": "sha512-vNQWS6kI+q6sBlHbh71IIeC+sRwK2N3EDySc/updIGhIee2x5z00J4c1242/5/d6EpEMdOnk/m+6tuk4/tcsqg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "dev": true, + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.682", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.682.tgz", + "integrity": "sha512-oCglfs8yYKs9RQjJFOHonSnhikPK3y+0SvSYc/YpYJV//6rqc0/hbwd0c7vgK4vrl6y2gJAwjkhkSGWK+z4KRA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/envinfo": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.1.tgz", + "integrity": "sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-entities": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", + "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", + "dev": true, + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-network-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.0.1.tgz", + "integrity": "sha512-OwQXkwBJeESyhFw+OumbJVD58BFBJJI5OM5S1+eyrDKlgDZPX2XNT5gXS56GSD3NPbbwUuMlR1Q71SRp5SobuQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/launch-editor": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", + "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", + "dev": true, + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.7.7.tgz", + "integrity": "sha512-x9qc6k88J/VVwnfTkJV8pRRswJ2156Rc4w5rciRqKceFDZ0y1MqsNL9pkg5sE0GOcDzZYbonreALhaHzg1siFw==", + "dev": true, + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">= 4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/open/-/open-10.0.4.tgz", + "integrity": "sha512-oujJ/FFr7ra6/7gJuQ4ZJJ8Gf2VHM0J3J/W7IvH++zaqEzacWVxzK++NiVY5NLHTTj7u/jNH5H3Ei9biL31Lng==", + "dev": true, + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", + "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", + "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy-transport/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/spdy/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.28.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.28.1.tgz", + "integrity": "sha512-wM+bZp54v/E9eRRGXb5ZFDvinrJIOaTapx3WUokyVGZu5ucVCK55zEgGd5Dl2fSr3jUo5sDiERErUWLY6QPFyA==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-loader/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/webpack": { + "version": "5.90.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", + "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.0.0.tgz", + "integrity": "sha512-tZ5hqsWwww/8DislmrzXE3x+4f+v10H1z57mA2dWFrILb4i3xX+dPhTkcdR0DLyQztrhF2AUmO5nN085UYjd/Q==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^4.6.0", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.2.tgz", + "integrity": "sha512-IVj3qsQhiLJR82zVg3QdPtngMD05CYP/Am+9NG5QSl+XwUR/UPtFwllRBKrMwM9ttzFsC6Zj3DMgniPyn/Z0hQ==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.4.0", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "rimraf": "^5.0.5", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^7.0.0", + "ws": "^8.16.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-server/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..0e1084a --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "sdk_client", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build_wasm": "wasm-pack build --out-dir ../../dist/pkg ./crates/sp_client --target bundler", + "start": "webpack serve", + "build": "webpack" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "html-webpack-plugin": "^5.6.0", + "ts-loader": "^9.5.1", + "typescript": "^5.3.3", + "webpack": "^5.90.3", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.2" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..cb1723c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,110 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "ES2017", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "ESNext", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "include": ["./src/**/*"] +} diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..be13690 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,39 @@ +const path = require('path'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); + +module.exports = { + mode: 'development', + entry: './src/index.ts', + devtool: 'inline-source-map', + experiments: { + asyncWebAssembly: true, + }, + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/, + }, + { + test: /\.wasm$/, + type: 'webassembly/async', + } + ], + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + }, + output: { + filename: 'index.js', + path: path.resolve(__dirname, 'dist'), + }, + plugins: [ + new HtmlWebpackPlugin({ + template: 'src/index.html' + }), + ], + devServer: { + static: './dist', + }, +}; From bfad95dd256cf74f403f0ef2efd735a47b8bcfd0 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Mon, 18 Mar 2024 15:46:31 +0100 Subject: [PATCH 04/90] Add sp_wallet creation in ts --- src/database.ts | 134 ++++++++++++++++++++++++++++++++++++++++++++++++ src/index.html | 10 ++++ src/index.ts | 15 ++++++ src/services.ts | 49 ++++++++++++++++++ 4 files changed, 208 insertions(+) create mode 100644 src/database.ts create mode 100644 src/index.html create mode 100644 src/index.ts create mode 100644 src/services.ts diff --git a/src/database.ts b/src/database.ts new file mode 100644 index 0000000..3d078c5 --- /dev/null +++ b/src/database.ts @@ -0,0 +1,134 @@ +class Database { + private static instance: Database; + private db: IDBDatabase | null = null; + private dbName: string = '4nk'; + private dbVersion: number = 1; + private storeDefinitions = { + SpClient: { + name: "sp_client", + options: {} + }, + AnkUser: { + name: "4nkUser", + options: {} + }, + AnkSession: { + name: "4nkSession", + options: {} + }, + AnkProcess: { + name: "4nkProcess", + options: {} + } + } + + // Private constructor to prevent direct instantiation from outside + private constructor() {} + + // Method to access the singleton instance of Database + public static async getInstance(): Promise { + if (!Database.instance) { + Database.instance = new Database(); + await Database.instance.init(); + } + return Database.instance; + } + + // Initialize the database + private async init(): Promise { + return new Promise((resolve, reject) => { + const request = indexedDB.open(this.dbName, this.dbVersion); + + request.onupgradeneeded = () => { + const db = request.result; + + Object.values(this.storeDefinitions).forEach(({name, options}) => { + if (!db.objectStoreNames.contains(name)) { + db.createObjectStore(name, options); + } + }); + }; + + request.onsuccess = (event) => { + this.db = request.result; + resolve(); + }; + + request.onerror = (event) => { + console.error("Database error:", request.error); + reject(request.error); + }; + }); + } + + public getDb(): IDBDatabase { + if (!this.db) { + throw new Error("Database not initialized"); + } + return this.db; + } + + public getStoreList(): {[key: string]: string} { + const objectList: {[key: string]: string} = {}; + Object.keys(this.storeDefinitions).forEach(key => { + objectList[key] = this.storeDefinitions[key as keyof typeof this.storeDefinitions].name; + }); + return objectList; + } + + public writeObject(db: IDBDatabase, storeName: string, obj: any, key: string | null): Promise { + return new Promise((resolve, reject) => { + const transaction = db.transaction(storeName, 'readwrite'); + const store = transaction.objectStore(storeName); + let request: IDBRequest; + if (key) { + request = store.add(obj, key); + } else { + request = store.add(obj); + } + + request.onerror = () => reject(request.error); + request.onsuccess = () => resolve(request.result); + }); + } + + public getObject(db: IDBDatabase, storeName: string, key: string | number): Promise { + return new Promise((resolve, reject) => { + const transaction = db.transaction(storeName, 'readonly'); + const store = transaction.objectStore(storeName); + const request = store.get(key); + + request.onerror = () => reject(request.error); + request.onsuccess = () => resolve(request.result); + }); + } + + public setObject(db: IDBDatabase, storeName: string, obj: any, key: string | null): Promise { + return new Promise((resolve, reject) => { + const transaction = db.transaction(storeName, 'readwrite'); + const store = transaction.objectStore(storeName); + let request: IDBRequest; + if (key) { + request = store.put(obj, key); + } else { + request = store.put(obj); + } + + request.onerror = () => reject(request.error); + request.onsuccess = () => resolve(request.result); + }); + } + + public getAll(db: IDBDatabase, storeName: string): Promise { + return new Promise((resolve, reject) => { + const transaction = db.transaction(storeName, 'readonly'); + const store = transaction.objectStore(storeName); + const request = store.getAll(); + + request.onerror = () => reject(request.error); + request.onsuccess = () => resolve(request.result); + }); + } +} + +export default Database; diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..00b59c8 --- /dev/null +++ b/src/index.html @@ -0,0 +1,10 @@ + + + + + + 4NK Client + + + + diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..257166f --- /dev/null +++ b/src/index.ts @@ -0,0 +1,15 @@ +import Services from './services'; +import IndexedDB from './database' + +document.addEventListener('DOMContentLoaded', async () => { + try { + const services = await Services.getInstance(); + const indexedDB = await IndexedDB.getInstance(); + + const db = indexedDB.getDb(); + await indexedDB.writeObject(db, indexedDB.getStoreList().SpClient, services.new_sp_client(), "default"); + } catch (error) { + console.error(error); + } +}); + diff --git a/src/services.ts b/src/services.ts new file mode 100644 index 0000000..ae9eafd --- /dev/null +++ b/src/services.ts @@ -0,0 +1,49 @@ +import IndexedDB from './database' + +class Services { + private static instance: Services; + private sdkClient: any; + + // Private constructor to prevent direct instantiation from outside + private constructor() {} + + // Method to access the singleton instance of Services + public static async getInstance(): Promise { + if (!Services.instance) { + Services.instance = new Services(); + await Services.instance.init(); + } + return Services.instance; + } + + // The init method is now part of the instance, and should only be called once + private async init(): Promise { + this.sdkClient = await import("../dist/pkg/sdk_client"); + this.sdkClient.setup(); + } + + public new_sp_client(): string { + return this.sdkClient.generate_sp_wallet(); + } + + public async getSpAddressDefaultClient(): Promise { + try { + const indexedDB = await IndexedDB.getInstance(); + const db = indexedDB.getDb(); + const spClient = await indexedDB.getObject(db, indexedDB.getStoreList().SpClient, "default"); + + if (spClient) { + return this.sdkClient.get_receiving_address(spClient); + } else { + console.error("SP client not found"); + return null; + } + } catch (error) { + console.error("Failed to retrieve object or get sp address:", error); + return null; + } + + } +} + +export default Services; From 59bbfafbb7d808ae1d9ed529cc3116ed8a914eed Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 20 Mar 2024 14:40:51 +0100 Subject: [PATCH 05/90] Update to last sp_backend api --- crates/sp_client/src/api.rs | 38 +++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 5aba703..b1f6ad3 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -1,41 +1,63 @@ use rand::Rng; +use sp_backend::silentpayments::sending::SilentPaymentAddress; use wasm_bindgen::prelude::*; -use sp_backend::spclient::{derive_keys_from_seed, SpClient}; use sp_backend::spclient::SpendKey; +use sp_backend::spclient::{derive_keys_from_seed, SpClient, OutputList}; const IS_TESTNET: bool = true; +#[wasm_bindgen] +pub struct GenerateSpWalletReturn { + sp_client_json: String, + sp_outputs_json: String, +} + #[wasm_bindgen] pub fn setup() { wasm_logger::init(wasm_logger::Config::default()); } -pub fn new_key() -> Vec { +fn new_key() -> Vec { let mut seed = [0u8; 64]; rand::thread_rng().fill(&mut seed); seed.to_vec() } #[wasm_bindgen] -pub fn generate_sp_wallet(birthday: u32, is_testnet: bool) -> Option { - let mut seed = [0u8;64]; +pub fn generate_sp_wallet(birthday: u32, is_testnet: bool) -> Option { + let mut seed = [0u8; 64]; seed.copy_from_slice(&new_key()); let (scan_sk, spend_sk) = derive_keys_from_seed(&seed, is_testnet).ok()?; - let sp_client = SpClient::new("".to_owned(), scan_sk, SpendKey::Secret(spend_sk), None, birthday, IS_TESTNET).ok()?; + let sp_client = SpClient::new( + "".to_owned(), + scan_sk, + SpendKey::Secret(spend_sk), + None, + IS_TESTNET, + ) + .ok()?; + let our_address: SilentPaymentAddress = sp_client.get_receiving_address().try_into().ok()?; log::info!( "Created client for sp with address: {}", - sp_client.get_receiving_address() + our_address.to_string() ); // zero out the seed for mut b in seed.into_iter() { b = 0; assert!(b == 0); // this guarantee that the compiler won't optimize it away } - let json = serde_json::to_string(&sp_client).ok(); + let sp_client_json = serde_json::to_string(&sp_client).ok()?; + + // Generate an empty outputs + let sp_outputs = OutputList::new(our_address.get_scan_key(), our_address.get_spend_key(), birthday); + let sp_outputs_json = serde_json::to_string(&sp_outputs).ok()?; - json + Some(GenerateSpWalletReturn { + sp_client_json, + sp_outputs_json, + }) } #[wasm_bindgen] From 92c77c91e0b6ac50a4e839375ad84ff08a048111 Mon Sep 17 00:00:00 2001 From: franck Date: Wed, 20 Mar 2024 16:03:37 +0100 Subject: [PATCH 06/90] Merge branche webapps dans dev --- crates/sp_client/src/injecteurhtml.rs | 99 +++++++ crates/sp_client/src/lib.rs | 2 + crates/sp_client/src/process.rs | 10 + package.json | 1 + src/assets/4nk_image.png | Bin 0 -> 62845 bytes src/assets/revoke.jpeg | Bin 0 -> 417434 bytes src/database.ts | 6 +- src/index.html | 11 +- src/index.ts | 10 +- src/services.ts | 365 ++++++++++++++++++++++++++ src/store/processstore.ts | 237 +++++++++++++++++ src/store/userstore.ts | 15 ++ src/style/4nk.css | 162 ++++++++++++ webpack.config.js | 7 + 14 files changed, 919 insertions(+), 6 deletions(-) create mode 100644 crates/sp_client/src/injecteurhtml.rs create mode 100644 crates/sp_client/src/process.rs create mode 100644 src/assets/4nk_image.png create mode 100644 src/assets/revoke.jpeg create mode 100644 src/store/processstore.ts create mode 100644 src/store/userstore.ts create mode 100644 src/style/4nk.css diff --git a/crates/sp_client/src/injecteurhtml.rs b/crates/sp_client/src/injecteurhtml.rs new file mode 100644 index 0000000..72e0c73 --- /dev/null +++ b/crates/sp_client/src/injecteurhtml.rs @@ -0,0 +1,99 @@ +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub fn inject_html_create_id() -> String { + String::from(" +
+
+

Create an Id

+ +
+
+ +
+ +
+
+ +
+ Recover +
+
+

+
+
+ ") +} + +#[wasm_bindgen] +pub fn inject_html_recover() -> String { + String::from(" +
+
+

Recover my Id

+ +
+
+ + + +
+
+ + +

+ Revoke +

+
+
+ ") +} + +#[wasm_bindgen] +pub fn inject_html_revokeimage() -> String { + String::from(" +
+
+ + +
+
+ + +
+
+ ") +} + +#[wasm_bindgen] +pub fn inject_html_revoke() -> String { + String::from(" +
+
+

Revoke an Id

+
+ Recover +
+
+
+ + +
+
+ + +
+
+ +
+
+ ") +} diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index e5fdf85..0ce9757 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -1 +1,3 @@ pub mod api; +mod injecteurhtml; +mod process; diff --git a/crates/sp_client/src/process.rs b/crates/sp_client/src/process.rs new file mode 100644 index 0000000..e4daebb --- /dev/null +++ b/crates/sp_client/src/process.rs @@ -0,0 +1,10 @@ +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub fn get_process() -> Vec { + let mut data_process: Vec = Vec::new(); + data_process.push(String::from("process1")); + data_process.push(String::from("process2")); + data_process.push(String::from("process3")); + data_process +} \ No newline at end of file diff --git a/package.json b/package.json index 0e1084a..6dabb0b 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "author": "", "license": "ISC", "devDependencies": { + "copy-webpack-plugin": "^12.0.2", "html-webpack-plugin": "^5.6.0", "ts-loader": "^9.5.1", "typescript": "^5.3.3", diff --git a/src/assets/4nk_image.png b/src/assets/4nk_image.png new file mode 100644 index 0000000000000000000000000000000000000000..d58693f1a03d4e31009b72cd8a21769440200b07 GIT binary patch literal 62845 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 {$}MQW_^l(qxpSD2GMwwu9V z6aX&IJW_mIt{N6OwNa8uI#$ z%#@h>hx`h~*bykti7m1N)XWvBErQ2~akl{m$v!3w(@kL?7LF0Jq(|wfqv8LQ&*NQU z3{-INH>`C=QP1rq<0l(EJ-Kz2%mL+v()6Tu)jFl@A()=znXy}dJIA?T3C4wIy7aue zT~so&p}IehF7~8 zo}{_V8J9*x&pX2BkrHt7pUomDuZR(>{mfxS7Y0@7ZG7gc61OE1>bBKcu_t-=%3s#q zb;in*xG*(u;iPN2}o33?KkP|~J2K=k?bPRGEf{`v%2hJaqU9cTHS-Nd0abSGS>@u0C; zgwy6`*70{_!-UuAPjrW2-3lEey!5nlts3&VuWcF#n0mMKSF7HQjwD}*Ih@lP|LgKP z)BflhXW3QyqZ!Sp`)KGzef10NldtpFE!p#{hC3u<+59 zNmHj^+g-WX^U4S{)A!jeC;$SGJo|ukG912p@7A`meIzR?o%tc~Tbs#v++*e5$`b zjvVhwfkZ5L16N4H_Yo5OEOTF5XAUQe8YfQ(ZpcFL9{=t&B)S|0_U;^~G% zxU`Am^)URtjO?Z2n*FWg3Hf9$q|?RrnJ3pE=;P}sNRZHL&Gxh!w#{yY_L@**gPFqM z?!ZYQP7BH}Rpp(O>V?3*#j+wJ!kXlo-1f7VJ^`}giT6ZrTd_?>DCutYg9_&o;be>$8UYCa)E`mzCreV%OdWApIMC`PQ2d=2QD$i5 zP}>)wMLgb$P*W^4?pVuc4!meFZ?+NM!pN++Dy#AdtiSxw{v# z%*v&s1}w#Z5-0ay`UdZ96~-X@*>W~D6b4{Musq? zPzOMt1P!p1fq%qeaSi|!jR4rdc)X4{A|S=_7_bV9@m)28VGOH-(te&{Q}oO3S#Jm? zz6{97#Zs|0L=p>V$12EuVEps%QnlCg+=Ln!YOC)-UGnC0@Q8E7KfR(u!Nx1eok2rl zkzv{*YY1$^{HZg=Y@4Ymz%&QP~Ml7jjtm_Tpo5ZM&iMnE&&^P;lXM(;9D3@h9lZ~jI zp#cmS2e3mJbsfu=v+a@g>!;%NAu+qoy5@^$(L}CpgWHrhq9i}m(rd$&#^LJju(*1v zI82rYa6zP_OU_1u-SmGuCPYxAsh$gliNK&B%ag$qs5f zdS3Qz4W$62{v5=n=1Vu6j1~hE{N;51K3Y0w8WScNkO3q7WrlHFpa8Y`4bfPNLo0N{L=6FlgK1Rfb|se}oDiah@4TTi z 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

+@)5|iq+U$^hmz4d2yc$O}pnte6Nib zdL{;uqqQeS%^_BF_G0r7!Xj z0dvfmJcm^NL6#xlHQcavev_#%t)IE5xyIA=sIZnWzGqHvF-oH;@~ap_c%P_QeKhVP zvr?IKm|uj8ZhdY)J zPkd4X`qLm9VYZ~oCS4CZ1l8A&#JWcj*CC*enX9f2J}WEJw>(-BJz@C(XCq&L24~DaplE z-vlFBYU#RwnM-B`^yXh0a}w}wbz79~?FFuQ+=$62MP)_`pl)0EVQ}_w?3hebR4&um zem(91iKsCRr-ef>IDMmt_hu+?xTjW!uRp%z4o7?I1MfHFMAW zN40Ec)`#`O!p@J^fQfC{eCdD%lHSE(B&6q0*2obEpY#E<%|84P0ykmuhC1QqPP=BuaFI;OkS+VKxW-^$nTo&K^P%VeCN zR|@|kV+xIyuCvQgS;j3A8Kg>zdHlp#0o`{GuEb>iMsz;>EY{X^da6LA4U*q5WJ^2dJ>r=eBPLQ!P&lI;f($26v=Vvl z8C`xey~3zd-P0_eScN?w4@9DYJ~CjBHDqifOW7JF#h9c-8dyB7Hk%3eTk&)om}!ngQ0CzoqJA3?VDRPBXi8-E2*?!+%ayaHTwZ75 z2X=$r%(-REFa1FNH3WY`T*|`~HRb(~tEK>9c*Pm~i`kz5SJ>|dv*v&Jzm$2O(0hmA zmWAn**r|FT{aUwhOfcr1VMtgXd~p`>@uf)U!68-*yaSY9GyHb$=0zd@;6c?_7H__=w*p<`z9~0pG%#>a}~!eBN;VZNG1!Hg8I~ zoIXAtmwb@7>UO|F973LhL6%4hsT^e$)FuB$I1UX5qtG(63fYwi#`k5fjhrU>dJUntli-)sZPyH*IMNMjY6Z3h2Z9 z3cFJRb253McB!_r4%Rpr07|I&5ftaBGpjg2ZX1=h;dWlYy^?a31oKJn^%7>Ty2e}cjC zXqnyF2WLcaRGW(~5nZ0lp~(cJkrO}xcz0c;&y}b5wE<|j4l7vmDl@d@T|!$MMdUh# z4qBI^YAfa3e4khKO^u6=Uom(tRe-d}v8+{HwyJ7HhL~~&SLo@K@JdPsJi%P-5`*7ERX?i#XX0qw_PGBxNdu4GR6a} zhXt^!apm_t>nABrE0oXoYF4y0psD56G+Ncn-BC#|MgEjBXtCU;tM@uh5)_Ux61FB! zem184Z0+)!FMUH^+2rBIx8s7bX)B(PFQmTO2DY(i|8<@6X+Gogke!n+0#y)UC2!pR1rPCXb8)058WbpCc?QWZ1if#1^l(GITha#8dA%bm& zq1>`I)uN_7HrYLL!|a^3Z(?ZO|BTDKebb%B zi8CIE++>$Sc}!gD%}Bn;0en-DYF~OgsV3_~rX6t#@y|St^(+X}FAeFG8xB-k-3vNl z|HPRVLlU1UZzGM_hr9#<#vLcX?ho#fyq@B_7l(&$iGEwYf$`^C;@D}w`9d{aAc}cc zWY#``L4AW)9%4S2cJLWjSMkT<^$^w`#?QO_5-!GXnLyG!IOHQS@3N_v^>hxL$MsSC~2cQbHLHZ3E&%5B63*jlSQL5 zX1>9kuK~I@Zki}TKZ+DObfa-nXuV6t8RMC~!c@LuU2{Rs zwbh2xQZ?#18u{v*xq}D9@T}6&aK>Ky^%(ulsKAf&F+-EG+j4Fje0-@7M{pSAS=h#2-Fd7g+1zOSbbOj6sgX5Z{D z>_qike`O$7zbG`$U~l`M(}F{$)C>=tr88LAu#8^I%7^v9?n_J~#J=sk=22=+qEx2c zj9#nj({%7>QOOX&+EOk?*4o=y7AEO41KsBEwq5ojZzD9W59Fuy1b63{FJ|_6r;gY7+ zP5zTRZG%(Ha z>cV+;ZH9Xbvi-ycxG0*gkdcr%>5a$j0Gj@

kTk`c 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͖| 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 z�|x6L~>>5B2)pk^E3`Ul?k4NQ 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 + + + - 4NK Client + + 4NK Application +

+ +
- + \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 257166f..59e125d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,10 +4,18 @@ import IndexedDB from './database' document.addEventListener('DOMContentLoaded', async () => { try { const services = await Services.getInstance(); - const indexedDB = await IndexedDB.getInstance(); + if ((await services.isNewUser())) { + services.displayCreateId(); + } + else { + services.displayRecover() + } + + const indexedDB = await IndexedDB.getInstance(); const db = indexedDB.getDb(); await indexedDB.writeObject(db, indexedDB.getStoreList().SpClient, services.new_sp_client(), "default"); + } catch (error) { console.error(error); } diff --git a/src/services.ts b/src/services.ts index ae9eafd..da08ff3 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,8 +1,11 @@ import IndexedDB from './database' +import Processstore from './store/processstore'; +import Userstore from './store/userstore'; class Services { private static instance: Services; private sdkClient: any; + private static CURRENT_PROCESS = "currentprocess"; // Private constructor to prevent direct instantiation from outside private constructor() {} @@ -44,6 +47,368 @@ class Services { } } + + public async isNewUser(): Promise { + let isNew = false; + try { + let listUserProcess = await Services.instance.getAllUserProces(); + if (listUserProcess.length == 0) { + isNew = true; + } + } catch (error) { + console.error("Failed to retrieve isNewUser :", error); + } + return isNew; + } + + public async displayCreateId(): Promise { + Services.instance.injectHtml(Services.instance.get_html_create_id()); + Services.instance.attachSubmitListener("form4nk", Services.instance.createId); + Services.instance.attachClickListener("displayrecover", Services.instance.displayRecover); + Services.instance.displayProcess(await Services.instance.getAllProcesAvailable()); + } + + public get_html_create_id(): string { + return this.sdkClient.inject_html_create_id(); + } + + public async createId(event: Event): Promise { + event.preventDefault(); + + const passwordElement = document.getElementById("password") as HTMLInputElement; + const processElement = document.getElementById("selectProcess") as HTMLSelectElement; + + if (!passwordElement || !processElement) { + console.error("One or more elements not found"); + return; + } + + const password = passwordElement.value; + const process = processElement.value; + console.log("JS password: " + password + " process: " + process); + // To comment if test + if (!Services.instance.isPasswordValid(password)) return; + + // TODO get secretpart1 from User object + // const user = new this.sdkClient.User(password); + let secretpart1 = "LKHGKJJJ3H"; + + try { + let userstore = new Userstore; + userstore.secretpart1 = secretpart1; + userstore.process = process; + const indexedDb = await IndexedDB.getInstance(); + const db = indexedDb.getDb(); + + await indexedDb.writeObject(db, indexedDb.getStoreList().AnkUser, userstore, process); + console.log("JS Userstore added"); + + await indexedDb.writeObject(db, indexedDb.getStoreList().AnkSession, process, Services.CURRENT_PROCESS); + console.log("JS Sessionstore added currentprocess"); + } catch (error) { + console.error("Failed to write userstore object :", error); + } + + await Services.instance.displayRevokeImage(); + } + + public async displayRecover(): Promise { + Services.instance.injectHtml(Services.instance.get_html_recover()); + Services.instance.attachSubmitListener("form4nk", Services.instance.recover); + Services.instance.attachClickListener("displaycreateid", Services.instance.displayCreateId); + Services.instance.attachClickListener("displayrevoke", Services.instance.displayRevoke); + Services.instance.attachClickListener("submitButtonRevoke", Services.instance.revoke); + Services.instance.displayProcess(await Services.instance.getAllUserProces()); + } + + public get_html_recover(): string { + return this.sdkClient.inject_html_recover(); + } + + public async recover(event: Event) { + event.preventDefault(); + console.log("JS recover submit "); + + const passwordElement = document.getElementById("password") as HTMLInputElement; + const processElement = document.getElementById("selectProcess") as HTMLSelectElement; + + if (!passwordElement || !processElement) { + console.error("One or more elements not found"); + return; + } + + const password = passwordElement.value; + const process = processElement.value; + console.log("JS password: " + password + " process: " + process); + // To comment if test + if (!Services.instance.isPasswordValid(password)) return; + + // TODO + alert("Recover submit to do ..."); + } + + public async displayRevokeImage(): Promise { + const html = Services.instance.get_html_revokeimage(); + Services.instance.injectHtml(html); + Services.instance.attachSubmitListener("form4nk", Services.instance.revokeimage); + } + + public get_html_revokeimage(): string { + return this.sdkClient.inject_html_revokeimage(); + } + + public async revokeimage(event: Event): Promise { + event.preventDefault(); + console.log("JS revokeimage submit "); + // TODO + alert("Revokeimage submit to do ..., next page Update an id ..."); + + await Services.instance.displayUpdateAnId(); + } + + public async displayRevoke(): Promise { + const html = Services.instance.get_html_revoke(); + Services.instance.injectHtml(html); + Services.instance.attachClickListener("displayrecover", Services.instance.displayRecover); + Services.instance.attachSubmitListener("form4nk", Services.instance.revoke); + } + + public get_html_revoke(): string { + return this.sdkClient.inject_html_revoke(); + } + + public async revoke(event: Event): Promise { + event.preventDefault(); + console.log("JS revoke click "); + // TODO + alert("revoke click to do ..."); + } + + public async displayUpdateAnId() { + let currentProcess = await this.getCurrentProcess(); + + let body = ""; + let style = ""; + let script = ""; + let inputName = ""; + try { + const indexedDB = await IndexedDB.getInstance(); + const db = indexedDB.getDb(); + try { + let processObject = await indexedDB.getObject(db, indexedDB.getStoreList().AnkProcess, currentProcess); + body = processObject.html; + style = processObject.style; + script = processObject.script; + inputName = processObject.inputName; + } catch (error) { + console.log("JS Processstore not exist "); + } + } catch (error) { + console.error("Failed to retrieve userstore object :", error); + } + + Services.instance.injectUpdateAnIdHtml(body, style, script, inputName); + Services.instance.attachSubmitListener("form4nk", Services.instance.updateAnId); + } + + public injectUpdateAnIdHtml(bodyToInject: string, styleToInject: string, scriptToInject: string, inputName: string) { + console.log("JS html : "+bodyToInject); + const body = document.getElementsByTagName('body')[0]; + + if (!body) { + console.error("No body tag"); + return; + } + body.innerHTML = styleToInject + bodyToInject; + + const script = document.createElement("script"); + script.innerHTML = scriptToInject; + document.body.appendChild(script); + script.onload = () => { + console.log('Script loaded successfuly'); + }; + script.onerror = () => { + console.log('Error loading script'); + }; + } + + public async updateAnId(event: Event): Promise { + event.preventDefault(); + + // TODO get values + const firstNameElement = 'firstName'; + const lastNameElement = 'lastName'; + const firstName = document.getElementById(firstNameElement) as HTMLInputElement; + const lastName = document.getElementById(lastNameElement) as HTMLInputElement; + + console.log("JS updateAnId submit "); + // TODO + alert("updateAnId submit to do ... Name : "+firstName.value + " "+lastName.value); + } + + public displayProcess(processList: string[]): void { + console.log("JS processList : "+processList); + const selectProcess = document.getElementById("selectProcess"); + if (selectProcess) { + processList.forEach((process) => { + let child = new Option(process, process); + if (!selectProcess.contains(child)) { + selectProcess.appendChild(child); + } + }) + } + } + + public async getAllUserProces(): Promise { + let userProcessList: string[] = []; + try { + const indexedDB = await IndexedDB.getInstance(); + const db = indexedDB.getDb(); + let userListObject = await indexedDB.getAll(db, indexedDB.getStoreList().AnkUser); + userListObject.forEach(async (userObject) => { + const processName = userObject.process; + userProcessList.push(processName); + console.log("JS Userstore found"); + }) + } catch (error) { + console.log("JS Userstore not found"); + } + return userProcessList; + } + + public async getAllProcesAvailable(): Promise { + let userProcessList = await Services.instance.getAllUserProces(); + let processList = await Services.instance.getAllProces(); + let availableProcessList = processList.filter(x => !userProcessList.includes(x)); + return availableProcessList; + } + + public async getAllProces(): Promise { + // if indexedDB is empty, get list from wasm + let processList: string[] = []; + try { + const indexedDB = await IndexedDB.getInstance(); + const db = indexedDB.getDb(); + let processListObject = await indexedDB.getAll(db, indexedDB.getStoreList().AnkProcess); + processListObject.forEach(async (processObject) => { + const processName = processObject.process; + processList.push(processName); + console.log("JS Processstore found"); + }) + } catch (error) { + console.log("JS Processstore not found"); + } + if (processList.length == 0) { + processList = await this.addProcessStore(); + } + return processList; + } + + public async addProcessStore(): Promise { + const processList = this.sdkClient.get_process() + processList.forEach(async (process: string) => { + // TODO process mock + let processstore = new Processstore; + processstore.process = process; + const indexedDB = await IndexedDB.getInstance(); + const db = indexedDB.getDb(); + await indexedDB.writeObject(db, indexedDB.getStoreList().AnkProcess, processstore, process); + console.log("JS Processstore mock added"); + }) + return processList; + } + + private async getSecretPart1(process: string): Promise { + let secretpart1 = ""; + try { + const indexedDB = await IndexedDB.getInstance(); + const db = indexedDB.getDb(); + try { + let userObject = await indexedDB.getObject(db, indexedDB.getStoreList().AnkUser, process); + secretpart1 = userObject.secretpart1; + console.log("JS Userstore exist secretpart1 : "+secretpart1); + } catch (error) { + console.log("JS Userstore not exist "); + } + } catch (error) { + console.error("Failed to retrieve userstore object :", error); + } + console.log("JS secretpart1 : "+secretpart1); + + return secretpart1; + } + + public attachClickListener(elementId: string, callback: (event: Event) => void): void { + const element = document.getElementById(elementId); + element?.removeEventListener("click", callback); + element?.addEventListener("click", callback); + } + + public attachSubmitListener(elementId: string, callback: (event: Event) => void): void { + const element = document.getElementById(elementId); + element?.removeEventListener("submit", callback); + element?.addEventListener("submit", callback); + } + + public injectHtml(html: string) { + console.log("JS html : "+html); + const container = document.getElementById('containerId'); + + if (!container) { + console.error("No html container"); + return; + } + container.innerHTML = html; + } + + public async getCurrentProcess(): Promise { + let currentProcess = ""; + try { + const indexedDB = await IndexedDB.getInstance(); + const db = indexedDB.getDb(); + currentProcess = await indexedDB.getObject(db, indexedDB.getStoreList().AnkSession, Services.CURRENT_PROCESS); + } catch (error) { + console.error("Failed to retrieve currentprocess object :", error); + } + return currentProcess; + } + + public isPasswordValid(password: string) { + var alertElem = document.getElementById("passwordalert"); + var success = true; + var strength = 0; + if (password.match(/[a-z]+/)) { + var strength = 0; + strength += 1; + } + if (password.match(/[A-Z]+/)) { + strength += 1; + } + if (password.match(/[0-9]+/)) { + strength += 1; + } + if (password.match(/[$@#&!]+/)) { + strength += 1; + } + if (alertElem !== null) { + // TODO Passer à 18 + if (password.length < 4) { + alertElem.innerHTML = "Password size is < 4"; + success = false; + } else { + if (password.length > 30) { + alertElem.innerHTML = "Password size is > 30"; + success = false; + } else { + if (strength < 4) { + alertElem.innerHTML = "Password need [a-z] [A-Z] [0-9]+ [$@#&!]+"; + success = false; + } + } + } + } + return success; + } } export default Services; diff --git a/src/store/processstore.ts b/src/store/processstore.ts new file mode 100644 index 0000000..39cabee --- /dev/null +++ b/src/store/processstore.ts @@ -0,0 +1,237 @@ +class Processstore { + process: string; + html: string; + style: string; + script: string; + inputName: string; + createDate: Date; + + constructor() { + this.process = ""; + this.html = getMockHtml(); + this.style = getMockStyle(); + this.script = getMockScript(); + this.script = getMockScript(); + this.inputName = getMockinputName(); + this.createDate = new Date; + } +} + +export default Processstore; + +function getMockHtml(): string { + let html: string = ` + +
+
+

Update an Id

+
+
+
+ + + + + + + + + + + + + +
+
+ + +
+
+
+ +
+ +
+
+ + `; + return html; +} + +function getMockStyle(): string { + let style: string = ` + `; + return style; +} + +function getMockScript(): string { + let script: string = ` + var addSpAddressBtn = document.getElementById('add-sp-address-btn'); + var removeSpAddressBtn = document.querySelectorAll('.minus-sp-address-btn'); + + addSpAddressBtn.addEventListener('click', function (event) { + addDynamicField(this); + }); + + function addDynamicField(element) { + var addSpAddressBlock = document.getElementById('sp-address-block'); + var spAddress = addSpAddressBlock.querySelector('#sp-address').value; + addSpAddressBlock.querySelector('#sp-address').value = ''; + spAddress = spAddress.trim(); + if (spAddress != '') { + var sideBySideDiv = document.createElement('div'); + sideBySideDiv.className = 'side-by-side'; + + var inputElement = document.createElement('input'); + inputElement.type = 'text'; + inputElement.name = 'spAddresses[]'; + inputElement.setAttribute('form', 'no-form'); + inputElement.value = spAddress; + inputElement.disabled = true; + + var buttonElement = document.createElement('button'); + buttonElement.type = 'button'; + buttonElement.className = + 'circle-btn bg-secondary minus-sp-address-btn'; + buttonElement.innerHTML = '-'; + + buttonElement.addEventListener('click', function (event) { + removeDynamicField(this.parentElement); + }); + + sideBySideDiv.appendChild(inputElement); + sideBySideDiv.appendChild(buttonElement); + + addSpAddressBlock.appendChild(sideBySideDiv); + } + function removeDynamicField(element) { + element.remove(); + } + } + `; + return script; +} + +function getMockinputName(): string { + return "firstName"; +} \ No newline at end of file diff --git a/src/store/userstore.ts b/src/store/userstore.ts new file mode 100644 index 0000000..d450008 --- /dev/null +++ b/src/store/userstore.ts @@ -0,0 +1,15 @@ +class Userstore { + process: string; + secretpart1: string; + password: string; + createDate: Date; + + constructor() { + this.process = ""; + this.secretpart1 = ""; + this.password = ""; + this.createDate = new Date; + } +} + +export default Userstore; diff --git a/src/style/4nk.css b/src/style/4nk.css new file mode 100644 index 0000000..39377bb --- /dev/null +++ b/src/style/4nk.css @@ -0,0 +1,162 @@ +body { + margin: 0; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + min-height: 100vh; + background-color: #f4f4f4; + font-family: 'Arial', sans-serif; +} +.container { + text-align: center; +} +.card { + max-width: 400px; + width: 100%; + padding: 20px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + background-color: #ffffff; + border-radius: 8px; + text-align: left; + overflow: hidden; +} +form { + display: flex; + flex-direction: column; + /* flex-wrap: wrap; */ +} +label { + font-weight: bold; + margin-bottom: 8px; +} +hr { + border: 0; + height: 1px; + background-color: #ddd; + margin: 10px 0; +} +input, select { + width: 100%; + padding: 10px; + margin: 8px 0; + box-sizing: border-box; +} +select { + padding: 10px; + background-color: #f9f9f9; + border: 1px solid #ddd; + border-radius: 4px; + cursor: pointer; +} +button { + display: inline-block; + background-color: #4caf50; + color: #fff; + border: none; + padding: 12px 17px; + border-radius: 4px; + cursor: pointer; +} +button:hover { + background-color: #45a049; +} +.side-by-side { + display: flex; + align-items: center; + justify-content: space-between; +} +.side-by-side>* { + display: inline-block; +} +button.recover { + display: inline-block; + text-align: center; + text-decoration: none; + display: inline-block; + background-color: #4caf50; + color: #fff; + border: none; + padding: 12px 17px; + border-radius: 4px; + cursor: pointer; +} +button.recover:hover { + background-color: #45a049; +} +a.btn { + display: inline-block; + text-align: center; + text-decoration: none; + display: inline-block; + background-color: #4caf50; + color: #fff; + border: none; + padding: 12px 17px; + border-radius: 4px; + cursor: pointer; + } + +a.btn:hover { + background-color: #45a049; +} + +a { + text-decoration: none; + color: #78a6de; +} +.bg-secondary { + background-color: #2b81ed; +} +.bg-primary { + background-color: #1A61ED; +} +.bg-primary:hover { + background-color: #457be8; +} +.card2 { + display: flex; + flex-direction: column; + max-width: 400px; + width: 100%; + padding: 20px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + background-color: #ffffff; + border-radius: 8px; + text-align: center; + align-items: center; + overflow: hidden; +} +.card2 button { + max-width: 50px; + width: 100%; + background: none; + border: none; + cursor: pointer; +} +.card2 svg { + width: 100%; + height: auto; + fill: #333; +} +.image-label { + display: block; + color: #fff; + padding: 5px; + margin-top: 10px; +} +.image-container { + width: 400px; + height: 300px; + overflow: hidden; +} +.image-container img { + text-align: center; + width: 100%; + height: 100%; + object-fit: cover; + object-position: center center; +} +.passwordalert { + color: #FF0000; +} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index be13690..e40143f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,5 +1,6 @@ const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); module.exports = { mode: 'development', @@ -32,6 +33,12 @@ module.exports = { new HtmlWebpackPlugin({ template: 'src/index.html' }), + new CopyWebpackPlugin({ + patterns: [ + { from: 'src/assets', to: './assets' }, + { from: 'src/style', to: './style' } + ], + }), ], devServer: { static: './dist', From 62bee1016638aad6c557591a8a0ae042290ddca6 Mon Sep 17 00:00:00 2001 From: Sosthene00 Date: Thu, 21 Mar 2024 17:09:52 +0100 Subject: [PATCH 07/90] Add tsify fix generate_sp_wallet --- crates/sp_client/Cargo.toml | 1 + crates/sp_client/src/api.rs | 38 +++++++++++++++++-------------------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/crates/sp_client/Cargo.toml b/crates/sp_client/Cargo.toml index 6a6eee5..249e291 100644 --- a/crates/sp_client/Cargo.toml +++ b/crates/sp_client/Cargo.toml @@ -17,6 +17,7 @@ getrandom = { version="0.2.12", features = ["js"] } wasm-logger = "0.2.0" rand = "0.8.5" log = "0.4.6" +tsify = { git = "https://github.com/Sosthene00/tsify", branch = "next" } [dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index b1f6ad3..0628a60 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -1,17 +1,21 @@ use rand::Rng; +use serde::{Deserialize, Serialize}; use sp_backend::silentpayments::sending::SilentPaymentAddress; use wasm_bindgen::prelude::*; +use tsify::Tsify; use sp_backend::spclient::SpendKey; use sp_backend::spclient::{derive_keys_from_seed, SpClient, OutputList}; const IS_TESTNET: bool = true; -#[wasm_bindgen] -pub struct GenerateSpWalletReturn { - sp_client_json: String, - sp_outputs_json: String, +#[derive(Tsify, Serialize, Deserialize)] +#[tsify(into_wasm_abi)] +#[allow(non_camel_case_types)] +pub struct generate_sp_wallet_return { + pub sp_client_json: String, + pub sp_outputs_json: String, } #[wasm_bindgen] @@ -19,19 +23,13 @@ pub fn setup() { wasm_logger::init(wasm_logger::Config::default()); } -fn new_key() -> Vec { +#[wasm_bindgen] +pub fn generate_sp_wallet(label: Option, birthday: u32, is_testnet: bool) -> Option { let mut seed = [0u8; 64]; rand::thread_rng().fill(&mut seed); - seed.to_vec() -} - -#[wasm_bindgen] -pub fn generate_sp_wallet(birthday: u32, is_testnet: bool) -> Option { - let mut seed = [0u8; 64]; - seed.copy_from_slice(&new_key()); let (scan_sk, spend_sk) = derive_keys_from_seed(&seed, is_testnet).ok()?; let sp_client = SpClient::new( - "".to_owned(), + label.unwrap_or("default".into()), scan_sk, SpendKey::Secret(spend_sk), None, @@ -43,21 +41,19 @@ pub fn generate_sp_wallet(birthday: u32, is_testnet: bool) -> Option Date: Thu, 21 Mar 2024 17:10:32 +0100 Subject: [PATCH 08/90] Keep sp_outputs in db --- package-lock.json | 289 ++++++++++++++++++++++++++++++++++++++++++++++ src/database.ts | 35 ++++-- src/index.ts | 5 +- src/services.ts | 5 +- 4 files changed, 323 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1dcf108..2ade8c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "devDependencies": { + "copy-webpack-plugin": "^12.0.2", "html-webpack-plugin": "^5.6.0", "ts-loader": "^9.5.1", "typescript": "^5.3.3", @@ -134,6 +135,41 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", "dev": true }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -144,6 +180,18 @@ "node": ">=14" } }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@types/body-parser": { "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", @@ -1095,6 +1143,95 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true }, + "node_modules/copy-webpack-plugin": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-12.0.2.tgz", + "integrity": "sha512-SNwdBeHyII+rWvee/bTnAYyO8vfVdcSTud4EIb6jcZ8inLeWucJE0DnxXQBjlQ5zlteuuvooGQy3LIyGxhvlOA==", + "dev": true, + "dependencies": { + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.1", + "globby": "^14.0.0", + "normalize-path": "^3.0.0", + "schema-utils": "^4.2.0", + "serialize-javascript": "^6.0.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/copy-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/copy-webpack-plugin/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -1579,6 +1716,22 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -1594,6 +1747,15 @@ "node": ">= 4.9.1" } }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/faye-websocket": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", @@ -1818,6 +1980,26 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "node_modules/globby": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", + "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -2125,6 +2307,15 @@ "node": ">=0.10.0" } }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -2511,6 +2702,15 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -2903,6 +3103,18 @@ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", "dev": true }, + "node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -2995,6 +3207,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -3159,6 +3391,16 @@ "node": ">= 4" } }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rimraf": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", @@ -3189,6 +3431,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -3473,6 +3738,18 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/sockjs": { "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", @@ -3881,6 +4158,18 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/src/database.ts b/src/database.ts index 7a8a4fe..e86404f 100644 --- a/src/database.ts +++ b/src/database.ts @@ -6,19 +6,34 @@ class Database { private storeDefinitions = { SpClient: { name: "sp_client", - options: {} + options: {}, + indices: [] + }, + SpOutputs: { + name: "sp_outputs", + options: {'autoIncrement': true}, + indices: [{ + name: 'by_wallet_fingerprint', + keyPath: 'wallet_fingerprint', + options: { + 'unique': false + } + }] }, AnkUser: { name: "user", - options: {} + options: {}, + indices: [] }, AnkSession: { name: "session", - options: {} + options: {}, + indices: [] }, AnkProcess: { name: "process", - options: {} + options: {}, + indices: [] } } @@ -42,19 +57,23 @@ class Database { request.onupgradeneeded = () => { const db = request.result; - Object.values(this.storeDefinitions).forEach(({name, options}) => { + Object.values(this.storeDefinitions).forEach(({name, options, indices}) => { if (!db.objectStoreNames.contains(name)) { - db.createObjectStore(name, options); + let store = db.createObjectStore(name, options); + + indices.forEach(({name, keyPath, options}) => { + store.createIndex(name, keyPath, options); + }) } }); }; - request.onsuccess = (event) => { + request.onsuccess = () => { this.db = request.result; resolve(); }; - request.onerror = (event) => { + request.onerror = () => { console.error("Database error:", request.error); reject(request.error); }; diff --git a/src/index.ts b/src/index.ts index 59e125d..891a579 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,9 +12,12 @@ document.addEventListener('DOMContentLoaded', async () => { services.displayRecover() } + let sp_wallet_return = services.new_sp_client("default", 0, true); + const indexedDB = await IndexedDB.getInstance(); const db = indexedDB.getDb(); - await indexedDB.writeObject(db, indexedDB.getStoreList().SpClient, services.new_sp_client(), "default"); + await indexedDB.writeObject(db, indexedDB.getStoreList().SpClient, sp_wallet_return.sp_client_json, "default"); + await indexedDB.writeObject(db, indexedDB.getStoreList().SpOutputs, sp_wallet_return.sp_outputs_json, null); } catch (error) { console.error(error); diff --git a/src/services.ts b/src/services.ts index da08ff3..3669c66 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,3 +1,4 @@ +import { GenerateSpWalletReturn } from '../dist/pkg/sdk_client'; import IndexedDB from './database' import Processstore from './store/processstore'; import Userstore from './store/userstore'; @@ -25,8 +26,8 @@ class Services { this.sdkClient.setup(); } - public new_sp_client(): string { - return this.sdkClient.generate_sp_wallet(); + public new_sp_client(label: string, current_tip: number, is_testnet: boolean): GenerateSpWalletReturn { + return this.sdkClient.generate_sp_wallet(label, current_tip, is_testnet); } public async getSpAddressDefaultClient(): Promise { From d081bc1f78035644252ecc0a5711e87d5a2274d9 Mon Sep 17 00:00:00 2001 From: Alex Silva Date: Thu, 21 Mar 2024 20:07:56 +0100 Subject: [PATCH 09/90] Add user, secretdata and aesgcm modules --- crates/sp_client/Cargo.toml | 14 ++ crates/sp_client/src/aesgcm.rs | 177 ++++++++++++++ crates/sp_client/src/lib.rs | 5 + crates/sp_client/src/secretdata.rs | 266 ++++++++++++++++++++ crates/sp_client/src/user.rs | 374 +++++++++++++++++++++++++++++ 5 files changed, 836 insertions(+) create mode 100644 crates/sp_client/src/aesgcm.rs create mode 100644 crates/sp_client/src/secretdata.rs create mode 100644 crates/sp_client/src/user.rs diff --git a/crates/sp_client/Cargo.toml b/crates/sp_client/Cargo.toml index 249e291..771af5c 100644 --- a/crates/sp_client/Cargo.toml +++ b/crates/sp_client/Cargo.toml @@ -18,6 +18,20 @@ wasm-logger = "0.2.0" rand = "0.8.5" log = "0.4.6" tsify = { git = "https://github.com/Sosthene00/tsify", branch = "next" } +web-sys = { version = "0.3", features = ["console"] } +bs58 = "0.4" +hex = "0.4.3" +sha2 = "0.10.8" +aes-gcm = "0.10.3" +aes = "0.8.3" +base64 = "0.21.7" +image = "0.24.9" +img-parts = "0.3.0" +bytes = "1.5.0" +scrypt = "0.11.0" +shamir = "2.0.0" +bitcoin = { version = "0.31.1", features = ["serde", "base64"] } + [dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/crates/sp_client/src/aesgcm.rs b/crates/sp_client/src/aesgcm.rs new file mode 100644 index 0000000..3783e01 --- /dev/null +++ b/crates/sp_client/src/aesgcm.rs @@ -0,0 +1,177 @@ +/* This module is temporary. We'll use the module described in key_encription +module defined in sdk_common repository! Some of the methods there were copied here. +*/ +use wasm_bindgen::JsValue; +use web_sys::console; +use core::result::Result as CoreResult; +use rand::RngCore; + +use serde::{Deserialize, Serialize}; +use serde_json::{json, Value}; + +use aes::cipher::consts::U32; +use aes::cipher::generic_array::GenericArray; +use aes_gcm::{ + aead::{AeadInPlace, KeyInit}, + Aes256Gcm, +}; +use rand::rngs::OsRng; +use hex; +use hex::FromHexError; + + +pub struct Aes256GcmIv96Bit { + pub key: GenericArray, +} + + +impl Aes256GcmIv96Bit { + pub fn new() -> Self { + let mut key_bytes = [0u8; 32]; + OsRng.fill_bytes(&mut key_bytes); + let key = GenericArray::from_slice(&key_bytes); + Aes256GcmIv96Bit { key: key.clone() } + } + + pub fn encrypt(&self, data: &[u8]) -> CoreResult, aes_gcm::Error> { + let cipher = Aes256Gcm::new(&self.key); + let mut nonce = [0u8; 12]; + OsRng.fill_bytes(&mut nonce); + + let mut buffer = data.to_vec(); + cipher.encrypt_in_place(GenericArray::from_slice(&nonce), b"", &mut buffer)?; + + Ok([nonce.to_vec(), buffer].concat()) + } + + pub fn decrypt(&self, data: &[u8]) -> CoreResult, aes_gcm::Error> { + if data.len() < 12 { + return Err(aes_gcm::Error); // Remplacer par une erreur appropriée + } + + let (nonce, encrypted_data) = data.split_at(12); + let mut buffer = encrypted_data.to_vec(); + let cipher = Aes256Gcm::new(&self.key); + cipher.decrypt_in_place(GenericArray::from_slice(nonce), b"", &mut buffer)?; + + Ok(buffer) + } + + pub fn encrypt_string(&self, data: &str) -> CoreResult { + match self.encrypt(data.as_bytes()) { + Ok(encrypted_data) => Ok(base64::encode(encrypted_data)), + Err(_) => Err("Erreur de chiffrement".to_string()), + } + } + + pub fn decrypt_string(&self, data: &str) -> CoreResult { + let decoded_data = match base64::decode(data) { + Ok(data) => data, + Err(_) => return Err("Erreur de décodage Base64".to_string()), + }; + + match self.decrypt(&decoded_data) { + Ok(decrypted_data) => match String::from_utf8(decrypted_data) { + Ok(text) => Ok(text), + Err(_) => Err("Erreur de conversion UTF-8".to_string()), + }, + Err(_) => Err("Erreur de déchiffrement".to_string()), + } + } + + pub fn export_key(&self) -> String { + base64::encode(&self.key) + } + + pub fn import_key(encoded_key: &str) -> CoreResult { + match base64::decode(encoded_key) { + Ok(decoded_key) => { + if decoded_key.len() == 32 { + let key = GenericArray::from_slice(&decoded_key); + Ok(Aes256GcmIv96Bit { key: key.clone() }) + } else { + Err("La taille de la clé n'est pas valide".to_string()) + } + } + Err(_) => Err("Échec du décodage de la clé".to_string()), + } + } + +} + +#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct KeyEncryption { + pub attribute_name: Option, + pub key: Option, + pub algorithm: Option, +} + +impl KeyEncryption { + pub fn new( + attribute_name: Option, + key: Option, + algorithm: Option, + ) -> Self { + KeyEncryption { + attribute_name, + key, + algorithm, + } + } + + pub fn encode(&self, data: String) -> CoreResult { + + if let Some(ref key) = self.key { + let decoded_key = Aes256GcmIv96Bit::import_key(key)?; + let encrypted_data = decoded_key.encrypt_string(&data)?; + Ok(encrypted_data) + } else { + Err("Aucune clé n'est définie".to_string()) + } + } + + pub fn decode(&self, encrypted_data: String) -> CoreResult { + if let Some(ref key) = self.key { + let decoded_key = Aes256GcmIv96Bit::import_key(key)?; + let decrypted_data = decoded_key.decrypt_string(&encrypted_data)?; + Ok(decrypted_data) + } else { + Err("Aucune clé n'est définie".to_string()) + } + } + + pub fn enc(&self, data: Value) -> String { + let data_string = serde_json::to_string(&data).unwrap_or_else(|_| "".to_string()); + self.encode(data_string).unwrap_or_else(|_| "".to_string()) + } + pub fn enc_string(&self, data: String) -> String { + self.enc(Value::String(data)) + } + pub fn enc_i64(&self, data: i64) -> String { + self.enc(Value::Number(data.into())) + } + pub fn enc_u64(&self, data: u64) -> String { + self.enc(Value::Number(data.into())) + } + pub fn enc_u32(&self, data: u32) -> String { + self.enc(Value::Number(data.into())) + } + pub fn enc_vec_string(&self, list: Vec) -> String { + self.enc(Value::Array(list.into_iter().map(Value::String).collect())) + } + pub fn enc_vec_key_encryption(&self, list: Vec) -> String { + // Utilisez `serde_json::to_value` pour convertir chaque `KeyEncryption` en `Value` + let json_list: Vec = list + .into_iter() + .map(|key_enc| serde_json::to_value(key_enc).unwrap_or_else(|_| json!({}))) + .collect(); + + self.enc(Value::Array(json_list)) + } +} + +fn hex_to_generic_array(hex_string: &str) -> Result, FromHexError> { + let byte_vec = hex::decode(hex_string)?; + let array = GenericArray::clone_from_slice(&byte_vec[..32]); + Ok(array) +} \ No newline at end of file diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index 0ce9757..b9931a4 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -1,3 +1,8 @@ +#![allow(warnings)] pub mod api; mod injecteurhtml; mod process; +mod user; +mod aesgcm; +mod secretdata; + diff --git a/crates/sp_client/src/secretdata.rs b/crates/sp_client/src/secretdata.rs new file mode 100644 index 0000000..d05e366 --- /dev/null +++ b/crates/sp_client/src/secretdata.rs @@ -0,0 +1,266 @@ +use rand::{thread_rng, RngCore}; + +pub struct SecretData { + pub secret_data: Option, + pub coefficients: Vec>, +} + +#[derive(Debug)] +pub enum ShamirError { + /// The number of shares must be between 1 and 255 + InvalidShareCount, +} + +impl SecretData { + pub fn with_secret(secret: &str, threshold: u8) -> SecretData { + let mut coefficients: Vec> = vec![]; + let mut rng = thread_rng(); + let mut rand_container = vec![0u8; (threshold - 1) as usize]; + for c in secret.as_bytes() { + rng.fill_bytes(&mut rand_container); + let mut coef: Vec = vec![*c]; + for r in rand_container.iter() { + coef.push(*r); + } + coefficients.push(coef); + } + + SecretData { + secret_data: Some(secret.to_string()), + coefficients, + } + } + + pub fn get_share(&self, id: u8) -> Result, ShamirError> { + if id == 0 { + return Err(ShamirError::InvalidShareCount); + } + let mut share_bytes: Vec = vec![]; + let coefficients = self.coefficients.clone(); + for coefficient in coefficients { + //let b = SecretData::accumulate_share_bytes(id, coefficient)?; + let b = r#try!(SecretData::accumulate_share_bytes(id, coefficient)); + share_bytes.push(b); + } + + share_bytes.insert(0, id); + Ok(share_bytes) + } + + pub fn is_valid_share(&self, share: &[u8]) -> bool { + let id = share[0]; + match self.get_share(id) { + Ok(s) => s == share, + _ => false, + } + } + + pub fn recover_secret(threshold: u8, shares: Vec>) -> Option { + if threshold as usize > shares.len() { + println!("Number of shares is below the threshold"); + return None; + } + let mut xs: Vec = vec![]; + + for share in shares.iter() { + if xs.contains(&share[0]) { + println!("Multiple shares with the same first byte"); + return None; + } + + if share.len() != shares[0].len() { + println!("Shares have different lengths"); + return None; + } + + xs.push(share[0].to_owned()); + } + let mut mycoefficients: Vec = vec![]; + let mut mysecretdata: Vec = vec![]; + let rounds = shares[0].len() - 1; + + for byte_to_use in 0..rounds { + let mut fxs: Vec = vec![]; + for share in shares.clone() { + fxs.push(share[1..][byte_to_use]); + } + + match SecretData::full_lagrange(&xs, &fxs) { + None => return None, + Some(resulting_poly) => { + mycoefficients.push(String::from_utf8_lossy(&resulting_poly[..]).to_string()); + mysecretdata.push(resulting_poly[0]); + } + } + } + + match String::from_utf8(mysecretdata) { + Ok(s) => Some(s), + Err(e) => { + println!("{:?}", e); + None + } + } + } + + fn accumulate_share_bytes(id: u8, coefficient_bytes: Vec) -> Result { + if id == 0 { + return Err(ShamirError::InvalidShareCount); + } + let mut accumulator: u8 = 0; + + let mut x_i: u8 = 1; + + for c in coefficient_bytes { + accumulator = SecretData::gf256_add(accumulator, SecretData::gf256_mul(c, x_i)); + x_i = SecretData::gf256_mul(x_i, id); + } + + Ok(accumulator) + } + + fn full_lagrange(xs: &[u8], fxs: &[u8]) -> Option> { + let mut returned_coefficients: Vec = vec![]; + let len = fxs.len(); + for i in 0..len { + let mut this_polynomial: Vec = vec![1]; + + for j in 0..len { + if i == j { + continue; + } + + let denominator = SecretData::gf256_sub(xs[i], xs[j]); + let first_term = SecretData::gf256_checked_div(xs[j], denominator); + let second_term = SecretData::gf256_checked_div(1, denominator); + match (first_term, second_term) { + (Some(a), Some(b)) => { + let this_term = vec![a, b]; + this_polynomial = + SecretData::multiply_polynomials(&this_polynomial, &this_term); + } + (_, _) => return None, + }; + } + if fxs.len() + 1 >= i { + this_polynomial = SecretData::multiply_polynomials(&this_polynomial, &[fxs[i]]) + } + returned_coefficients = + SecretData::add_polynomials(&returned_coefficients, &this_polynomial); + } + Some(returned_coefficients) + } + + #[inline] + fn gf256_add(a: u8, b: u8) -> u8 { + a ^ b + } + + #[inline] + fn gf256_sub(a: u8, b: u8) -> u8 { + SecretData::gf256_add(a, b) + } + + #[inline] + fn gf256_mul(a: u8, b: u8) -> u8 { + if a == 0 || b == 0 { + 0 + } else { + GF256_EXP[((u16::from(GF256_LOG[a as usize]) + u16::from(GF256_LOG[b as usize])) % 255) + as usize] + } + } + + #[inline] + fn gf256_checked_div(a: u8, b: u8) -> Option { + if a == 0 { + Some(0) + } else if b == 0 { + None + } else { + let a_log = i16::from(GF256_LOG[a as usize]); + let b_log = i16::from(GF256_LOG[b as usize]); + + let mut diff = a_log - b_log; + + if diff < 0 { + diff += 255; + } + Some(GF256_EXP[(diff % 255) as usize]) + } + } + + #[inline] + fn multiply_polynomials(a: &[u8], b: &[u8]) -> Vec { + let mut resultterms: Vec = vec![]; + + let mut termpadding: Vec = vec![]; + + for bterm in b { + let mut thisvalue = termpadding.clone(); + for aterm in a { + thisvalue.push(SecretData::gf256_mul(*aterm, *bterm)); + } + resultterms = SecretData::add_polynomials(&resultterms, &thisvalue); + termpadding.push(0); + } + resultterms + } + + #[inline] + fn add_polynomials(a: &[u8], b: &[u8]) -> Vec { + let mut a = a.to_owned(); + let mut b = b.to_owned(); + if a.len() < b.len() { + let mut t = vec![0; b.len() - a.len()]; + a.append(&mut t); + } else if a.len() > b.len() { + let mut t = vec![0; a.len() - b.len()]; + b.append(&mut t); + } + let mut results: Vec = vec![]; + + for i in 0..a.len() { + results.push(SecretData::gf256_add(a[i], b[i])); + } + results + } +} + +static GF256_EXP: [u8; 256] = [ + 0x01, 0x03, 0x05, 0x0f, 0x11, 0x33, 0x55, 0xff, 0x1a, 0x2e, 0x72, 0x96, 0xa1, 0xf8, 0x13, 0x35, + 0x5f, 0xe1, 0x38, 0x48, 0xd8, 0x73, 0x95, 0xa4, 0xf7, 0x02, 0x06, 0x0a, 0x1e, 0x22, 0x66, 0xaa, + 0xe5, 0x34, 0x5c, 0xe4, 0x37, 0x59, 0xeb, 0x26, 0x6a, 0xbe, 0xd9, 0x70, 0x90, 0xab, 0xe6, 0x31, + 0x53, 0xf5, 0x04, 0x0c, 0x14, 0x3c, 0x44, 0xcc, 0x4f, 0xd1, 0x68, 0xb8, 0xd3, 0x6e, 0xb2, 0xcd, + 0x4c, 0xd4, 0x67, 0xa9, 0xe0, 0x3b, 0x4d, 0xd7, 0x62, 0xa6, 0xf1, 0x08, 0x18, 0x28, 0x78, 0x88, + 0x83, 0x9e, 0xb9, 0xd0, 0x6b, 0xbd, 0xdc, 0x7f, 0x81, 0x98, 0xb3, 0xce, 0x49, 0xdb, 0x76, 0x9a, + 0xb5, 0xc4, 0x57, 0xf9, 0x10, 0x30, 0x50, 0xf0, 0x0b, 0x1d, 0x27, 0x69, 0xbb, 0xd6, 0x61, 0xa3, + 0xfe, 0x19, 0x2b, 0x7d, 0x87, 0x92, 0xad, 0xec, 0x2f, 0x71, 0x93, 0xae, 0xe9, 0x20, 0x60, 0xa0, + 0xfb, 0x16, 0x3a, 0x4e, 0xd2, 0x6d, 0xb7, 0xc2, 0x5d, 0xe7, 0x32, 0x56, 0xfa, 0x15, 0x3f, 0x41, + 0xc3, 0x5e, 0xe2, 0x3d, 0x47, 0xc9, 0x40, 0xc0, 0x5b, 0xed, 0x2c, 0x74, 0x9c, 0xbf, 0xda, 0x75, + 0x9f, 0xba, 0xd5, 0x64, 0xac, 0xef, 0x2a, 0x7e, 0x82, 0x9d, 0xbc, 0xdf, 0x7a, 0x8e, 0x89, 0x80, + 0x9b, 0xb6, 0xc1, 0x58, 0xe8, 0x23, 0x65, 0xaf, 0xea, 0x25, 0x6f, 0xb1, 0xc8, 0x43, 0xc5, 0x54, + 0xfc, 0x1f, 0x21, 0x63, 0xa5, 0xf4, 0x07, 0x09, 0x1b, 0x2d, 0x77, 0x99, 0xb0, 0xcb, 0x46, 0xca, + 0x45, 0xcf, 0x4a, 0xde, 0x79, 0x8b, 0x86, 0x91, 0xa8, 0xe3, 0x3e, 0x42, 0xc6, 0x51, 0xf3, 0x0e, + 0x12, 0x36, 0x5a, 0xee, 0x29, 0x7b, 0x8d, 0x8c, 0x8f, 0x8a, 0x85, 0x94, 0xa7, 0xf2, 0x0d, 0x17, + 0x39, 0x4b, 0xdd, 0x7c, 0x84, 0x97, 0xa2, 0xfd, 0x1c, 0x24, 0x6c, 0xb4, 0xc7, 0x52, 0xf6, 0x01, +]; + +static GF256_LOG: [u8; 256] = [ + 0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, 0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03, + 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, 0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1, + 0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78, + 0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, 0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e, + 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, 0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38, + 0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10, + 0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, 0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba, + 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, 0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57, + 0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8, + 0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, 0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0, + 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, 0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7, + 0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d, + 0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, 0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1, + 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab, + 0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5, + 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, 0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07, +]; \ No newline at end of file diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs new file mode 100644 index 0000000..9fdc76f --- /dev/null +++ b/crates/sp_client/src/user.rs @@ -0,0 +1,374 @@ +use bitcoin::secp256k1::SecretKey; +use serde::{Deserialize, Serialize}; +use serde_json::{json, Value}; +use rand::{self, Rng,thread_rng, RngCore}; +use wasm_bindgen::JsValue; +use wasm_bindgen::prelude::*; +use web_sys::console; +use anyhow::Error; + +use crate::aesgcm::{Aes256GcmIv96Bit,KeyEncryption}; +use crate::secretdata::SecretData; +use hex; +use sha2::{Sha256, Digest}; +use bytes::Bytes; +use std::fs::File; + +use crate::api::{generate_sp_wallet_return,generate_sp_wallet}; +use sp_backend::spclient::SpendKey; +use sp_backend::spclient::{SpClient, OutputList}; +use sp_backend::silentpayments::sending::SilentPaymentAddress; + +use img_parts::jpeg::Jpeg; +use img_parts::{ImageEXIF, ImageICC}; + +use scrypt::{ + password_hash::{ + rand_core::OsRng, + PasswordHash, PasswordHasher, PasswordVerifier, SaltString + }, + Scrypt +}; + +//extern crate shamir; +//use shamir::SecretData; + + +#[wasm_bindgen] +#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct User { + image_recover: ImageRecover, + image_revoke: ImageRevoke, + sharding: Sharding, + pre_id: String, + recovered_spend_key: Option, +} + +#[wasm_bindgen] +impl User { + #[wasm_bindgen(constructor)] + pub fn new(new_password: &str, image_to_recover: &[u8], image_to_revoke: &[u8]) -> Self { + + let password = new_password.to_string(); + let random_seed1 = generate_random_key(32); + let random_seed2 = generate_random_key(32); + //wallet recover + let wallet_rec: String = match generate_sp_wallet(None,50000, true) { + Some(sp_wallet) => sp_wallet.sp_client_json, + None => panic!("No wallet recover available"), + }; + let sp_client_rec: SpClient = serde_json::from_str(&wallet_rec).unwrap(); + let priv_recover_scan_key_bytes = sp_client_rec.get_scan_key().secret_bytes(); + let priv_recover_scan_key = from_b64_to_hex(&base64::encode(priv_recover_scan_key_bytes)); + let priv_recover_spend_key_bytes = match sp_client_rec.get_spend_key(){ + SpendKey::Secret(key)=> key.secret_bytes(), + SpendKey::Public(_) => panic!("No recover spend key created on Signet"), + }; + let priv_recover_spend_key = from_b64_to_hex(&base64::encode(priv_recover_spend_key_bytes)); + console::log_2(&"priv_recover_spend_key".into(),&JsValue::from_str(&priv_recover_spend_key)); + //wallet revoke + let wallet_rev: String = match generate_sp_wallet(None, 50000, true) { + Some(sp_wallet) => sp_wallet.sp_client_json, + None => panic!("No wallet revoke available"), + }; + let sp_client_rev: SpClient = serde_json::from_str(&wallet_rec).unwrap(); + let priv_revoke_scan_key_bytes = sp_client_rev.get_scan_key().secret_bytes(); + let priv_revoke_scan_key = from_b64_to_hex(&base64::encode(priv_revoke_scan_key_bytes)); + let priv_revoke_spend_key_bytes = match sp_client_rev.get_spend_key(){ + SpendKey::Secret(key)=> key.secret_bytes(), + SpendKey::Public(_) => panic!("No revoke spend key created on Signet"), + }; + let priv_revoke_spend_key = from_b64_to_hex(&base64::encode(priv_revoke_spend_key_bytes)); + + //split recover spend key + let (part1_key, part2_key) = priv_recover_spend_key.split_at(priv_recover_spend_key.len()/2); + + //part1 enc + let pwd_hash_part1 = from_hex_to_b64(&sha_256(&format!("{}{}",password, &random_seed1))); + let key_enc_part1 = KeyEncryption::new(None, Some(pwd_hash_part1.clone()), None); + let part1_key_enc = key_enc_part1.enc_string(part1_key.to_string()); + //part2 enc + let pwd_hash_part2 = from_hex_to_b64(&sha_256(&format!("{}{}", password, random_seed2))); + let key_enc_part2 = KeyEncryption::new(None, Some(pwd_hash_part2.clone()), None); + let part2_key_enc = key_enc_part2.enc_string(part2_key.to_string()); + //image recover + let image_recover = ImageRecover::new(image_to_recover, &random_seed1, &random_seed2,&part1_key_enc); + //image revoke + //let priv_revoke_spend_key = wallet.priv_revoke_spend_key.to_owned(); + //let priv_revoke_scan_key = wallet.priv_revoke_scan_key.to_owned(); + let image_revoke = ImageRevoke::new(image_to_revoke,&priv_revoke_spend_key,&priv_revoke_scan_key); + //create shardings + let sharding = Sharding::new(&part2_key_enc, 10u8); //nMembers = 10 for testing, need to recover nmember elsewhere + //Pre ID + let pre_id = sha_256(&format!("{}{}",password, part2_key_enc)); + + //Create PRDList + //@todo + //Send messages PRDList + //@todo + //Receive List Items (PCD) + + console::log_1(&"authentication: ok".into()); + User {image_recover, + image_revoke, + sharding, + pre_id, + recovered_spend_key:None + } + } + + pub fn login(&self,password: &str, image_recover: &[u8]) -> Option{ + let exif_image_bytes = read_exif(image_recover).unwrap_or_else(|error| { + panic!("Unable to read the image exif: {}", error); + }); + + let exif_image_string = String::from_utf8(exif_image_bytes.to_vec()).unwrap(); + let exif_image_json: Value = serde_json::from_str(&exif_image_string).unwrap(); + let random_seed1 = exif_image_json["random_seed1"].as_str().unwrap_or("N/A"); + let random_seed2 = exif_image_json["random_seed2"].as_str().unwrap_or("N/A"); + let part1_key_enc = exif_image_json["part1_key_enc"].as_str().unwrap_or("N/A"); + let part1_recovered = Self::recover_part1(password,random_seed1,part1_key_enc); + let part1_trimmed = part1_recovered.trim_matches('"'); + + //@todo: get shardings from member managers!! + let shardings = self.sharding.shares_vec.clone(); // temporary + + let part2_recovered = Self::recover_part2(&password,&random_seed2, shardings); + let part2_trimmed = part2_recovered.trim_matches('"'); + let recover_key_hex: String = format!("{}{}", part1_trimmed, part2_trimmed); + + Some(recover_key_hex) + } + + fn recover_part1(password: &str, random_seed1: &str, part1_key_enc: & str) -> String{ + let pwd_hash_part1 = from_hex_to_b64(&sha_256(&format!("{}{}",password, random_seed1))); + let key_dec_part1 = KeyEncryption::new(None, Some(pwd_hash_part1), None); + let part1_key_recovered = key_dec_part1.decode(part1_key_enc.to_string()).unwrap_or_else(|_| "".to_string()); + part1_key_recovered + } + + fn recover_part2(password: &str, random_seed2: &str, shares_vec: Vec>) -> String{ + let quorum_sharding = (Sharding::QUORUM_SHARD * f32::from(shares_vec.len() as u8)).round() as u8; + let part2_key_enc = SecretData::recover_secret(quorum_sharding, shares_vec).unwrap(); + let pwd_hash_part2 = from_hex_to_b64(&sha_256(&format!("{}{}",password, random_seed2))); + let key_dec_part2 = KeyEncryption::new(None, Some(pwd_hash_part2), None); + let part2_key_recovered = key_dec_part2.decode(part2_key_enc).unwrap_or_else(|_| "".to_string()); + part2_key_recovered + } + + + //not used + pub fn pbkdf2(password: &str, data: & str)->String { + let data_salt = data.trim_end_matches('='); + let salt = SaltString::from_b64(data_salt) + .map(|s| { s }) + .unwrap_or_else(|_| { + panic!("Failed to parse salt value from base64 string") + }); + + let mut password_hash = String::new(); + if let Ok(pwd) = Scrypt.hash_password(password.as_bytes(), &salt) { + password_hash.push_str(&pwd.to_string()); + } + sha_256(&password_hash) + + + } + + pub fn get_image_recover(&self)-> Vec{ + return self.image_recover.image_recover_bytes.clone(); + } + + pub fn get_exif_image(&self,image:&[u8])-> Vec{ + return read_exif(image).expect("Error reading the exif"); + } + + pub fn get_image_revoke(&self)-> Vec{ + return self.image_revoke.image_revoke_bytes.clone(); + } + + // Test sharing JS side + pub fn get_shares(&self)->Vec{ + self.sharding.shares_format_str.clone() + + } + + //Test sharing Js side + pub fn get_secret(&self,shardings: Vec)->String{ + let mut shares_vec = Vec::new(); + + for s in shardings.iter(){ + let bytes_vec: Vec = s + .trim_matches(|c| c == '[' || c == ']') + .split(',') + .filter_map(|s| s.trim().parse().ok()) + .collect(); + shares_vec.push(bytes_vec); + + } + self.sharding.recover_secrete(shares_vec.clone()) + } + + } + +#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct ImageRecover { + image_recover_bytes: Vec, +} + +impl ImageRecover{ + pub fn new(image_to_recover: &[u8], + random_seed1: &str, + random_seed2: &str, + part1_key_enc: &str, + ) -> Self{ + let data_exif_json = json!({ + "random_seed1": random_seed1, + "random_seed2": random_seed2, + "part1_key_enc": part1_key_enc + }); + + let data = serde_json::to_string(&data_exif_json).unwrap(); + let image_recover = write_exif(image_to_recover, &data); + ImageRecover{ + image_recover_bytes: image_recover.expect("Image recover not generated!") + } + } + +} + +#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct ImageRevoke { + image_revoke_bytes: Vec, +} +impl ImageRevoke{ + pub fn new(image_to_revoke: &[u8], + priv_revoke_spend_key: &str, + priv_revoke_scan_key: &str, + + )->Self{ + let data_exif_json = json!({ + "priv_revoke_spend_key":priv_revoke_spend_key, + "priv_revoke_scan_key":priv_revoke_scan_key + }); + + let data = serde_json::to_string(&data_exif_json).unwrap(); + let image_revoke = write_exif(image_to_revoke, &data); + ImageRevoke{ + image_revoke_bytes: image_revoke.expect("Image revoke not generated!") + } + } + +} + + +#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct Sharding { + shares_vec: Vec>, + shares_format_str: Vec, + +} + +impl Sharding{ + const QUORUM_SHARD: f32= 0.80_f32; + pub fn new( + part2_key_enc: &str, + number_members: u8, + )->Self{ + let secret_data = SecretData::with_secret(part2_key_enc, number_members); + let mut shares_format_str: Vec = Vec::new(); + let shares_vec = (1..=number_members).map(|i| match secret_data.get_share(i) + { + Ok(share) => { + let string = format!("[{}]", share.clone().iter() + .map(|b| format!("{}", b)) + .collect::>() + .join(",")); + shares_format_str.push(string.clone()); + share + }, + Err(_) => panic!("Not able to recover the shares!"), + } + ).collect::>(); + + Sharding{ + shares_vec, + shares_format_str + + } + } + + pub fn recover_secrete(&self, shares: Vec>) -> String { + let quorum_sharding = (Self::QUORUM_SHARD * f32::from(shares.len() as u8)).round() as u8; + SecretData::recover_secret(quorum_sharding, shares).unwrap() + } +} + +//associated functions +pub fn generate_random_key(length:usize) ->String { + let mut rng = rand::thread_rng(); + let random_bytes: Vec = (0..length) + .map(|_| rng.gen_range(0x00..=0xFF)) + .collect(); + base64::encode(random_bytes) +} + +pub fn sha_256(data: &str)-> String{ + let mut hasher = Sha256::new(); + hasher.update(data); + let result = hasher.finalize(); + hex::encode(result) +} + + pub fn write_exif(image_to_recover: &[u8], data: &str) -> Result, String>{ + let image_to_recover_bytes = Bytes::from(image_to_recover.to_vec()); + let mut jpeg = Jpeg::from_bytes(image_to_recover_bytes).unwrap(); + let data_bytes = Bytes::from(data.as_bytes().to_vec()); + jpeg.set_exif(Some(data_bytes)); + let output_image_bytes = jpeg.encoder().bytes(); + let output_image = output_image_bytes.as_ref(); + Ok(output_image.to_vec()) +} + + + pub fn read_exif(image: &[u8])->Result, String>{ + let image_bytes = Bytes::from(image.to_vec()); + let jpeg = Jpeg::from_bytes(image_bytes).unwrap(); + + //exif out + let mut exif_image = Bytes::new(); + if let Some(ref meta) = jpeg.exif(){ + exif_image = meta.clone(); + }else { + return Err("No exif data".to_string()); + } + let exif_bytes =exif_image.as_ref(); + Ok(exif_bytes.to_vec()) +} + +//change for return Result? +pub fn from_hex_to_b58(hex_string: &str)-> String{ + let decoded_data = hex::decode(hex_string).expect("Failed to decode hex string"); + let base58_string = bs58::encode(decoded_data).into_string(); + base58_string +} +//change for return Result? +pub fn from_b58_to_hex(base58_string: &str)-> String{ + let decoded_data = bs58::decode(base58_string.to_owned()).into_vec().unwrap(); + let hex_string = decoded_data.iter().map(|b| format!("{:02x}", b)).collect::(); + hex_string +} + +fn from_b64_to_hex(base64_string:&str)->String{ + let decoded_data = base64::decode(base64_string).unwrap(); + let hex_string = decoded_data.iter().map(|b| format!("{:02x}", b)).collect::(); + hex_string +} +fn from_hex_to_b64(hex_string:&str)->String{ + let decoded_data = hex::decode(hex_string).expect("Failed to decode hex string"); + let base64_string = base64::encode(decoded_data); + base64_string +} + + + From 70dc18ef978da07f3ab7b538638fee875b2c7bd6 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Fri, 22 Mar 2024 12:04:52 +0100 Subject: [PATCH 10/90] Better error management in api --- crates/sp_client/src/api.rs | 67 ++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 0628a60..cdce897 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -1,15 +1,49 @@ use rand::Rng; +use anyhow::Error as AnyhowError; +use sp_backend::silentpayments::Error as SpError; +use serde_json::Error as SerdeJsonError; + use serde::{Deserialize, Serialize}; use sp_backend::silentpayments::sending::SilentPaymentAddress; -use wasm_bindgen::prelude::*; use tsify::Tsify; +use wasm_bindgen::convert::FromWasmAbi; +use wasm_bindgen::prelude::*; use sp_backend::spclient::SpendKey; -use sp_backend::spclient::{derive_keys_from_seed, SpClient, OutputList}; +type ApiResult = Result; const IS_TESTNET: bool = true; +#[derive(Debug)] +struct ApiError { + message: String, +} + +impl From for ApiError { + fn from(value: AnyhowError) -> Self { + ApiError {message: value.to_string()} + } +} + +impl From for ApiError { + fn from(value: SpError) -> Self { + ApiError { message: value.to_string() } + } +} + +impl From for ApiError { + fn from(value: SerdeJsonError) -> Self { + ApiError { message: value.to_string() } + } +} + +impl Into for ApiError { + fn into(self) -> JsValue { + JsValue::from_str(&self.message) + } +} + #[derive(Tsify, Serialize, Deserialize)] #[tsify(into_wasm_abi)] #[allow(non_camel_case_types)] @@ -24,36 +58,43 @@ pub fn setup() { } #[wasm_bindgen] -pub fn generate_sp_wallet(label: Option, birthday: u32, is_testnet: bool) -> Option { +pub fn generate_sp_wallet( + label: Option, + birthday: u32, + is_testnet: bool, +) -> ApiResult { let mut seed = [0u8; 64]; rand::thread_rng().fill(&mut seed); - let (scan_sk, spend_sk) = derive_keys_from_seed(&seed, is_testnet).ok()?; + let (scan_sk, spend_sk) = derive_keys_from_seed(&seed, is_testnet)?; let sp_client = SpClient::new( label.unwrap_or("default".into()), scan_sk, SpendKey::Secret(spend_sk), None, IS_TESTNET, - ) - .ok()?; - let our_address: SilentPaymentAddress = sp_client.get_receiving_address().try_into().ok()?; + )?; + let our_address: SilentPaymentAddress = sp_client.get_receiving_address().try_into()?; log::info!( "Created client for sp with address: {}", our_address.to_string() ); - let sp_client_json = serde_json::to_string(&sp_client).ok()?; - + let sp_client_json = serde_json::to_string(&sp_client)?; + // Generate an empty outputs - let sp_outputs = OutputList::new(our_address.get_scan_key(), our_address.get_spend_key(), birthday); - let sp_outputs_json = serde_json::to_string(&sp_outputs).ok()?; + let sp_outputs = OutputList::new( + our_address.get_scan_key(), + our_address.get_spend_key(), + birthday, + ); + let sp_outputs_json = serde_json::to_string(&sp_outputs)?; let res = generate_sp_wallet_return { sp_client_json, - sp_outputs_json + sp_outputs_json, }; - Some(res) + Ok(res) } #[wasm_bindgen] From 8dde96b93cc3b80eee55773a28b863eb939a90c6 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Fri, 22 Mar 2024 12:10:08 +0100 Subject: [PATCH 11/90] cargo fmt --- crates/sp_client/src/aesgcm.rs | 20 +- crates/sp_client/src/api.rs | 2 + crates/sp_client/src/injecteurhtml.rs | 12 +- crates/sp_client/src/lib.rs | 5 +- crates/sp_client/src/process.rs | 2 +- crates/sp_client/src/secretdata.rs | 2 +- crates/sp_client/src/user.rs | 306 +++++++++++++------------- 7 files changed, 180 insertions(+), 169 deletions(-) diff --git a/crates/sp_client/src/aesgcm.rs b/crates/sp_client/src/aesgcm.rs index 3783e01..20882cf 100644 --- a/crates/sp_client/src/aesgcm.rs +++ b/crates/sp_client/src/aesgcm.rs @@ -1,10 +1,10 @@ /* This module is temporary. We'll use the module described in key_encription module defined in sdk_common repository! Some of the methods there were copied here. -*/ -use wasm_bindgen::JsValue; -use web_sys::console; +*/ use core::result::Result as CoreResult; use rand::RngCore; +use wasm_bindgen::JsValue; +use web_sys::console; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; @@ -15,16 +15,14 @@ use aes_gcm::{ aead::{AeadInPlace, KeyInit}, Aes256Gcm, }; -use rand::rngs::OsRng; use hex; use hex::FromHexError; - +use rand::rngs::OsRng; pub struct Aes256GcmIv96Bit { pub key: GenericArray, } - impl Aes256GcmIv96Bit { pub fn new() -> Self { let mut key_bytes = [0u8; 32]; @@ -96,7 +94,6 @@ impl Aes256GcmIv96Bit { Err(_) => Err("Échec du décodage de la clé".to_string()), } } - } #[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] @@ -118,9 +115,8 @@ impl KeyEncryption { algorithm, } } - + pub fn encode(&self, data: String) -> CoreResult { - if let Some(ref key) = self.key { let decoded_key = Aes256GcmIv96Bit::import_key(key)?; let encrypted_data = decoded_key.encrypt_string(&data)?; @@ -140,7 +136,7 @@ impl KeyEncryption { } } - pub fn enc(&self, data: Value) -> String { + pub fn enc(&self, data: Value) -> String { let data_string = serde_json::to_string(&data).unwrap_or_else(|_| "".to_string()); self.encode(data_string).unwrap_or_else(|_| "".to_string()) } @@ -172,6 +168,6 @@ impl KeyEncryption { fn hex_to_generic_array(hex_string: &str) -> Result, FromHexError> { let byte_vec = hex::decode(hex_string)?; - let array = GenericArray::clone_from_slice(&byte_vec[..32]); + let array = GenericArray::clone_from_slice(&byte_vec[..32]); Ok(array) -} \ No newline at end of file +} diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index cdce897..d629df8 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -11,6 +11,8 @@ use wasm_bindgen::convert::FromWasmAbi; use wasm_bindgen::prelude::*; use sp_backend::spclient::SpendKey; +use sp_backend::spclient::{derive_keys_from_seed, OutputList, SpClient}; + type ApiResult = Result; const IS_TESTNET: bool = true; diff --git a/crates/sp_client/src/injecteurhtml.rs b/crates/sp_client/src/injecteurhtml.rs index 72e0c73..9a2ca73 100644 --- a/crates/sp_client/src/injecteurhtml.rs +++ b/crates/sp_client/src/injecteurhtml.rs @@ -2,7 +2,8 @@ use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn inject_html_create_id() -> String { - String::from(" + String::from( + "

Create an Id

@@ -22,7 +23,8 @@ pub fn inject_html_create_id() -> String {
- ") + ", + ) } #[wasm_bindgen] @@ -75,7 +77,8 @@ pub fn inject_html_revokeimage() -> String { #[wasm_bindgen] pub fn inject_html_revoke() -> String { - String::from(" + String::from( + "

Revoke an Id

@@ -95,5 +98,6 @@ pub fn inject_html_revoke() -> String {
- ") + ", + ) } diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index b9931a4..637b54a 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -1,8 +1,7 @@ #![allow(warnings)] +mod aesgcm; pub mod api; mod injecteurhtml; mod process; -mod user; -mod aesgcm; mod secretdata; - +mod user; diff --git a/crates/sp_client/src/process.rs b/crates/sp_client/src/process.rs index e4daebb..427481d 100644 --- a/crates/sp_client/src/process.rs +++ b/crates/sp_client/src/process.rs @@ -7,4 +7,4 @@ pub fn get_process() -> Vec { data_process.push(String::from("process2")); data_process.push(String::from("process3")); data_process -} \ No newline at end of file +} diff --git a/crates/sp_client/src/secretdata.rs b/crates/sp_client/src/secretdata.rs index d05e366..3d84b62 100644 --- a/crates/sp_client/src/secretdata.rs +++ b/crates/sp_client/src/secretdata.rs @@ -263,4 +263,4 @@ static GF256_LOG: [u8; 256] = [ 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab, 0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5, 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, 0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07, -]; \ No newline at end of file +]; diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index 9fdc76f..c4ebc87 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -1,33 +1,31 @@ +use anyhow::Error; use bitcoin::secp256k1::SecretKey; +use rand::{self, thread_rng, Rng, RngCore}; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; -use rand::{self, Rng,thread_rng, RngCore}; -use wasm_bindgen::JsValue; +use tsify::Tsify; use wasm_bindgen::prelude::*; +use wasm_bindgen::JsValue; use web_sys::console; -use anyhow::Error; -use crate::aesgcm::{Aes256GcmIv96Bit,KeyEncryption}; +use crate::aesgcm::{Aes256GcmIv96Bit, KeyEncryption}; use crate::secretdata::SecretData; -use hex; -use sha2::{Sha256, Digest}; use bytes::Bytes; +use hex; +use sha2::{Digest, Sha256}; use std::fs::File; -use crate::api::{generate_sp_wallet_return,generate_sp_wallet}; -use sp_backend::spclient::SpendKey; -use sp_backend::spclient::{SpClient, OutputList}; +use crate::api::{generate_sp_wallet, generate_sp_wallet_return}; use sp_backend::silentpayments::sending::SilentPaymentAddress; +use sp_backend::spclient::SpendKey; +use sp_backend::spclient::{OutputList, SpClient}; use img_parts::jpeg::Jpeg; use img_parts::{ImageEXIF, ImageICC}; use scrypt::{ - password_hash::{ - rand_core::OsRng, - PasswordHash, PasswordHasher, PasswordVerifier, SaltString - }, - Scrypt + password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString}, + Scrypt, }; //extern crate shamir; @@ -85,22 +83,38 @@ impl User { //part1 enc let pwd_hash_part1 = from_hex_to_b64(&sha_256(&format!("{}{}",password, &random_seed1))); + + //split recover spend key + let (part1_key, part2_key) = + priv_recover_spend_key.split_at(priv_recover_spend_key.len() / 2); + + //part1 enc + let pwd_hash_part1 = from_hex_to_b64(&sha_256(&format!("{}{}", password, &random_seed1))); let key_enc_part1 = KeyEncryption::new(None, Some(pwd_hash_part1.clone()), None); let part1_key_enc = key_enc_part1.enc_string(part1_key.to_string()); - //part2 enc + //part2 enc let pwd_hash_part2 = from_hex_to_b64(&sha_256(&format!("{}{}", password, random_seed2))); let key_enc_part2 = KeyEncryption::new(None, Some(pwd_hash_part2.clone()), None); let part2_key_enc = key_enc_part2.enc_string(part2_key.to_string()); - //image recover - let image_recover = ImageRecover::new(image_to_recover, &random_seed1, &random_seed2,&part1_key_enc); + //image recover + let image_recover = ImageRecover::new( + image_to_recover, + &random_seed1, + &random_seed2, + &part1_key_enc, + ); //image revoke //let priv_revoke_spend_key = wallet.priv_revoke_spend_key.to_owned(); //let priv_revoke_scan_key = wallet.priv_revoke_scan_key.to_owned(); - let image_revoke = ImageRevoke::new(image_to_revoke,&priv_revoke_spend_key,&priv_revoke_scan_key); + let image_revoke = ImageRevoke::new( + image_to_revoke, + &priv_revoke_spend_key, + &priv_revoke_scan_key, + ); //create shardings - let sharding = Sharding::new(&part2_key_enc, 10u8); //nMembers = 10 for testing, need to recover nmember elsewhere - //Pre ID - let pre_id = sha_256(&format!("{}{}",password, part2_key_enc)); + let sharding = Sharding::new(&part2_key_enc, 10u8); //nMembers = 10 for testing, need to recover nmember elsewhere + //Pre ID + let pre_id = sha_256(&format!("{}{}", password, part2_key_enc)); //Create PRDList //@todo @@ -109,144 +123,142 @@ impl User { //Receive List Items (PCD) console::log_1(&"authentication: ok".into()); - User {image_recover, + User { + image_recover, image_revoke, sharding, pre_id, - recovered_spend_key:None + recovered_spend_key: None, } } - pub fn login(&self,password: &str, image_recover: &[u8]) -> Option{ + pub fn login(&self, password: &str, image_recover: &[u8]) -> Option { let exif_image_bytes = read_exif(image_recover).unwrap_or_else(|error| { panic!("Unable to read the image exif: {}", error); }); - + let exif_image_string = String::from_utf8(exif_image_bytes.to_vec()).unwrap(); let exif_image_json: Value = serde_json::from_str(&exif_image_string).unwrap(); let random_seed1 = exif_image_json["random_seed1"].as_str().unwrap_or("N/A"); let random_seed2 = exif_image_json["random_seed2"].as_str().unwrap_or("N/A"); let part1_key_enc = exif_image_json["part1_key_enc"].as_str().unwrap_or("N/A"); - let part1_recovered = Self::recover_part1(password,random_seed1,part1_key_enc); - let part1_trimmed = part1_recovered.trim_matches('"'); - + let part1_recovered = Self::recover_part1(password, random_seed1, part1_key_enc); + let part1_trimmed = part1_recovered.trim_matches('"'); + //@todo: get shardings from member managers!! let shardings = self.sharding.shares_vec.clone(); // temporary - let part2_recovered = Self::recover_part2(&password,&random_seed2, shardings); - let part2_trimmed = part2_recovered.trim_matches('"'); + let part2_recovered = Self::recover_part2(&password, &random_seed2, shardings); + let part2_trimmed = part2_recovered.trim_matches('"'); let recover_key_hex: String = format!("{}{}", part1_trimmed, part2_trimmed); - + Some(recover_key_hex) } - fn recover_part1(password: &str, random_seed1: &str, part1_key_enc: & str) -> String{ - let pwd_hash_part1 = from_hex_to_b64(&sha_256(&format!("{}{}",password, random_seed1))); + fn recover_part1(password: &str, random_seed1: &str, part1_key_enc: &str) -> String { + let pwd_hash_part1 = from_hex_to_b64(&sha_256(&format!("{}{}", password, random_seed1))); let key_dec_part1 = KeyEncryption::new(None, Some(pwd_hash_part1), None); - let part1_key_recovered = key_dec_part1.decode(part1_key_enc.to_string()).unwrap_or_else(|_| "".to_string()); + let part1_key_recovered = key_dec_part1 + .decode(part1_key_enc.to_string()) + .unwrap_or_else(|_| "".to_string()); part1_key_recovered } - fn recover_part2(password: &str, random_seed2: &str, shares_vec: Vec>) -> String{ - let quorum_sharding = (Sharding::QUORUM_SHARD * f32::from(shares_vec.len() as u8)).round() as u8; + fn recover_part2(password: &str, random_seed2: &str, shares_vec: Vec>) -> String { + let quorum_sharding = + (Sharding::QUORUM_SHARD * f32::from(shares_vec.len() as u8)).round() as u8; let part2_key_enc = SecretData::recover_secret(quorum_sharding, shares_vec).unwrap(); - let pwd_hash_part2 = from_hex_to_b64(&sha_256(&format!("{}{}",password, random_seed2))); - let key_dec_part2 = KeyEncryption::new(None, Some(pwd_hash_part2), None); - let part2_key_recovered = key_dec_part2.decode(part2_key_enc).unwrap_or_else(|_| "".to_string()); + let pwd_hash_part2 = from_hex_to_b64(&sha_256(&format!("{}{}", password, random_seed2))); + let key_dec_part2 = KeyEncryption::new(None, Some(pwd_hash_part2), None); + let part2_key_recovered = key_dec_part2 + .decode(part2_key_enc) + .unwrap_or_else(|_| "".to_string()); part2_key_recovered - } - + } //not used - pub fn pbkdf2(password: &str, data: & str)->String { + pub fn pbkdf2(password: &str, data: &str) -> String { let data_salt = data.trim_end_matches('='); let salt = SaltString::from_b64(data_salt) - .map(|s| { s }) - .unwrap_or_else(|_| { - panic!("Failed to parse salt value from base64 string") - }); - - let mut password_hash = String::new(); + .map(|s| s) + .unwrap_or_else(|_| panic!("Failed to parse salt value from base64 string")); + + let mut password_hash = String::new(); if let Ok(pwd) = Scrypt.hash_password(password.as_bytes(), &salt) { - password_hash.push_str(&pwd.to_string()); + password_hash.push_str(&pwd.to_string()); } sha_256(&password_hash) - - } - - pub fn get_image_recover(&self)-> Vec{ + + pub fn get_image_recover(&self) -> Vec { return self.image_recover.image_recover_bytes.clone(); } - - pub fn get_exif_image(&self,image:&[u8])-> Vec{ - return read_exif(image).expect("Error reading the exif"); + + pub fn get_exif_image(&self, image: &[u8]) -> Vec { + return read_exif(image).expect("Error reading the exif"); } - pub fn get_image_revoke(&self)-> Vec{ + pub fn get_image_revoke(&self) -> Vec { return self.image_revoke.image_revoke_bytes.clone(); } // Test sharing JS side - pub fn get_shares(&self)->Vec{ + pub fn get_shares(&self) -> Vec { self.sharding.shares_format_str.clone() - } - + //Test sharing Js side - pub fn get_secret(&self,shardings: Vec)->String{ - let mut shares_vec = Vec::new(); - - for s in shardings.iter(){ - let bytes_vec: Vec = s + pub fn get_secret(&self, shardings: Vec) -> String { + let mut shares_vec = Vec::new(); + + for s in shardings.iter() { + let bytes_vec: Vec = s .trim_matches(|c| c == '[' || c == ']') .split(',') .filter_map(|s| s.trim().parse().ok()) .collect(); shares_vec.push(bytes_vec); - } self.sharding.recover_secrete(shares_vec.clone()) } - - } +} #[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct ImageRecover { - image_recover_bytes: Vec, + image_recover_bytes: Vec, } -impl ImageRecover{ - pub fn new(image_to_recover: &[u8], +impl ImageRecover { + pub fn new( + image_to_recover: &[u8], random_seed1: &str, random_seed2: &str, - part1_key_enc: &str, - ) -> Self{ - let data_exif_json = json!({ - "random_seed1": random_seed1, - "random_seed2": random_seed2, - "part1_key_enc": part1_key_enc - }); - - let data = serde_json::to_string(&data_exif_json).unwrap(); - let image_recover = write_exif(image_to_recover, &data); - ImageRecover{ - image_recover_bytes: image_recover.expect("Image recover not generated!") - } - } + part1_key_enc: &str, + ) -> Self { + let data_exif_json = json!({ + "random_seed1": random_seed1, + "random_seed2": random_seed2, + "part1_key_enc": part1_key_enc + }); + let data = serde_json::to_string(&data_exif_json).unwrap(); + let image_recover = write_exif(image_to_recover, &data); + ImageRecover { + image_recover_bytes: image_recover.expect("Image recover not generated!"), + } + } } #[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct ImageRevoke { - image_revoke_bytes: Vec, + image_revoke_bytes: Vec, } -impl ImageRevoke{ - pub fn new(image_to_revoke: &[u8], +impl ImageRevoke { + pub fn new( + image_to_revoke: &[u8], priv_revoke_spend_key: &str, priv_revoke_scan_key: &str, - - )->Self{ + ) -> Self { let data_exif_json = json!({ "priv_revoke_spend_key":priv_revoke_spend_key, "priv_revoke_scan_key":priv_revoke_scan_key @@ -254,73 +266,69 @@ impl ImageRevoke{ let data = serde_json::to_string(&data_exif_json).unwrap(); let image_revoke = write_exif(image_to_revoke, &data); - ImageRevoke{ - image_revoke_bytes: image_revoke.expect("Image revoke not generated!") + ImageRevoke { + image_revoke_bytes: image_revoke.expect("Image revoke not generated!"), } } - } - #[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Sharding { - shares_vec: Vec>, - shares_format_str: Vec, - + shares_vec: Vec>, + shares_format_str: Vec, } -impl Sharding{ - const QUORUM_SHARD: f32= 0.80_f32; - pub fn new( - part2_key_enc: &str, - number_members: u8, - )->Self{ - let secret_data = SecretData::with_secret(part2_key_enc, number_members); - let mut shares_format_str: Vec = Vec::new(); - let shares_vec = (1..=number_members).map(|i| match secret_data.get_share(i) - { +impl Sharding { + const QUORUM_SHARD: f32 = 0.80_f32; + pub fn new(part2_key_enc: &str, number_members: u8) -> Self { + let secret_data = SecretData::with_secret(part2_key_enc, number_members); + let mut shares_format_str: Vec = Vec::new(); + let shares_vec = (1..=number_members) + .map(|i| match secret_data.get_share(i) { Ok(share) => { - let string = format!("[{}]", share.clone().iter() - .map(|b| format!("{}", b)) - .collect::>() - .join(",")); + let string = format!( + "[{}]", + share + .clone() + .iter() + .map(|b| format!("{}", b)) + .collect::>() + .join(",") + ); shares_format_str.push(string.clone()); share - }, + } Err(_) => panic!("Not able to recover the shares!"), - } - ).collect::>(); - - Sharding{ + }) + .collect::>(); + + Sharding { shares_vec, - shares_format_str - + shares_format_str, } } - - pub fn recover_secrete(&self, shares: Vec>) -> String { + + pub fn recover_secrete(&self, shares: Vec>) -> String { let quorum_sharding = (Self::QUORUM_SHARD * f32::from(shares.len() as u8)).round() as u8; - SecretData::recover_secret(quorum_sharding, shares).unwrap() + SecretData::recover_secret(quorum_sharding, shares).unwrap() } } //associated functions -pub fn generate_random_key(length:usize) ->String { +pub fn generate_random_key(length: usize) -> String { let mut rng = rand::thread_rng(); - let random_bytes: Vec = (0..length) - .map(|_| rng.gen_range(0x00..=0xFF)) - .collect(); + let random_bytes: Vec = (0..length).map(|_| rng.gen_range(0x00..=0xFF)).collect(); base64::encode(random_bytes) } -pub fn sha_256(data: &str)-> String{ +pub fn sha_256(data: &str) -> String { let mut hasher = Sha256::new(); hasher.update(data); let result = hasher.finalize(); hex::encode(result) } - pub fn write_exif(image_to_recover: &[u8], data: &str) -> Result, String>{ +pub fn write_exif(image_to_recover: &[u8], data: &str) -> Result, String> { let image_to_recover_bytes = Bytes::from(image_to_recover.to_vec()); let mut jpeg = Jpeg::from_bytes(image_to_recover_bytes).unwrap(); let data_bytes = Bytes::from(data.as_bytes().to_vec()); @@ -330,45 +338,47 @@ pub fn sha_256(data: &str)-> String{ Ok(output_image.to_vec()) } - - pub fn read_exif(image: &[u8])->Result, String>{ +pub fn read_exif(image: &[u8]) -> Result, String> { let image_bytes = Bytes::from(image.to_vec()); let jpeg = Jpeg::from_bytes(image_bytes).unwrap(); - //exif out - let mut exif_image = Bytes::new(); - if let Some(ref meta) = jpeg.exif(){ - exif_image = meta.clone(); - }else { - return Err("No exif data".to_string()); - } - let exif_bytes =exif_image.as_ref(); - Ok(exif_bytes.to_vec()) + //exif out + let mut exif_image = Bytes::new(); + if let Some(ref meta) = jpeg.exif() { + exif_image = meta.clone(); + } else { + return Err("No exif data".to_string()); + } + let exif_bytes = exif_image.as_ref(); + Ok(exif_bytes.to_vec()) } //change for return Result? -pub fn from_hex_to_b58(hex_string: &str)-> String{ +pub fn from_hex_to_b58(hex_string: &str) -> String { let decoded_data = hex::decode(hex_string).expect("Failed to decode hex string"); let base58_string = bs58::encode(decoded_data).into_string(); - base58_string + base58_string } //change for return Result? -pub fn from_b58_to_hex(base58_string: &str)-> String{ +pub fn from_b58_to_hex(base58_string: &str) -> String { let decoded_data = bs58::decode(base58_string.to_owned()).into_vec().unwrap(); - let hex_string = decoded_data.iter().map(|b| format!("{:02x}", b)).collect::(); + let hex_string = decoded_data + .iter() + .map(|b| format!("{:02x}", b)) + .collect::(); hex_string } -fn from_b64_to_hex(base64_string:&str)->String{ +fn from_b64_to_hex(base64_string: &str) -> String { let decoded_data = base64::decode(base64_string).unwrap(); - let hex_string = decoded_data.iter().map(|b| format!("{:02x}", b)).collect::(); + let hex_string = decoded_data + .iter() + .map(|b| format!("{:02x}", b)) + .collect::(); hex_string } -fn from_hex_to_b64(hex_string:&str)->String{ +fn from_hex_to_b64(hex_string: &str) -> String { let decoded_data = hex::decode(hex_string).expect("Failed to decode hex string"); let base64_string = base64::encode(decoded_data); base64_string } - - - From 38beda800722b4cfcdae277dc0673d19b0e88fd0 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Sat, 23 Mar 2024 23:24:00 +0100 Subject: [PATCH 12/90] Create new user --- crates/sp_client/Cargo.toml | 2 - crates/sp_client/src/api.rs | 59 ++++- crates/sp_client/src/user.rs | 410 ++++++++++++++++++----------------- src/services.ts | 10 +- 4 files changed, 275 insertions(+), 206 deletions(-) diff --git a/crates/sp_client/Cargo.toml b/crates/sp_client/Cargo.toml index 771af5c..52fc7ed 100644 --- a/crates/sp_client/Cargo.toml +++ b/crates/sp_client/Cargo.toml @@ -30,8 +30,6 @@ img-parts = "0.3.0" bytes = "1.5.0" scrypt = "0.11.0" shamir = "2.0.0" -bitcoin = { version = "0.31.1", features = ["serde", "base64"] } - [dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index d629df8..8f14e6f 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -1,8 +1,9 @@ use rand::Rng; use anyhow::Error as AnyhowError; -use sp_backend::silentpayments::Error as SpError; use serde_json::Error as SerdeJsonError; +use sp_backend::silentpayments::Error as SpError; +use sp_backend::bitcoin::secp256k1::SecretKey; use serde::{Deserialize, Serialize}; use sp_backend::silentpayments::sending::SilentPaymentAddress; @@ -12,6 +13,9 @@ use wasm_bindgen::prelude::*; use sp_backend::spclient::SpendKey; use sp_backend::spclient::{derive_keys_from_seed, OutputList, SpClient}; +use web_sys::js_sys::JsString; + +use crate::user::User; type ApiResult = Result; @@ -24,19 +28,25 @@ struct ApiError { impl From for ApiError { fn from(value: AnyhowError) -> Self { - ApiError {message: value.to_string()} + ApiError { + message: value.to_string(), + } } } impl From for ApiError { fn from(value: SpError) -> Self { - ApiError { message: value.to_string() } + ApiError { + message: value.to_string(), + } } } impl From for ApiError { fn from(value: SerdeJsonError) -> Self { - ApiError { message: value.to_string() } + ApiError { + message: value.to_string(), + } } } @@ -104,3 +114,44 @@ pub fn get_receiving_address(sp_client: String) -> String { let sp_client: SpClient = serde_json::from_str(&sp_client).unwrap(); sp_client.get_receiving_address() } + +#[wasm_bindgen] +pub fn create_user( + recover_wallet: String, + revoke_wallet: String, + password: JsString, + image_to_recover: &[u8], + image_to_revoke: &[u8], +) -> ApiResult { + let recover_sp_client: SpClient = serde_json::from_str(&recover_wallet)?; + let revoke_sp_client: SpClient = serde_json::from_str(&revoke_wallet)?; + let recover_spend_key: SecretKey = match recover_sp_client.get_spend_key() { + SpendKey::Secret(sk) => sk, + SpendKey::Public(_) => { + return Err(ApiError { + message: "Can't create user from a watch-only sp_client".to_owned(), + }) + } + }; + let revoke_spend_key: SecretKey = match revoke_sp_client.get_spend_key() { + SpendKey::Secret(sk) => sk, + SpendKey::Public(_) => { + return Err(ApiError { + message: "Can't create user from a watch-only sp_client".to_owned(), + }) + } + }; + + let revoke_scan_key = revoke_sp_client.get_scan_key(); + + let user = User::new( + recover_spend_key, + revoke_spend_key, + revoke_scan_key, + &password, + image_to_recover, + image_to_revoke, + )?; + + Ok(user) +} diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index c4ebc87..be1c61b 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -1,21 +1,37 @@ -use anyhow::Error; -use bitcoin::secp256k1::SecretKey; +use aes::cipher::generic_array::GenericArray; +use aes_gcm::aead::Aead; +use aes_gcm::AeadCore; +use aes_gcm::KeyInit; +use aes_gcm::{aead::Buffer, Aes256Gcm, Key}; +use anyhow::{Error, Result}; +use bytes::Buf; use rand::{self, thread_rng, Rng, RngCore}; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; +use sp_backend::bitcoin::hashes::Hash; +use sp_backend::bitcoin::hashes::HashEngine; +use sp_backend::bitcoin::hex::{DisplayHex, FromHex}; +use sp_backend::bitcoin::secp256k1::SecretKey; use tsify::Tsify; use wasm_bindgen::prelude::*; use wasm_bindgen::JsValue; use web_sys::console; +use web_sys::js_sys::JsString; use crate::aesgcm::{Aes256GcmIv96Bit, KeyEncryption}; -use crate::secretdata::SecretData; +// use crate::secretdata::SecretData; use bytes::Bytes; use hex; use sha2::{Digest, Sha256}; +use shamir::SecretData; use std::fs::File; +use std::io::Read; +use std::io::Write; +use std::str::FromStr; use crate::api::{generate_sp_wallet, generate_sp_wallet_return}; +use sp_backend::bitcoin::secp256k1::constants::SECRET_KEY_SIZE; +use sp_backend::silentpayments::bitcoin_hashes::sha256; use sp_backend::silentpayments::sending::SilentPaymentAddress; use sp_backend::spclient::SpendKey; use sp_backend::spclient::{OutputList, SpClient}; @@ -31,90 +47,100 @@ use scrypt::{ //extern crate shamir; //use shamir::SecretData; - -#[wasm_bindgen] -#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Debug, Serialize, Deserialize, Clone, Tsify)] +#[tsify(into_wasm_abi, from_wasm_abi)] pub struct User { - image_recover: ImageRecover, - image_revoke: ImageRevoke, - sharding: Sharding, - pre_id: String, - recovered_spend_key: Option, + image_recover: BackUpImage, + image_revoke: BackUpImage, + sharding: Sharding, + pre_id: String, + recovered_spend_key: Option, } -#[wasm_bindgen] impl User { - #[wasm_bindgen(constructor)] - pub fn new(new_password: &str, image_to_recover: &[u8], image_to_revoke: &[u8]) -> Self { - - let password = new_password.to_string(); - let random_seed1 = generate_random_key(32); - let random_seed2 = generate_random_key(32); - //wallet recover - let wallet_rec: String = match generate_sp_wallet(None,50000, true) { - Some(sp_wallet) => sp_wallet.sp_client_json, - None => panic!("No wallet recover available"), - }; - let sp_client_rec: SpClient = serde_json::from_str(&wallet_rec).unwrap(); - let priv_recover_scan_key_bytes = sp_client_rec.get_scan_key().secret_bytes(); - let priv_recover_scan_key = from_b64_to_hex(&base64::encode(priv_recover_scan_key_bytes)); - let priv_recover_spend_key_bytes = match sp_client_rec.get_spend_key(){ - SpendKey::Secret(key)=> key.secret_bytes(), - SpendKey::Public(_) => panic!("No recover spend key created on Signet"), - }; - let priv_recover_spend_key = from_b64_to_hex(&base64::encode(priv_recover_spend_key_bytes)); - console::log_2(&"priv_recover_spend_key".into(),&JsValue::from_str(&priv_recover_spend_key)); - //wallet revoke - let wallet_rev: String = match generate_sp_wallet(None, 50000, true) { - Some(sp_wallet) => sp_wallet.sp_client_json, - None => panic!("No wallet revoke available"), - }; - let sp_client_rev: SpClient = serde_json::from_str(&wallet_rec).unwrap(); - let priv_revoke_scan_key_bytes = sp_client_rev.get_scan_key().secret_bytes(); - let priv_revoke_scan_key = from_b64_to_hex(&base64::encode(priv_revoke_scan_key_bytes)); - let priv_revoke_spend_key_bytes = match sp_client_rev.get_spend_key(){ - SpendKey::Secret(key)=> key.secret_bytes(), - SpendKey::Public(_) => panic!("No revoke spend key created on Signet"), - }; - let priv_revoke_spend_key = from_b64_to_hex(&base64::encode(priv_revoke_spend_key_bytes)); - - //split recover spend key - let (part1_key, part2_key) = priv_recover_spend_key.split_at(priv_recover_spend_key.len()/2); - - //part1 enc - let pwd_hash_part1 = from_hex_to_b64(&sha_256(&format!("{}{}",password, &random_seed1))); + pub fn new( + recover_spend_key: SecretKey, + revoke_spend_key: SecretKey, + revoke_scan_key: SecretKey, + user_password: &JsString, + recover_image: &[u8], + revoke_image: &[u8], + ) -> Result { + // image revoke + // We just take the 2 revoke keys and put it in the revoke_img file + let mut revoke_data = [0u8; SECRET_KEY_SIZE * 2]; + revoke_data[..SECRET_KEY_SIZE].copy_from_slice(revoke_scan_key.as_ref()); + revoke_data[SECRET_KEY_SIZE..].copy_from_slice(revoke_spend_key.as_ref()); - //split recover spend key - let (part1_key, part2_key) = - priv_recover_spend_key.split_at(priv_recover_spend_key.len() / 2); + let revoke_img_with_data = BackUpImage::new_revoke(revoke_image, &revoke_data)?; + + // split recover spend key + let (part1_key, part2_key) = recover_spend_key.as_ref().split_at(SECRET_KEY_SIZE / 2); + let mut recover_data = Vec::::with_capacity(88); + + // generate 2 tokens of 32B entropy + let mut entropy_1 = [0u8; 32]; + entropy_1.copy_from_slice(&generate_random_key(32)); + let mut entropy_2 = [0u8; 32]; + entropy_2.copy_from_slice(&generate_random_key(32)); + + recover_data.extend_from_slice(&entropy_1); + recover_data.extend_from_slice(&entropy_2); + + // convert the password in a Vec + // Be careful of javascript strings: https://rustwasm.github.io/wasm-bindgen/reference/types/str.html#utf-16-vs-utf-8 + assert!(user_password.is_valid_utf16()); + let password: String = user_password.into(); + + // hash the concatenation + let mut engine = sha256::HashEngine::default(); + engine.write_all(&password.as_bytes()); + engine.write_all(&entropy_1); + let hash1 = sha256::Hash::from_engine(engine); + + // take it as a AES key + let key1: &Key = hash1.as_byte_array().try_into()?; + let cipher = Aes256Gcm::new(&key1); + + // encrypt the part1 of the key + let nonce1 = Aes256Gcm::generate_nonce(&mut thread_rng()); + let nonce2 = Aes256Gcm::generate_nonce(&mut thread_rng()); + let cipher_recover_part1 = cipher + .encrypt(&nonce1, part1_key) + .map_err(|e| anyhow::Error::msg(format!("{}", e)))?; + + log::debug!("cipher_part1 length: {}", cipher_recover_part1.len()); + + recover_data.extend_from_slice(&nonce1); + recover_data.extend_from_slice(&nonce2); + recover_data.extend_from_slice(&cipher_recover_part1); - //part1 enc - let pwd_hash_part1 = from_hex_to_b64(&sha_256(&format!("{}{}", password, &random_seed1))); - let key_enc_part1 = KeyEncryption::new(None, Some(pwd_hash_part1.clone()), None); - let part1_key_enc = key_enc_part1.enc_string(part1_key.to_string()); - //part2 enc - let pwd_hash_part2 = from_hex_to_b64(&sha_256(&format!("{}{}", password, random_seed2))); - let key_enc_part2 = KeyEncryption::new(None, Some(pwd_hash_part2.clone()), None); - let part2_key_enc = key_enc_part2.enc_string(part2_key.to_string()); //image recover - let image_recover = ImageRecover::new( - image_to_recover, - &random_seed1, - &random_seed2, - &part1_key_enc, - ); - //image revoke - //let priv_revoke_spend_key = wallet.priv_revoke_spend_key.to_owned(); - //let priv_revoke_scan_key = wallet.priv_revoke_scan_key.to_owned(); - let image_revoke = ImageRevoke::new( - image_to_revoke, - &priv_revoke_spend_key, - &priv_revoke_scan_key, - ); + let recover_img_with_data = BackUpImage::new_recover(recover_image, &recover_data)?; + + // encrypt the part 2 of the key + let mut engine = sha256::HashEngine::default(); + engine.write_all(&password.as_bytes()); + engine.write_all(&entropy_2); + let hash2 = sha256::Hash::from_engine(engine); + + // take it as a AES key + let key2: &Key = hash2.as_byte_array().try_into()?; + let cipher = Aes256Gcm::new(&key2); + + // encrypt the part2 of the key + let cipher_recover_part2 = cipher + .encrypt(&nonce2, part2_key) + .map_err(|e| anyhow::Error::msg(format!("{}", e)))?; + //create shardings - let sharding = Sharding::new(&part2_key_enc, 10u8); //nMembers = 10 for testing, need to recover nmember elsewhere - //Pre ID - let pre_id = sha_256(&format!("{}{}", password, part2_key_enc)); + let sharding = Sharding::new(&cipher_recover_part2.to_lower_hex_string(), 10u8); //nMembers = 10 for testing, need to recover nmember elsewhere + + //Pre ID + let mut engine = sha256::HashEngine::default(); + engine.write_all(&password.as_bytes()); + engine.write_all(&cipher_recover_part1); + let pre_id = sha256::Hash::from_engine(engine); //Create PRDList //@todo @@ -122,86 +148,118 @@ impl User { //@todo //Receive List Items (PCD) - console::log_1(&"authentication: ok".into()); - User { - image_recover, - image_revoke, + Ok(User { + image_recover: recover_img_with_data, + image_revoke: revoke_img_with_data, sharding, - pre_id, + pre_id: pre_id.to_string(), recovered_spend_key: None, - } + }) } - pub fn login(&self, password: &str, image_recover: &[u8]) -> Option { - let exif_image_bytes = read_exif(image_recover).unwrap_or_else(|error| { - panic!("Unable to read the image exif: {}", error); - }); + pub fn login(&self, user_password: JsString, image_recover: &[u8]) -> Result { + let mut retrieved_key = [0u8; 32]; + let mut entropy1 = [0u8; 32]; + let mut entropy2 = [0u8; 32]; + let mut nonce1 = [0u8; 12]; + let mut nonce2 = [0u8; 12]; + let mut part1_ciphertext = Vec::with_capacity(32); // just a guess - let exif_image_string = String::from_utf8(exif_image_bytes.to_vec()).unwrap(); - let exif_image_json: Value = serde_json::from_str(&exif_image_string).unwrap(); - let random_seed1 = exif_image_json["random_seed1"].as_str().unwrap_or("N/A"); - let random_seed2 = exif_image_json["random_seed2"].as_str().unwrap_or("N/A"); - let part1_key_enc = exif_image_json["part1_key_enc"].as_str().unwrap_or("N/A"); - let part1_recovered = Self::recover_part1(password, random_seed1, part1_key_enc); - let part1_trimmed = part1_recovered.trim_matches('"'); + assert!(user_password.is_valid_utf16()); + let password: String = user_password.into(); - //@todo: get shardings from member managers!! + let exif_image_bytes = + Bytes::from(read_exif(image_recover).map_err(|e| Error::msg(format!("{}", e)))?); + let mut reader = exif_image_bytes.reader(); + reader.read_exact(&mut entropy1)?; + reader.read_exact(&mut entropy2)?; + reader.read_exact(&mut nonce1)?; + reader.read_exact(&mut nonce2)?; + reader.read_to_end(&mut part1_ciphertext)?; + + retrieved_key[..16].copy_from_slice(&Self::recover_part1( + &password, + &entropy1, + &nonce1, + &part1_ciphertext, + )?); + + //@todo: get shardings from member managers! let shardings = self.sharding.shares_vec.clone(); // temporary - let part2_recovered = Self::recover_part2(&password, &random_seed2, shardings); - let part2_trimmed = part2_recovered.trim_matches('"'); - let recover_key_hex: String = format!("{}{}", part1_trimmed, part2_trimmed); + retrieved_key[16..].copy_from_slice(&Self::recover_part2( + &password, &entropy2, &nonce2, shardings, + )?); - Some(recover_key_hex) + let key = SecretKey::from_slice(&retrieved_key)?; + + Ok(key) } - fn recover_part1(password: &str, random_seed1: &str, part1_key_enc: &str) -> String { - let pwd_hash_part1 = from_hex_to_b64(&sha_256(&format!("{}{}", password, random_seed1))); - let key_dec_part1 = KeyEncryption::new(None, Some(pwd_hash_part1), None); - let part1_key_recovered = key_dec_part1 - .decode(part1_key_enc.to_string()) - .unwrap_or_else(|_| "".to_string()); - part1_key_recovered + fn recover_part1( + password: &str, + entropy: &[u8], + nonce: &[u8], + part1_ciphertext: &[u8], + ) -> Result> { + let mut engine = sha256::HashEngine::default(); + engine.write_all(&password.as_bytes()); + engine.write_all(&entropy); + let hash = sha256::Hash::from_engine(engine); + + let key: &Key = hash.as_byte_array().try_into()?; + let cipher = Aes256Gcm::new(&key); + + cipher + .decrypt(nonce.into(), part1_ciphertext) + .map_err(|e| anyhow::Error::msg(format!("{}", e))) } - fn recover_part2(password: &str, random_seed2: &str, shares_vec: Vec>) -> String { - let quorum_sharding = - (Sharding::QUORUM_SHARD * f32::from(shares_vec.len() as u8)).round() as u8; - let part2_key_enc = SecretData::recover_secret(quorum_sharding, shares_vec).unwrap(); - let pwd_hash_part2 = from_hex_to_b64(&sha_256(&format!("{}{}", password, random_seed2))); - let key_dec_part2 = KeyEncryption::new(None, Some(pwd_hash_part2), None); - let part2_key_recovered = key_dec_part2 - .decode(part2_key_enc) - .unwrap_or_else(|_| "".to_string()); - part2_key_recovered + fn recover_part2( + password: &str, + entropy: &[u8], + nonce: &[u8], + shares_vec: Vec>, + ) -> Result> { + let mut engine = sha256::HashEngine::default(); + engine.write_all(&password.as_bytes()); + engine.write_all(&entropy); + let hash = sha256::Hash::from_engine(engine); + + let shares_total: f32 = u8::try_from(shares_vec.len())?.try_into()?; + let quorum_sharding: u8 = (Sharding::QUORUM_SHARD * shares_total).round() as u8; + + let part2_key_enc = Vec::from_hex( + &SecretData::recover_secret(quorum_sharding, shares_vec) + .ok_or_else(|| anyhow::Error::msg("Failed to retrieve the sharded secret"))?, + )?; + + let key: &Key = hash.as_byte_array().try_into()?; + let cipher = Aes256Gcm::new(&key); + + cipher + .decrypt(nonce.into(), &*part2_key_enc) + .map_err(|e| anyhow::Error::msg(format!("{}", e))) } //not used - pub fn pbkdf2(password: &str, data: &str) -> String { - let data_salt = data.trim_end_matches('='); - let salt = SaltString::from_b64(data_salt) - .map(|s| s) - .unwrap_or_else(|_| panic!("Failed to parse salt value from base64 string")); + // pub fn pbkdf2(password: &str, data: &str) -> String { + // let data_salt = data.trim_end_matches('='); + // let salt = SaltString::from_b64(data_salt) + // .map(|s| s) + // .unwrap_or_else(|_| panic!("Failed to parse salt value from base64 string")); - let mut password_hash = String::new(); - if let Ok(pwd) = Scrypt.hash_password(password.as_bytes(), &salt) { - password_hash.push_str(&pwd.to_string()); - } - sha_256(&password_hash) - } - - pub fn get_image_recover(&self) -> Vec { - return self.image_recover.image_recover_bytes.clone(); - } + // let mut password_hash = String::new(); + // if let Ok(pwd) = Scrypt.hash_password(password.as_bytes(), &salt) { + // password_hash.push_str(&pwd.to_string()); + // } + // sha_256(&password_hash) + // } pub fn get_exif_image(&self, image: &[u8]) -> Vec { return read_exif(image).expect("Error reading the exif"); } - pub fn get_image_revoke(&self) -> Vec { - return self.image_revoke.image_revoke_bytes.clone(); - } - // Test sharing JS side pub fn get_shares(&self) -> Vec { self.sharding.shares_format_str.clone() @@ -223,52 +281,21 @@ impl User { } } -#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct ImageRecover { - image_recover_bytes: Vec, +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum BackUpImage { + Recover(Vec), + Revoke(Vec), } -impl ImageRecover { - pub fn new( - image_to_recover: &[u8], - random_seed1: &str, - random_seed2: &str, - part1_key_enc: &str, - ) -> Self { - let data_exif_json = json!({ - "random_seed1": random_seed1, - "random_seed2": random_seed2, - "part1_key_enc": part1_key_enc - }); - - let data = serde_json::to_string(&data_exif_json).unwrap(); - let image_recover = write_exif(image_to_recover, &data); - ImageRecover { - image_recover_bytes: image_recover.expect("Image recover not generated!"), - } +impl BackUpImage { + pub fn new_recover(image: &[u8], data: &[u8]) -> Result { + let img = write_exif(image, data)?; + Ok(Self::Recover(img)) } -} -#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct ImageRevoke { - image_revoke_bytes: Vec, -} -impl ImageRevoke { - pub fn new( - image_to_revoke: &[u8], - priv_revoke_spend_key: &str, - priv_revoke_scan_key: &str, - ) -> Self { - let data_exif_json = json!({ - "priv_revoke_spend_key":priv_revoke_spend_key, - "priv_revoke_scan_key":priv_revoke_scan_key - }); - - let data = serde_json::to_string(&data_exif_json).unwrap(); - let image_revoke = write_exif(image_to_revoke, &data); - ImageRevoke { - image_revoke_bytes: image_revoke.expect("Image revoke not generated!"), - } + pub fn new_revoke(image: &[u8], data: &[u8]) -> Result { + let img = write_exif(image, data)?; + Ok(Self::Recover(img)) } } @@ -315,27 +342,20 @@ impl Sharding { } //associated functions -pub fn generate_random_key(length: usize) -> String { +pub fn generate_random_key(length: usize) -> Vec { let mut rng = rand::thread_rng(); - let random_bytes: Vec = (0..length).map(|_| rng.gen_range(0x00..=0xFF)).collect(); - base64::encode(random_bytes) + let mut entropy = Vec::::with_capacity(length); + rng.fill_bytes(&mut entropy); + entropy } -pub fn sha_256(data: &str) -> String { - let mut hasher = Sha256::new(); - hasher.update(data); - let result = hasher.finalize(); - hex::encode(result) -} - -pub fn write_exif(image_to_recover: &[u8], data: &str) -> Result, String> { - let image_to_recover_bytes = Bytes::from(image_to_recover.to_vec()); - let mut jpeg = Jpeg::from_bytes(image_to_recover_bytes).unwrap(); - let data_bytes = Bytes::from(data.as_bytes().to_vec()); +pub fn write_exif(image_to_recover: &[u8], data: &[u8]) -> Result> { + let mut jpeg = Jpeg::from_bytes(Bytes::from(image_to_recover.to_vec()))?; + let data_bytes = Bytes::from(data.to_owned()); jpeg.set_exif(Some(data_bytes)); let output_image_bytes = jpeg.encoder().bytes(); - let output_image = output_image_bytes.as_ref(); - Ok(output_image.to_vec()) + let output_image = output_image_bytes.to_vec(); + Ok(output_image) } pub fn read_exif(image: &[u8]) -> Result, String> { diff --git a/src/services.ts b/src/services.ts index 3669c66..d6a65c6 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,4 +1,4 @@ -import { GenerateSpWalletReturn } from '../dist/pkg/sdk_client'; +import { generate_sp_wallet_return, User } from '../dist/pkg/sdk_client'; import IndexedDB from './database' import Processstore from './store/processstore'; import Userstore from './store/userstore'; @@ -26,7 +26,7 @@ class Services { this.sdkClient.setup(); } - public new_sp_client(label: string, current_tip: number, is_testnet: boolean): GenerateSpWalletReturn { + public new_sp_client(label: string, current_tip: number, is_testnet: boolean): generate_sp_wallet_return { return this.sdkClient.generate_sp_wallet(label, current_tip, is_testnet); } @@ -91,12 +91,12 @@ class Services { if (!Services.instance.isPasswordValid(password)) return; // TODO get secretpart1 from User object - // const user = new this.sdkClient.User(password); - let secretpart1 = "LKHGKJJJ3H"; + // const user: User = new this.sdkClient.create_user(password); + const user: User = this.sdkClient.create_user(password); + // let secretpart1 = "LKHGKJJJ3H"; try { let userstore = new Userstore; - userstore.secretpart1 = secretpart1; userstore.process = process; const indexedDb = await IndexedDB.getInstance(); const db = indexedDb.getDb(); From 40267ea224b8b969f264b08cd1f5ede39c12833d Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Mon, 25 Mar 2024 11:13:36 +0100 Subject: [PATCH 13/90] target --- crates/sp_client/src/api.rs | 36 ++++++++++------------------------ crates/sp_client/src/crypto.rs | 9 +++++++++ 2 files changed, 19 insertions(+), 26 deletions(-) create mode 100644 crates/sp_client/src/crypto.rs diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 8f14e6f..5674539 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -2,8 +2,8 @@ use rand::Rng; use anyhow::Error as AnyhowError; use serde_json::Error as SerdeJsonError; -use sp_backend::silentpayments::Error as SpError; use sp_backend::bitcoin::secp256k1::SecretKey; +use sp_backend::silentpayments::Error as SpError; use serde::{Deserialize, Serialize}; use sp_backend::silentpayments::sending::SilentPaymentAddress; @@ -59,9 +59,9 @@ impl Into for ApiError { #[derive(Tsify, Serialize, Deserialize)] #[tsify(into_wasm_abi)] #[allow(non_camel_case_types)] -pub struct generate_sp_wallet_return { - pub sp_client_json: String, - pub sp_outputs_json: String, +pub struct generate_create_user_return { + pub user: User, + pub output_list: OutputList } #[wasm_bindgen] @@ -69,7 +69,6 @@ pub fn setup() { wasm_logger::init(wasm_logger::Config::default()); } -#[wasm_bindgen] pub fn generate_sp_wallet( label: Option, birthday: u32, @@ -117,32 +116,17 @@ pub fn get_receiving_address(sp_client: String) -> String { #[wasm_bindgen] pub fn create_user( - recover_wallet: String, - revoke_wallet: String, password: JsString, image_to_recover: &[u8], image_to_revoke: &[u8], + label: Option, + birthday: u32, ) -> ApiResult { - let recover_sp_client: SpClient = serde_json::from_str(&recover_wallet)?; - let revoke_sp_client: SpClient = serde_json::from_str(&revoke_wallet)?; - let recover_spend_key: SecretKey = match recover_sp_client.get_spend_key() { - SpendKey::Secret(sk) => sk, - SpendKey::Public(_) => { - return Err(ApiError { - message: "Can't create user from a watch-only sp_client".to_owned(), - }) - } - }; - let revoke_spend_key: SecretKey = match revoke_sp_client.get_spend_key() { - SpendKey::Secret(sk) => sk, - SpendKey::Public(_) => { - return Err(ApiError { - message: "Can't create user from a watch-only sp_client".to_owned(), - }) - } - }; - let revoke_scan_key = revoke_sp_client.get_scan_key(); + // todo: struct with sp_client{revoke, recover, main} + let sp_client_recover = generate_sp_wallet(label, birthday, true)?; + let sp_client_revoke = generate_sp_wallet(label, birthday, true)?; + let sp_client_main = generate_sp_wallet(label, birthday, false)?; let user = User::new( recover_spend_key, diff --git a/crates/sp_client/src/crypto.rs b/crates/sp_client/src/crypto.rs new file mode 100644 index 0000000..0372315 --- /dev/null +++ b/crates/sp_client/src/crypto.rs @@ -0,0 +1,9 @@ +use aes_gcm; + +pub enum KeyType { + Aes256GcmIv96BitKey([u8;32]) +} + +pub struct EncryptionKey { + sk: KeyType +} From 19eb1b66ab5ef7d93deeb79cf37c8fcbd02b39ec Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Mon, 25 Mar 2024 23:02:04 +0100 Subject: [PATCH 14/90] encryption refactoring --- crates/sp_client/src/aesgcm.rs | 295 ++++++++++++++++----------------- crates/sp_client/src/user.rs | 118 ++++++------- 2 files changed, 195 insertions(+), 218 deletions(-) diff --git a/crates/sp_client/src/aesgcm.rs b/crates/sp_client/src/aesgcm.rs index 20882cf..e0e2b13 100644 --- a/crates/sp_client/src/aesgcm.rs +++ b/crates/sp_client/src/aesgcm.rs @@ -1,173 +1,168 @@ -/* This module is temporary. We'll use the module described in key_encription -module defined in sdk_common repository! Some of the methods there were copied here. -*/ -use core::result::Result as CoreResult; -use rand::RngCore; +use std::collections::HashMap; + +use anyhow::{Error, Result}; +use sp_backend::{ + bitcoin::{ + consensus::serde::hex, + hex::DisplayHex, + key::constants::SECRET_KEY_SIZE, + secp256k1::{ecdh::SharedSecret, SecretKey}, + Txid, + }, + silentpayments::sending::SilentPaymentAddress, +}; use wasm_bindgen::JsValue; -use web_sys::console; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; -use aes::cipher::consts::U32; use aes::cipher::generic_array::GenericArray; -use aes_gcm::{ - aead::{AeadInPlace, KeyInit}, - Aes256Gcm, +use aes::{ + cipher::consts::{U32, U8}, + Aes256, }; -use hex; -use hex::FromHexError; -use rand::rngs::OsRng; +use aes_gcm::{ + aead::{Aead, AeadInPlace, KeyInit, Nonce}, + AeadCore, Aes256Gcm, AesGcm, Key, TagSize, +}; +use rand::{thread_rng, RngCore}; -pub struct Aes256GcmIv96Bit { - pub key: GenericArray, +const HALFKEYSIZE: usize = SECRET_KEY_SIZE / 2; + +pub type HalfKey = [u8; HALFKEYSIZE]; + +pub enum EncryptionTarget { + Login(HalfKey), } -impl Aes256GcmIv96Bit { - pub fn new() -> Self { - let mut key_bytes = [0u8; 32]; - OsRng.fill_bytes(&mut key_bytes); - let key = GenericArray::from_slice(&key_bytes); - Aes256GcmIv96Bit { key: key.clone() } - } - - pub fn encrypt(&self, data: &[u8]) -> CoreResult, aes_gcm::Error> { - let cipher = Aes256Gcm::new(&self.key); - let mut nonce = [0u8; 12]; - OsRng.fill_bytes(&mut nonce); - - let mut buffer = data.to_vec(); - cipher.encrypt_in_place(GenericArray::from_slice(&nonce), b"", &mut buffer)?; - - Ok([nonce.to_vec(), buffer].concat()) - } - - pub fn decrypt(&self, data: &[u8]) -> CoreResult, aes_gcm::Error> { - if data.len() < 12 { - return Err(aes_gcm::Error); // Remplacer par une erreur appropriée - } - - let (nonce, encrypted_data) = data.split_at(12); - let mut buffer = encrypted_data.to_vec(); - let cipher = Aes256Gcm::new(&self.key); - cipher.decrypt_in_place(GenericArray::from_slice(nonce), b"", &mut buffer)?; - - Ok(buffer) - } - - pub fn encrypt_string(&self, data: &str) -> CoreResult { - match self.encrypt(data.as_bytes()) { - Ok(encrypted_data) => Ok(base64::encode(encrypted_data)), - Err(_) => Err("Erreur de chiffrement".to_string()), - } - } - - pub fn decrypt_string(&self, data: &str) -> CoreResult { - let decoded_data = match base64::decode(data) { - Ok(data) => data, - Err(_) => return Err("Erreur de décodage Base64".to_string()), - }; - - match self.decrypt(&decoded_data) { - Ok(decrypted_data) => match String::from_utf8(decrypted_data) { - Ok(text) => Ok(text), - Err(_) => Err("Erreur de conversion UTF-8".to_string()), - }, - Err(_) => Err("Erreur de déchiffrement".to_string()), - } - } - - pub fn export_key(&self) -> String { - base64::encode(&self.key) - } - - pub fn import_key(encoded_key: &str) -> CoreResult { - match base64::decode(encoded_key) { - Ok(decoded_key) => { - if decoded_key.len() == 32 { - let key = GenericArray::from_slice(&decoded_key); - Ok(Aes256GcmIv96Bit { key: key.clone() }) - } else { - Err("La taille de la clé n'est pas valide".to_string()) - } - } - Err(_) => Err("Échec du décodage de la clé".to_string()), - } - } +pub enum DecryptionTarget { + Login, } -#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct KeyEncryption { - pub attribute_name: Option, - pub key: Option, - pub algorithm: Option, +pub enum PlainText { + Login(HalfKey), } -impl KeyEncryption { +pub type CipherText = Vec; + +pub struct Aes256Decryption { + target: DecryptionTarget, + aes_key: [u8; 32], + nonce: [u8; 12], + cipher_text: CipherText, +} + +impl Aes256Decryption { pub fn new( - attribute_name: Option, - key: Option, - algorithm: Option, - ) -> Self { - KeyEncryption { - attribute_name, - key, - algorithm, + target: DecryptionTarget, + encrypted_aes_key: Vec, + shared_secret: SharedSecret, + cipher_text: CipherText, + ) -> Result { + if encrypted_aes_key.len() <= 12 { + return Err(Error::msg("encrypted_aes_key is shorter than nonce length")); + } + // take the first 12 bytes form encrypted_aes_key as nonce + let (decrypt_key_nonce, encrypted_key) = encrypted_aes_key.split_at(12); + // decrypt key with shared_secret obtained from transaction + let decrypt_key_cipher = Aes256Gcm::new_from_slice(shared_secret.as_ref()) + .map_err(|e| Error::msg(format!("{}", e)))?; + let aes_key_plain = decrypt_key_cipher + .decrypt(decrypt_key_nonce.into(), encrypted_key) + .map_err(|e| Error::msg(format!("{}", e)))?; + if aes_key_plain.len() != 32 { + return Err(Error::msg("Invalid length for decrypted key")); + } + let mut aes_key = [0u8; 32]; + aes_key.copy_from_slice(&aes_key_plain); + if cipher_text.len() <= 12 { + return Err(Error::msg("cipher_text is shorter than nonce lenght")); + } + let (message_nonce, message_cipher) = cipher_text.split_at(12); + let mut nonce = [0u8; 12]; + nonce.copy_from_slice(message_nonce); + Ok(Self { + target, + aes_key, + nonce, + cipher_text: message_cipher.to_vec(), + }) + } + + pub fn decrypt_with_key(&self) -> Result { + match self.target { + DecryptionTarget::Login => self.decrypt_login() } } - pub fn encode(&self, data: String) -> CoreResult<String, String> { - if let Some(ref key) = self.key { - let decoded_key = Aes256GcmIv96Bit::import_key(key)?; - let encrypted_data = decoded_key.encrypt_string(&data)?; - Ok(encrypted_data) - } else { - Err("Aucune clé n'est définie".to_string()) + fn decrypt_login(&self) -> Result<PlainText> { + let cipher = Aes256Gcm::new(&self.aes_key.into()); + let plain = cipher + .decrypt(&self.nonce.into(), &*self.cipher_text) + .map_err(|e| Error::msg(format!("{}", e)))?; + if plain.len() != SECRET_KEY_SIZE / 2 { + return Err(Error::msg("Plain text of invalid lenght for a login")); } - } - - pub fn decode(&self, encrypted_data: String) -> CoreResult<String, String> { - if let Some(ref key) = self.key { - let decoded_key = Aes256GcmIv96Bit::import_key(key)?; - let decrypted_data = decoded_key.decrypt_string(&encrypted_data)?; - Ok(decrypted_data) - } else { - Err("Aucune clé n'est définie".to_string()) - } - } - - pub fn enc(&self, data: Value) -> String { - let data_string = serde_json::to_string(&data).unwrap_or_else(|_| "".to_string()); - self.encode(data_string).unwrap_or_else(|_| "".to_string()) - } - pub fn enc_string(&self, data: String) -> String { - self.enc(Value::String(data)) - } - pub fn enc_i64(&self, data: i64) -> String { - self.enc(Value::Number(data.into())) - } - pub fn enc_u64(&self, data: u64) -> String { - self.enc(Value::Number(data.into())) - } - pub fn enc_u32(&self, data: u32) -> String { - self.enc(Value::Number(data.into())) - } - pub fn enc_vec_string(&self, list: Vec<String>) -> String { - self.enc(Value::Array(list.into_iter().map(Value::String).collect())) - } - pub fn enc_vec_key_encryption(&self, list: Vec<KeyEncryption>) -> String { - // Utilisez `serde_json::to_value` pour convertir chaque `KeyEncryption` en `Value` - let json_list: Vec<Value> = list - .into_iter() - .map(|key_enc| serde_json::to_value(key_enc).unwrap_or_else(|_| json!({}))) - .collect(); - - self.enc(Value::Array(json_list)) + let mut key_half = [0u8; SECRET_KEY_SIZE / 2]; + key_half.copy_from_slice(&plain); + Ok(PlainText::Login(key_half)) } } -fn hex_to_generic_array(hex_string: &str) -> Result<GenericArray<u8, U32>, FromHexError> { - let byte_vec = hex::decode(hex_string)?; - let array = GenericArray::clone_from_slice(&byte_vec[..32]); - Ok(array) +pub struct Aes256Encryption { + pub target: EncryptionTarget, + aes_key: [u8; 32], + nonce: [u8; 12], + shared_secrets: HashMap<Txid, HashMap<SilentPaymentAddress, SharedSecret>>, +} + +impl Aes256Encryption { + pub fn new(target: EncryptionTarget) -> Result<Self> { + let mut rng = thread_rng(); + let aes_key: [u8; 32] = Aes256Gcm::generate_key(&mut rng).into(); + let nonce: [u8; 12] = Aes256Gcm::generate_nonce(&mut rng).into(); + Ok(Self { + target, + aes_key, + nonce, + shared_secrets: HashMap::new(), + }) + } + + pub fn set_shared_secret( + &mut self, + shared_secrets: HashMap<Txid, HashMap<SilentPaymentAddress, SharedSecret>>, + ) -> Result<()> { + unimplemented!(); + } + + pub fn import_key( + target: EncryptionTarget, + aes_key: [u8; 32], + nonce: [u8; 12], + ) -> Result<Self> { + Ok(Self { + target, + aes_key, + nonce, + shared_secrets: HashMap::new(), + }) + } + + pub fn encrypt_with_aes_key(&self) -> Result<CipherText> { + match self.target { + EncryptionTarget::Login(half_key) => self.encrypt_login(half_key), + } + } + + fn encrypt_login(&self, plaintext: HalfKey) -> Result<CipherText> { + let cipher = Aes256Gcm::new(&self.aes_key.into()); + let cipher_text = cipher + .encrypt(&self.nonce.into(), plaintext.as_slice()) + .map_err(|e| Error::msg(format!("{}", e)))?; + let mut res = Vec::with_capacity(self.nonce.len() + cipher_text.len()); + res.extend_from_slice(&self.nonce); + res.extend_from_slice(&cipher_text); + Ok(res) + } } diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index be1c61b..3c9e9c2 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -5,6 +5,7 @@ use aes_gcm::KeyInit; use aes_gcm::{aead::Buffer, Aes256Gcm, Key}; use anyhow::{Error, Result}; use bytes::Buf; +use js_sys::JsString; use rand::{self, thread_rng, Rng, RngCore}; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; @@ -15,21 +16,14 @@ use sp_backend::bitcoin::secp256k1::SecretKey; use tsify::Tsify; use wasm_bindgen::prelude::*; use wasm_bindgen::JsValue; -use web_sys::console; -use web_sys::js_sys::JsString; -use crate::aesgcm::{Aes256GcmIv96Bit, KeyEncryption}; -// use crate::secretdata::SecretData; use bytes::Bytes; -use hex; -use sha2::{Digest, Sha256}; use shamir::SecretData; use std::fs::File; use std::io::Read; use std::io::Write; use std::str::FromStr; -use crate::api::{generate_sp_wallet, generate_sp_wallet_return}; use sp_backend::bitcoin::secp256k1::constants::SECRET_KEY_SIZE; use sp_backend::silentpayments::bitcoin_hashes::sha256; use sp_backend::silentpayments::sending::SilentPaymentAddress; @@ -39,10 +33,8 @@ use sp_backend::spclient::{OutputList, SpClient}; use img_parts::jpeg::Jpeg; use img_parts::{ImageEXIF, ImageICC}; -use scrypt::{ - password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString}, - Scrypt, -}; +use crate::aesgcm::HalfKey; +use crate::aesgcm::{Aes256Encryption, EncryptionTarget}; //extern crate shamir; //use shamir::SecretData; @@ -66,6 +58,8 @@ impl User { recover_image: &[u8], revoke_image: &[u8], ) -> Result<Self> { + let mut rng = thread_rng(); + // image revoke // We just take the 2 revoke keys and put it in the revoke_img file let mut revoke_data = [0u8; SECRET_KEY_SIZE * 2]; @@ -76,20 +70,18 @@ impl User { // split recover spend key let (part1_key, part2_key) = recover_spend_key.as_ref().split_at(SECRET_KEY_SIZE / 2); - let mut recover_data = Vec::<u8>::with_capacity(88); + let mut recover_data = Vec::<u8>::with_capacity(64); // 32 * 2 // generate 2 tokens of 32B entropy - let mut entropy_1 = [0u8; 32]; - entropy_1.copy_from_slice(&generate_random_key(32)); - let mut entropy_2 = [0u8; 32]; - entropy_2.copy_from_slice(&generate_random_key(32)); + let mut entropy_1: [u8; 32] = Aes256Gcm::generate_key(&mut rng).into(); + let mut entropy_2: [u8; 32] = Aes256Gcm::generate_key(&mut rng).into(); recover_data.extend_from_slice(&entropy_1); recover_data.extend_from_slice(&entropy_2); - // convert the password in a Vec<u8> + // convert the password in a String, i.e. a Vec<u8> // Be careful of javascript strings: https://rustwasm.github.io/wasm-bindgen/reference/types/str.html#utf-16-vs-utf-8 - assert!(user_password.is_valid_utf16()); + assert!(user_password.is_valid_utf16()); // we can think better than panicking in this case let password: String = user_password.into(); // hash the concatenation @@ -99,20 +91,17 @@ impl User { let hash1 = sha256::Hash::from_engine(engine); // take it as a AES key - let key1: &Key<Aes256Gcm> = hash1.as_byte_array().try_into()?; - let cipher = Aes256Gcm::new(&key1); + let part1_encryption = Aes256Encryption::import_key( + EncryptionTarget::Login(part1_key.try_into()?), + hash1.to_byte_array(), + Aes256Gcm::generate_nonce(&mut rng).into(), + )?; // encrypt the part1 of the key - let nonce1 = Aes256Gcm::generate_nonce(&mut thread_rng()); - let nonce2 = Aes256Gcm::generate_nonce(&mut thread_rng()); - let cipher_recover_part1 = cipher - .encrypt(&nonce1, part1_key) - .map_err(|e| anyhow::Error::msg(format!("{}", e)))?; + let cipher_recover_part1 = part1_encryption.encrypt_with_aes_key()?; log::debug!("cipher_part1 length: {}", cipher_recover_part1.len()); - recover_data.extend_from_slice(&nonce1); - recover_data.extend_from_slice(&nonce2); recover_data.extend_from_slice(&cipher_recover_part1); //image recover @@ -125,13 +114,14 @@ impl User { let hash2 = sha256::Hash::from_engine(engine); // take it as a AES key - let key2: &Key<Aes256Gcm> = hash2.as_byte_array().try_into()?; - let cipher = Aes256Gcm::new(&key2); + let part2_encryption = Aes256Encryption::import_key( + EncryptionTarget::Login(part2_key.try_into()?), + hash2.to_byte_array(), + Aes256Gcm::generate_nonce(&mut rng).into(), + )?; // encrypt the part2 of the key - let cipher_recover_part2 = cipher - .encrypt(&nonce2, part2_key) - .map_err(|e| anyhow::Error::msg(format!("{}", e)))?; + let cipher_recover_part2 = part2_encryption.encrypt_with_aes_key()?; //create shardings let sharding = Sharding::new(&cipher_recover_part2.to_lower_hex_string(), 10u8); //nMembers = 10 for testing, need to recover nmember elsewhere @@ -341,14 +331,6 @@ impl Sharding { } } -//associated functions -pub fn generate_random_key(length: usize) -> Vec<u8> { - let mut rng = rand::thread_rng(); - let mut entropy = Vec::<u8>::with_capacity(length); - rng.fill_bytes(&mut entropy); - entropy -} - pub fn write_exif(image_to_recover: &[u8], data: &[u8]) -> Result<Vec<u8>> { let mut jpeg = Jpeg::from_bytes(Bytes::from(image_to_recover.to_vec()))?; let data_bytes = Bytes::from(data.to_owned()); @@ -373,32 +355,32 @@ pub fn read_exif(image: &[u8]) -> Result<Vec<u8>, String> { Ok(exif_bytes.to_vec()) } -//change for return Result? -pub fn from_hex_to_b58(hex_string: &str) -> String { - let decoded_data = hex::decode(hex_string).expect("Failed to decode hex string"); - let base58_string = bs58::encode(decoded_data).into_string(); - base58_string -} -//change for return Result? -pub fn from_b58_to_hex(base58_string: &str) -> String { - let decoded_data = bs58::decode(base58_string.to_owned()).into_vec().unwrap(); - let hex_string = decoded_data - .iter() - .map(|b| format!("{:02x}", b)) - .collect::<String>(); - hex_string -} +// //change for return Result? +// pub fn from_hex_to_b58(hex_string: &str) -> String { +// let decoded_data = hex::decode(hex_string).expect("Failed to decode hex string"); +// let base58_string = bs58::encode(decoded_data).into_string(); +// base58_string +// } +// //change for return Result? +// pub fn from_b58_to_hex(base58_string: &str) -> String { +// let decoded_data = bs58::decode(base58_string.to_owned()).into_vec().unwrap(); +// let hex_string = decoded_data +// .iter() +// .map(|b| format!("{:02x}", b)) +// .collect::<String>(); +// hex_string +// } -fn from_b64_to_hex(base64_string: &str) -> String { - let decoded_data = base64::decode(base64_string).unwrap(); - let hex_string = decoded_data - .iter() - .map(|b| format!("{:02x}", b)) - .collect::<String>(); - hex_string -} -fn from_hex_to_b64(hex_string: &str) -> String { - let decoded_data = hex::decode(hex_string).expect("Failed to decode hex string"); - let base64_string = base64::encode(decoded_data); - base64_string -} +// fn from_b64_to_hex(base64_string: &str) -> String { +// let decoded_data = base64::decode(base64_string).unwrap(); +// let hex_string = decoded_data +// .iter() +// .map(|b| format!("{:02x}", b)) +// .collect::<String>(); +// hex_string +// } +// fn from_hex_to_b64(hex_string: &str) -> String { +// let decoded_data = hex::decode(hex_string).expect("Failed to decode hex string"); +// let base64_string = base64::encode(decoded_data); +// base64_string +// } From 09709869b203a79648674d01599a9f8c82b0a95d Mon Sep 17 00:00:00 2001 From: franck <franck.petretto@atos.net> Date: Tue, 26 Mar 2024 10:30:04 +0100 Subject: [PATCH 15/90] Utilisation de create_user, suppression du bouchon processstore --- src/services.ts | 82 ++++++++++++++++++++---------------------- src/store/userstore.ts | 15 -------- 2 files changed, 39 insertions(+), 58 deletions(-) delete mode 100644 src/store/userstore.ts diff --git a/src/services.ts b/src/services.ts index d6a65c6..25f36b1 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,7 +1,6 @@ import { generate_sp_wallet_return, User } from '../dist/pkg/sdk_client'; import IndexedDB from './database' import Processstore from './store/processstore'; -import Userstore from './store/userstore'; class Services { private static instance: Services; @@ -52,7 +51,7 @@ class Services { public async isNewUser(): Promise<boolean> { let isNew = false; try { - let listUserProcess = await Services.instance.getAllUserProces(); + let listUserProcess = await Services.instance.getAllUserProcess(); if (listUserProcess.length == 0) { isNew = true; } @@ -66,7 +65,7 @@ class Services { Services.instance.injectHtml(Services.instance.get_html_create_id()); Services.instance.attachSubmitListener("form4nk", Services.instance.createId); Services.instance.attachClickListener("displayrecover", Services.instance.displayRecover); - Services.instance.displayProcess(await Services.instance.getAllProcesAvailable()); + Services.instance.displayProcess(await Services.instance.getAllProcessAvailable()); } public get_html_create_id(): string { @@ -90,36 +89,50 @@ class Services { // To comment if test if (!Services.instance.isPasswordValid(password)) return; - // TODO get secretpart1 from User object - // const user: User = new this.sdkClient.create_user(password); - const user: User = this.sdkClient.create_user(password); - // let secretpart1 = "LKHGKJJJ3H"; + const image_to_recover = Services.instance.getImage("assets/4nk_image.jpeg"); + const image_to_revoke = Services.instance.getImage("assets/revoke.jpeg"); + let label = null; + let birthday = 50000; + const user: User = this.sdkClient.create_user(password, image_to_recover, image_to_revoke, label, birthday); try { - let userstore = new Userstore; - userstore.process = process; const indexedDb = await IndexedDB.getInstance(); const db = indexedDb.getDb(); - - await indexedDb.writeObject(db, indexedDb.getStoreList().AnkUser, userstore, process); - console.log("JS Userstore added"); + await indexedDb.writeObject(db, indexedDb.getStoreList().AnkUser, user, process); + console.log("JS User added"); await indexedDb.writeObject(db, indexedDb.getStoreList().AnkSession, process, Services.CURRENT_PROCESS); console.log("JS Sessionstore added currentprocess"); } catch (error) { - console.error("Failed to write userstore object :", error); + console.error("Failed to write user object :", error); } await Services.instance.displayRevokeImage(); } + private async getImage(imageUrl:string): Promise<Uint8Array|null> { + let imageBytes = null; + try { + const response = await fetch(imageUrl); + if (!response.ok) { + throw new Error(`Failed to fetch image: ${response.status} ${response.statusText}`); + } + const arrayBuffer = await response.arrayBuffer(); + imageBytes = new Uint8Array(arrayBuffer); + console.log(imageBytes); + } catch (error) { + console.error("Failed to get image : "+imageUrl, error); + } + return imageBytes; + } + public async displayRecover(): Promise<void> { Services.instance.injectHtml(Services.instance.get_html_recover()); Services.instance.attachSubmitListener("form4nk", Services.instance.recover); Services.instance.attachClickListener("displaycreateid", Services.instance.displayCreateId); Services.instance.attachClickListener("displayrevoke", Services.instance.displayRevoke); Services.instance.attachClickListener("submitButtonRevoke", Services.instance.revoke); - Services.instance.displayProcess(await Services.instance.getAllUserProces()); + Services.instance.displayProcess(await Services.instance.getAllUserProcess()); } public get_html_recover(): string { @@ -205,7 +218,7 @@ class Services { console.log("JS Processstore not exist "); } } catch (error) { - console.error("Failed to retrieve userstore object :", error); + console.error("Failed to retrieve user object :", error); } Services.instance.injectUpdateAnIdHtml(body, style, script, inputName); @@ -260,31 +273,33 @@ class Services { } } - public async getAllUserProces(): Promise<string[]> { + public async getAllUserProcess(): Promise<string[]> { let userProcessList: string[] = []; try { const indexedDB = await IndexedDB.getInstance(); const db = indexedDB.getDb(); - let userListObject = await indexedDB.getAll<Userstore>(db, indexedDB.getStoreList().AnkUser); + let userListObject = await indexedDB.getAll<User>(db, indexedDB.getStoreList().AnkUser); userListObject.forEach(async (userObject) => { - const processName = userObject.process; + // TODO get processname + //const processName = userObject.process; + const processName = "process1"; userProcessList.push(processName); - console.log("JS Userstore found"); + console.log("JS User found"); }) } catch (error) { - console.log("JS Userstore not found"); + console.log("JS User not found"); } return userProcessList; } - public async getAllProcesAvailable(): Promise<string[]> { - let userProcessList = await Services.instance.getAllUserProces(); - let processList = await Services.instance.getAllProces(); + public async getAllProcessAvailable(): Promise<string[]> { + let userProcessList = await Services.instance.getAllUserProcess(); + let processList = await Services.instance.getAllProcess(); let availableProcessList = processList.filter(x => !userProcessList.includes(x)); return availableProcessList; } - public async getAllProces(): Promise<string[]> { + public async getAllProcess(): Promise<string[]> { // if indexedDB is empty, get list from wasm let processList: string[] = []; try { @@ -319,25 +334,6 @@ class Services { return processList; } - private async getSecretPart1(process: string): Promise<string> { - let secretpart1 = ""; - try { - const indexedDB = await IndexedDB.getInstance(); - const db = indexedDB.getDb(); - try { - let userObject = await indexedDB.getObject<Userstore>(db, indexedDB.getStoreList().AnkUser, process); - secretpart1 = userObject.secretpart1; - console.log("JS Userstore exist secretpart1 : "+secretpart1); - } catch (error) { - console.log("JS Userstore not exist "); - } - } catch (error) { - console.error("Failed to retrieve userstore object :", error); - } - console.log("JS secretpart1 : "+secretpart1); - - return secretpart1; - } public attachClickListener(elementId: string, callback: (event: Event) => void): void { const element = document.getElementById(elementId); diff --git a/src/store/userstore.ts b/src/store/userstore.ts deleted file mode 100644 index d450008..0000000 --- a/src/store/userstore.ts +++ /dev/null @@ -1,15 +0,0 @@ -class Userstore { - process: string; - secretpart1: string; - password: string; - createDate: Date; - - constructor() { - this.process = ""; - this.secretpart1 = ""; - this.password = ""; - this.createDate = new Date; - } -} - -export default Userstore; From 744f792b97c52f9f6b38877ab5179b71b424f93b Mon Sep 17 00:00:00 2001 From: franck <franck.petretto@atos.net> Date: Tue, 26 Mar 2024 15:23:48 +0100 Subject: [PATCH 16/90] Ajout mock liste des membres d'un process --- src/services.ts | 52 +++++++++++++++++++-------------------- src/store/processstore.ts | 8 +++--- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/src/services.ts b/src/services.ts index 25f36b1..980e861 100644 --- a/src/services.ts +++ b/src/services.ts @@ -48,16 +48,18 @@ class Services { } - public async isNewUser(): Promise<boolean> { + public async isNewUser(): Promise<boolean> { let isNew = false; try { - let listUserProcess = await Services.instance.getAllUserProcess(); - if (listUserProcess.length == 0) { + const indexedDB = await IndexedDB.getInstance(); + const db = indexedDB.getDb(); + let userListObject = await indexedDB.getAll<User>(db, indexedDB.getStoreList().AnkUser); + if (userListObject.length == 0) { isNew = true; } } catch (error) { console.error("Failed to retrieve isNewUser :", error); - } + } return isNew; } @@ -65,7 +67,7 @@ class Services { Services.instance.injectHtml(Services.instance.get_html_create_id()); Services.instance.attachSubmitListener("form4nk", Services.instance.createId); Services.instance.attachClickListener("displayrecover", Services.instance.displayRecover); - Services.instance.displayProcess(await Services.instance.getAllProcessAvailable()); + Services.instance.displayProcess(await Services.instance.getAllProcess()); } public get_html_create_id(): string { @@ -89,7 +91,7 @@ class Services { // To comment if test if (!Services.instance.isPasswordValid(password)) return; - const image_to_recover = Services.instance.getImage("assets/4nk_image.jpeg"); + const image_to_recover = Services.instance.getImage("assets/4nk_image.png"); const image_to_revoke = Services.instance.getImage("assets/revoke.jpeg"); let label = null; let birthday = 50000; @@ -204,7 +206,6 @@ class Services { let body = ""; let style = ""; let script = ""; - let inputName = ""; try { const indexedDB = await IndexedDB.getInstance(); const db = indexedDB.getDb(); @@ -213,7 +214,6 @@ class Services { body = processObject.html; style = processObject.style; script = processObject.script; - inputName = processObject.inputName; } catch (error) { console.log("JS Processstore not exist "); } @@ -221,11 +221,11 @@ class Services { console.error("Failed to retrieve user object :", error); } - Services.instance.injectUpdateAnIdHtml(body, style, script, inputName); + Services.instance.injectUpdateAnIdHtml(body, style, script); Services.instance.attachSubmitListener("form4nk", Services.instance.updateAnId); } - public injectUpdateAnIdHtml(bodyToInject: string, styleToInject: string, scriptToInject: string, inputName: string) { + public injectUpdateAnIdHtml(bodyToInject: string, styleToInject: string, scriptToInject: string) { console.log("JS html : "+bodyToInject); const body = document.getElementsByTagName('body')[0]; @@ -258,6 +258,8 @@ class Services { console.log("JS updateAnId submit "); // TODO alert("updateAnId submit to do ... Name : "+firstName.value + " "+lastName.value); + + // TODO Mock add user member to process } public displayProcess(processList: string[]): void { @@ -272,33 +274,29 @@ class Services { }) } } - + public async getAllUserProcess(): Promise<string[]> { let userProcessList: string[] = []; try { const indexedDB = await IndexedDB.getInstance(); const db = indexedDB.getDb(); - let userListObject = await indexedDB.getAll<User>(db, indexedDB.getStoreList().AnkUser); - userListObject.forEach(async (userObject) => { - // TODO get processname - //const processName = userObject.process; - const processName = "process1"; - userProcessList.push(processName); - console.log("JS User found"); + let processListObject = await indexedDB.getAll<Processstore>(db, indexedDB.getStoreList().AnkProcess); + processListObject.forEach(async (processObject) => { + const listMember = processObject.listMember; + const processName = processObject.process; + listMember.forEach(async (member) => { + if (member == "user1") { + userProcessList.push(processName); + console.log("JS UserProcess found"); + } + }) }) } catch (error) { - console.log("JS User not found"); - } + console.log("JS Processstore not found"); + } return userProcessList; } - public async getAllProcessAvailable(): Promise<string[]> { - let userProcessList = await Services.instance.getAllUserProcess(); - let processList = await Services.instance.getAllProcess(); - let availableProcessList = processList.filter(x => !userProcessList.includes(x)); - return availableProcessList; - } - public async getAllProcess(): Promise<string[]> { // if indexedDB is empty, get list from wasm let processList: string[] = []; diff --git a/src/store/processstore.ts b/src/store/processstore.ts index 39cabee..76eb6b5 100644 --- a/src/store/processstore.ts +++ b/src/store/processstore.ts @@ -3,7 +3,7 @@ class Processstore { html: string; style: string; script: string; - inputName: string; + listMember: string[]; createDate: Date; constructor() { @@ -12,7 +12,7 @@ class Processstore { this.style = getMockStyle(); this.script = getMockScript(); this.script = getMockScript(); - this.inputName = getMockinputName(); + this.listMember = getMockListMember(); this.createDate = new Date; } } @@ -232,6 +232,6 @@ function getMockScript(): string { return script; } -function getMockinputName(): string { - return "firstName"; +function getMockListMember(): string[] { + return ["user1","user2","user3"]; } \ No newline at end of file From 0ba5bc0e2aebbf959ab9fd60cd941fb1b0b9d870 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Tue, 26 Mar 2024 17:18:34 +0100 Subject: [PATCH 17/90] aesgcm refactoring + unit tests --- crates/sp_client/src/aesgcm.rs | 303 ++++++++++++++++++++++++++++----- 1 file changed, 265 insertions(+), 38 deletions(-) diff --git a/crates/sp_client/src/aesgcm.rs b/crates/sp_client/src/aesgcm.rs index e0e2b13..0539f7e 100644 --- a/crates/sp_client/src/aesgcm.rs +++ b/crates/sp_client/src/aesgcm.rs @@ -29,40 +29,57 @@ use rand::{thread_rng, RngCore}; const HALFKEYSIZE: usize = SECRET_KEY_SIZE / 2; -pub type HalfKey = [u8; HALFKEYSIZE]; +pub struct HalfKey([u8; HALFKEYSIZE]); -pub enum EncryptionTarget { - Login(HalfKey), +impl TryFrom<Vec<u8>> for HalfKey { + type Error = anyhow::Error; + fn try_from(value: Vec<u8>) -> std::prelude::v1::Result<Self, Error> { + if value.len() == HALFKEYSIZE { + let mut buf = [0u8; HALFKEYSIZE]; + buf.copy_from_slice(&value); + Ok(HalfKey(buf)) + } else { + Err(Error::msg("Invalid length for HalfKey")) + } + } } -pub enum DecryptionTarget { +impl HalfKey { + pub fn as_slice(&self) -> &[u8] { + &self.0 + } + + pub fn to_inner(&self) -> Vec<u8> { + self.0.to_vec() + } +} + +pub enum Purpose { Login, } -pub enum PlainText { - Login(HalfKey), -} - pub type CipherText = Vec<u8>; +pub type EncryptedKey = Vec<u8>; + pub struct Aes256Decryption { - target: DecryptionTarget, + pub purpose: Purpose, + cipher_text: CipherText, aes_key: [u8; 32], nonce: [u8; 12], - cipher_text: CipherText, } impl Aes256Decryption { pub fn new( - target: DecryptionTarget, + purpose: Purpose, + cipher_text: CipherText, encrypted_aes_key: Vec<u8>, shared_secret: SharedSecret, - cipher_text: CipherText, ) -> Result<Self> { if encrypted_aes_key.len() <= 12 { return Err(Error::msg("encrypted_aes_key is shorter than nonce length")); - } - // take the first 12 bytes form encrypted_aes_key as nonce + } // Actually we could probably test that if the remnant is not a multiple of 32, something's wrong + // take the first 12 bytes form encrypted_aes_key as nonce let (decrypt_key_nonce, encrypted_key) = encrypted_aes_key.split_at(12); // decrypt key with shared_secret obtained from transaction let decrypt_key_cipher = Aes256Gcm::new_from_slice(shared_secret.as_ref()) @@ -76,26 +93,29 @@ impl Aes256Decryption { let mut aes_key = [0u8; 32]; aes_key.copy_from_slice(&aes_key_plain); if cipher_text.len() <= 12 { - return Err(Error::msg("cipher_text is shorter than nonce lenght")); + return Err(Error::msg("cipher_text is shorter than nonce length")); } let (message_nonce, message_cipher) = cipher_text.split_at(12); let mut nonce = [0u8; 12]; nonce.copy_from_slice(message_nonce); Ok(Self { - target, + purpose, + cipher_text: message_cipher.to_vec(), aes_key, nonce, - cipher_text: message_cipher.to_vec(), }) } - pub fn decrypt_with_key(&self) -> Result<PlainText> { - match self.target { - DecryptionTarget::Login => self.decrypt_login() + pub fn decrypt_with_key(&self) -> Result<Vec<u8>> { + match self.purpose { + Purpose::Login => { + let half_key = self.decrypt_login()?; + Ok(half_key.to_inner()) + } } } - fn decrypt_login(&self) -> Result<PlainText> { + fn decrypt_login(&self) -> Result<HalfKey> { let cipher = Aes256Gcm::new(&self.aes_key.into()); let plain = cipher .decrypt(&self.nonce.into(), &*self.cipher_text) @@ -105,44 +125,70 @@ impl Aes256Decryption { } let mut key_half = [0u8; SECRET_KEY_SIZE / 2]; key_half.copy_from_slice(&plain); - Ok(PlainText::Login(key_half)) + Ok(HalfKey(key_half)) } } pub struct Aes256Encryption { - pub target: EncryptionTarget, + pub purpose: Purpose, + plaintext: Vec<u8>, aes_key: [u8; 32], nonce: [u8; 12], shared_secrets: HashMap<Txid, HashMap<SilentPaymentAddress, SharedSecret>>, } impl Aes256Encryption { - pub fn new(target: EncryptionTarget) -> Result<Self> { + pub fn new(purpose: Purpose, plaintext: Vec<u8>) -> Result<Self> { let mut rng = thread_rng(); let aes_key: [u8; 32] = Aes256Gcm::generate_key(&mut rng).into(); let nonce: [u8; 12] = Aes256Gcm::generate_nonce(&mut rng).into(); - Ok(Self { - target, - aes_key, - nonce, - shared_secrets: HashMap::new(), - }) + Self::import_key(purpose, plaintext, aes_key, nonce) } pub fn set_shared_secret( &mut self, shared_secrets: HashMap<Txid, HashMap<SilentPaymentAddress, SharedSecret>>, - ) -> Result<()> { - unimplemented!(); + ) { + self.shared_secrets = shared_secrets; + } + + pub fn encrypt_keys_with_shared_secrets( + &self, + ) -> Result<HashMap<SilentPaymentAddress, EncryptedKey>> { + let mut res = HashMap::new(); + let mut rng = thread_rng(); + + for (_, sp_address2shared_secret) in self.shared_secrets.iter() { + for (sp_address, shared_secret) in sp_address2shared_secret { + let cipher = Aes256Gcm::new_from_slice(shared_secret.as_ref()) + .map_err(|e| Error::msg(format!("{}", e)))?; + let nonce = Aes256Gcm::generate_nonce(&mut rng); + let encrypted_key = cipher + .encrypt(&nonce, self.aes_key.as_slice()) + .map_err(|e| Error::msg(format!("{}", e)))?; + + let mut ciphertext = Vec::<u8>::with_capacity(nonce.len() + encrypted_key.len()); + ciphertext.extend(nonce); + ciphertext.extend(encrypted_key); + + res.insert(sp_address.to_owned(), ciphertext); + } + } + Ok(res) } pub fn import_key( - target: EncryptionTarget, + purpose: Purpose, + plaintext: Vec<u8>, aes_key: [u8; 32], nonce: [u8; 12], ) -> Result<Self> { + if plaintext.len() == 0 { + return Err(Error::msg("Can't create encryption for an empty message")); + } Ok(Self { - target, + purpose, + plaintext, aes_key, nonce, shared_secrets: HashMap::new(), @@ -150,15 +196,16 @@ impl Aes256Encryption { } pub fn encrypt_with_aes_key(&self) -> Result<CipherText> { - match self.target { - EncryptionTarget::Login(half_key) => self.encrypt_login(half_key), + match self.purpose { + Purpose::Login => self.encrypt_login(), } } - fn encrypt_login(&self, plaintext: HalfKey) -> Result<CipherText> { + fn encrypt_login(&self) -> Result<CipherText> { + let half_key: HalfKey = self.plaintext.clone().try_into()?; let cipher = Aes256Gcm::new(&self.aes_key.into()); let cipher_text = cipher - .encrypt(&self.nonce.into(), plaintext.as_slice()) + .encrypt(&self.nonce.into(), half_key.as_slice()) .map_err(|e| Error::msg(format!("{}", e)))?; let mut res = Vec::with_capacity(self.nonce.len() + cipher_text.len()); res.extend_from_slice(&self.nonce); @@ -166,3 +213,183 @@ impl Aes256Encryption { Ok(res) } } + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use super::*; + + const ALICE_SP_ADDRESS: &str = "tsp1qqw3lqr6xravz9nf8ntazgwwl0fqv47kfjdxsnxs6eutavqfwyv5q6qk97mmyf6dtkdyzqlu2zv6h9j2ggclk7vn705q5u2phglpq7yw3dg5rwpdz"; + const BOB_SP_ADDRESS: &str = "tsp1qq2hlsgrj0gz8kcfkf9flqw5llz0u2vr04telqndku9mcqm6dl4fhvq60t8r78srrf56w9yr7w9e9dusc2wjqc30up6fjwnh9mw3e3veqegdmtf08"; + const TRANSACTION: &str = "4e6d03dec558e1b6624f813bf2da7cd8d8fb1c2296684c08cf38724dcfd8d10b"; + const ALICE_SHARED_SECRET: &str = "ccf02d364c2641ca129a3fdf49de57b705896e233f7ba6d738991993ea7e2106"; + const BOB_SHARED_SECRET: &str = "15ef3e377fb842e81de52dbaaea8ba30aeb051a81043ee19264afd27353da521"; + + #[test] + fn new_aes_empty_plaintext() { + let plaintext = Vec::new(); + let aes_enc = Aes256Encryption::new(Purpose::Login, plaintext); + + assert!(aes_enc.is_err()); + } + + #[test] + fn aes_encrypt_login_invalid_length() { + let plaintext = "example"; + let aes_enc_short = Aes256Encryption::new(Purpose::Login, plaintext.as_bytes().to_vec()); + + assert!(aes_enc_short.is_ok()); + + let cipher = aes_enc_short.unwrap().encrypt_with_aes_key(); + + assert!(cipher.is_err()); + + let plaintext = [1u8; 64]; + let aes_enc_long = Aes256Encryption::new(Purpose::Login, plaintext.to_vec()); + + assert!(aes_enc_long.is_ok()); + + let cipher = aes_enc_long.unwrap().encrypt_with_aes_key(); + + assert!(cipher.is_err()); + } + + #[test] + fn aes_encrypt_login() { + let plaintext = [1u8; HALFKEYSIZE]; + let aes_enc = Aes256Encryption::new(Purpose::Login, plaintext.to_vec()); + + assert!(aes_enc.is_ok()); + + let cipher = aes_enc.unwrap().encrypt_with_aes_key(); + + assert!(cipher.is_ok()); + } + + #[test] + fn aes_encrypt_key() { + let plaintext = [1u8; HALFKEYSIZE]; + let mut aes_enc = Aes256Encryption::new(Purpose::Login, plaintext.to_vec()).unwrap(); + + let mut shared_secrets: HashMap<Txid, _> = HashMap::new(); + let mut sp_address2shared_secrets: HashMap<SilentPaymentAddress, SharedSecret> = + HashMap::new(); + sp_address2shared_secrets.insert( + ALICE_SP_ADDRESS.try_into().unwrap(), + SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap(), + ); + shared_secrets.insert( + Txid::from_str(TRANSACTION).unwrap(), + sp_address2shared_secrets, + ); + + aes_enc.set_shared_secret(shared_secrets); + + let sp_address2encrypted_keys = aes_enc.encrypt_keys_with_shared_secrets(); + + assert!(sp_address2encrypted_keys.is_ok()); + + let encrypted_key = sp_address2encrypted_keys + .unwrap() + .get(&ALICE_SP_ADDRESS.try_into().unwrap()) + .cloned(); + + let ciphertext = aes_enc.encrypt_with_aes_key(); + + assert!(ciphertext.is_ok()); + + let aes_dec = Aes256Decryption::new( + Purpose::Login, + ciphertext.unwrap(), + encrypted_key.unwrap(), + SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap(), + ); + + assert!(aes_dec.is_ok()); + + let retrieved_plain = aes_dec.unwrap().decrypt_with_key(); + + assert!(retrieved_plain.is_ok()); + + assert!(retrieved_plain.unwrap() == plaintext); + } + + #[test] + fn aes_encrypt_key_many() { + let plaintext = [1u8; HALFKEYSIZE]; + let mut aes_enc = Aes256Encryption::new(Purpose::Login, plaintext.to_vec()).unwrap(); + + let mut shared_secrets: HashMap<Txid, _> = HashMap::new(); + let mut sp_address2shared_secrets: HashMap<SilentPaymentAddress, SharedSecret> = + HashMap::new(); + sp_address2shared_secrets.insert( + ALICE_SP_ADDRESS.try_into().unwrap(), + SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap(), + ); + sp_address2shared_secrets.insert( + BOB_SP_ADDRESS.try_into().unwrap(), + SharedSecret::from_str(BOB_SHARED_SECRET).unwrap(), + ); + shared_secrets.insert( + Txid::from_str(TRANSACTION).unwrap(), + sp_address2shared_secrets, + ); + + aes_enc.set_shared_secret(shared_secrets); + + let mut sp_address2encrypted_keys = aes_enc.encrypt_keys_with_shared_secrets(); + + assert!(sp_address2encrypted_keys.is_ok()); + + // Alice + let encrypted_key = sp_address2encrypted_keys.as_mut() + .unwrap() + .get(&ALICE_SP_ADDRESS.try_into().unwrap()) + .cloned(); + + let ciphertext = aes_enc.encrypt_with_aes_key(); + + assert!(ciphertext.is_ok()); + + let aes_dec = Aes256Decryption::new( + Purpose::Login, + ciphertext.unwrap(), + encrypted_key.unwrap(), + SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap(), + ); + + assert!(aes_dec.is_ok()); + + let retrieved_plain = aes_dec.unwrap().decrypt_with_key(); + + assert!(retrieved_plain.is_ok()); + + assert!(retrieved_plain.unwrap() == plaintext); + + // Bob + let encrypted_key = sp_address2encrypted_keys + .unwrap() + .get(&BOB_SP_ADDRESS.try_into().unwrap()) + .cloned(); + + let ciphertext = aes_enc.encrypt_with_aes_key(); + + assert!(ciphertext.is_ok()); + + let aes_dec = Aes256Decryption::new( + Purpose::Login, + ciphertext.unwrap(), + encrypted_key.unwrap(), + SharedSecret::from_str(BOB_SHARED_SECRET).unwrap(), + ); + + assert!(aes_dec.is_ok()); + + let retrieved_plain = aes_dec.unwrap().decrypt_with_key(); + + assert!(retrieved_plain.is_ok()); + + assert!(retrieved_plain.unwrap() == plaintext); + } +} From 3aaca40f1508b9a5fa831c6ac2c6b6f006cb8a5a Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Tue, 26 Mar 2024 18:01:48 +0100 Subject: [PATCH 18/90] Allow for direct decryption withou shared secret --- crates/sp_client/src/aesgcm.rs | 58 ++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/crates/sp_client/src/aesgcm.rs b/crates/sp_client/src/aesgcm.rs index 0539f7e..b3d55c7 100644 --- a/crates/sp_client/src/aesgcm.rs +++ b/crates/sp_client/src/aesgcm.rs @@ -73,25 +73,32 @@ impl Aes256Decryption { pub fn new( purpose: Purpose, cipher_text: CipherText, - encrypted_aes_key: Vec<u8>, - shared_secret: SharedSecret, + encrypted_aes_key: Vec<u8>, // If shared_secret is none this is actually the aes_key + shared_secret: Option<SharedSecret>, // We don't need that for certain purpose, like Login ) -> Result<Self> { - if encrypted_aes_key.len() <= 12 { - return Err(Error::msg("encrypted_aes_key is shorter than nonce length")); - } // Actually we could probably test that if the remnant is not a multiple of 32, something's wrong - // take the first 12 bytes form encrypted_aes_key as nonce - let (decrypt_key_nonce, encrypted_key) = encrypted_aes_key.split_at(12); - // decrypt key with shared_secret obtained from transaction - let decrypt_key_cipher = Aes256Gcm::new_from_slice(shared_secret.as_ref()) - .map_err(|e| Error::msg(format!("{}", e)))?; - let aes_key_plain = decrypt_key_cipher - .decrypt(decrypt_key_nonce.into(), encrypted_key) - .map_err(|e| Error::msg(format!("{}", e)))?; - if aes_key_plain.len() != 32 { - return Err(Error::msg("Invalid length for decrypted key")); - } let mut aes_key = [0u8; 32]; - aes_key.copy_from_slice(&aes_key_plain); + if let Some(shared_secret) = shared_secret { + if encrypted_aes_key.len() <= 12 { + return Err(Error::msg("encrypted_aes_key is shorter than nonce length")); + } // Actually we could probably test that if the remnant is not a multiple of 32, something's wrong + // take the first 12 bytes form encrypted_aes_key as nonce + let (decrypt_key_nonce, encrypted_key) = encrypted_aes_key.split_at(12); + // decrypt key with shared_secret obtained from transaction + let decrypt_key_cipher = Aes256Gcm::new_from_slice(shared_secret.as_ref()) + .map_err(|e| Error::msg(format!("{}", e)))?; + let aes_key_plain = decrypt_key_cipher + .decrypt(decrypt_key_nonce.into(), encrypted_key) + .map_err(|e| Error::msg(format!("{}", e)))?; + if aes_key_plain.len() != 32 { + return Err(Error::msg("Invalid length for decrypted key")); + } + aes_key.copy_from_slice(&aes_key_plain); + } else { + if encrypted_aes_key.len() != 32 { + return Err(Error::msg("Invalid length for decrypted key")); + } + aes_key.copy_from_slice(&encrypted_aes_key); + } if cipher_text.len() <= 12 { return Err(Error::msg("cipher_text is shorter than nonce length")); } @@ -258,13 +265,22 @@ mod tests { #[test] fn aes_encrypt_login() { let plaintext = [1u8; HALFKEYSIZE]; - let aes_enc = Aes256Encryption::new(Purpose::Login, plaintext.to_vec()); + let aes_key = Aes256Gcm::generate_key(&mut thread_rng()); + let nonce = Aes256Gcm::generate_nonce(&mut thread_rng()); + let aes_enc = Aes256Encryption::import_key(Purpose::Login, plaintext.to_vec(), aes_key.into(), nonce.into()); assert!(aes_enc.is_ok()); let cipher = aes_enc.unwrap().encrypt_with_aes_key(); assert!(cipher.is_ok()); + + let mut plain_key = [0u8;32]; + plain_key.copy_from_slice(&aes_key.to_vec()); + + let aes_dec = Aes256Decryption::new(Purpose::Login, cipher.unwrap(), plain_key.to_vec(), None); + + assert!(aes_dec.is_ok()); } #[test] @@ -303,7 +319,7 @@ mod tests { Purpose::Login, ciphertext.unwrap(), encrypted_key.unwrap(), - SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap(), + Some(SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap()), ); assert!(aes_dec.is_ok()); @@ -356,7 +372,7 @@ mod tests { Purpose::Login, ciphertext.unwrap(), encrypted_key.unwrap(), - SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap(), + Some(SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap()), ); assert!(aes_dec.is_ok()); @@ -381,7 +397,7 @@ mod tests { Purpose::Login, ciphertext.unwrap(), encrypted_key.unwrap(), - SharedSecret::from_str(BOB_SHARED_SECRET).unwrap(), + Some(SharedSecret::from_str(BOB_SHARED_SECRET).unwrap()), ); assert!(aes_dec.is_ok()); From 9fe0687a4e52570401af621a913c8ee5c91fa33a Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Tue, 26 Mar 2024 18:00:41 +0100 Subject: [PATCH 19/90] Refactore user + test --- crates/sp_client/src/user.rs | 142 ++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 68 deletions(-) diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index 3c9e9c2..844f283 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -5,7 +5,6 @@ use aes_gcm::KeyInit; use aes_gcm::{aead::Buffer, Aes256Gcm, Key}; use anyhow::{Error, Result}; use bytes::Buf; -use js_sys::JsString; use rand::{self, thread_rng, Rng, RngCore}; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; @@ -15,7 +14,6 @@ use sp_backend::bitcoin::hex::{DisplayHex, FromHex}; use sp_backend::bitcoin::secp256k1::SecretKey; use tsify::Tsify; use wasm_bindgen::prelude::*; -use wasm_bindgen::JsValue; use bytes::Bytes; use shamir::SecretData; @@ -33,8 +31,9 @@ use sp_backend::spclient::{OutputList, SpClient}; use img_parts::jpeg::Jpeg; use img_parts::{ImageEXIF, ImageICC}; +use crate::aesgcm::Aes256Decryption; use crate::aesgcm::HalfKey; -use crate::aesgcm::{Aes256Encryption, EncryptionTarget}; +use crate::aesgcm::{Aes256Encryption, Purpose}; //extern crate shamir; //use shamir::SecretData; @@ -42,8 +41,8 @@ use crate::aesgcm::{Aes256Encryption, EncryptionTarget}; #[derive(Debug, Serialize, Deserialize, Clone, Tsify)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct User { - image_recover: BackUpImage, - image_revoke: BackUpImage, + recover_data: Vec<u8>, + revoke_data: Vec<u8>, sharding: Sharding, pre_id: String, recovered_spend_key: Option<String>, @@ -54,19 +53,15 @@ impl User { recover_spend_key: SecretKey, revoke_spend_key: SecretKey, revoke_scan_key: SecretKey, - user_password: &JsString, - recover_image: &[u8], - revoke_image: &[u8], + user_password: String, ) -> Result<Self> { let mut rng = thread_rng(); // image revoke - // We just take the 2 revoke keys and put it in the revoke_img file - let mut revoke_data = [0u8; SECRET_KEY_SIZE * 2]; - revoke_data[..SECRET_KEY_SIZE].copy_from_slice(revoke_scan_key.as_ref()); - revoke_data[SECRET_KEY_SIZE..].copy_from_slice(revoke_spend_key.as_ref()); - - let revoke_img_with_data = BackUpImage::new_revoke(revoke_image, &revoke_data)?; + // We just take the 2 revoke keys + let mut revoke_data = Vec::with_capacity(64); + revoke_data.extend_from_slice(revoke_scan_key.as_ref()); + revoke_data.extend_from_slice(revoke_spend_key.as_ref()); // split recover spend key let (part1_key, part2_key) = recover_spend_key.as_ref().split_at(SECRET_KEY_SIZE / 2); @@ -79,20 +74,16 @@ impl User { recover_data.extend_from_slice(&entropy_1); recover_data.extend_from_slice(&entropy_2); - // convert the password in a String, i.e. a Vec<u8> - // Be careful of javascript strings: https://rustwasm.github.io/wasm-bindgen/reference/types/str.html#utf-16-vs-utf-8 - assert!(user_password.is_valid_utf16()); // we can think better than panicking in this case - let password: String = user_password.into(); - // hash the concatenation let mut engine = sha256::HashEngine::default(); - engine.write_all(&password.as_bytes()); + engine.write_all(&user_password.as_bytes()); engine.write_all(&entropy_1); let hash1 = sha256::Hash::from_engine(engine); // take it as a AES key let part1_encryption = Aes256Encryption::import_key( - EncryptionTarget::Login(part1_key.try_into()?), + Purpose::Login, + part1_key.to_vec(), hash1.to_byte_array(), Aes256Gcm::generate_nonce(&mut rng).into(), )?; @@ -100,22 +91,18 @@ impl User { // encrypt the part1 of the key let cipher_recover_part1 = part1_encryption.encrypt_with_aes_key()?; - log::debug!("cipher_part1 length: {}", cipher_recover_part1.len()); - recover_data.extend_from_slice(&cipher_recover_part1); - //image recover - let recover_img_with_data = BackUpImage::new_recover(recover_image, &recover_data)?; - // encrypt the part 2 of the key let mut engine = sha256::HashEngine::default(); - engine.write_all(&password.as_bytes()); + engine.write_all(&user_password.as_bytes()); engine.write_all(&entropy_2); let hash2 = sha256::Hash::from_engine(engine); // take it as a AES key let part2_encryption = Aes256Encryption::import_key( - EncryptionTarget::Login(part2_key.try_into()?), + Purpose::Login, + part2_key.to_vec(), hash2.to_byte_array(), Aes256Gcm::generate_nonce(&mut rng).into(), )?; @@ -128,7 +115,7 @@ impl User { //Pre ID let mut engine = sha256::HashEngine::default(); - engine.write_all(&password.as_bytes()); + engine.write_all(&user_password.as_bytes()); engine.write_all(&cipher_recover_part1); let pre_id = sha256::Hash::from_engine(engine); @@ -139,46 +126,34 @@ impl User { //Receive List Items (PCD) Ok(User { - image_recover: recover_img_with_data, - image_revoke: revoke_img_with_data, + recover_data, + revoke_data, sharding, pre_id: pre_id.to_string(), recovered_spend_key: None, }) } - pub fn login(&self, user_password: JsString, image_recover: &[u8]) -> Result<SecretKey> { + pub fn login(user_password: String, recover_data: &[u8], sharding: Sharding) -> Result<SecretKey> { let mut retrieved_key = [0u8; 32]; let mut entropy1 = [0u8; 32]; let mut entropy2 = [0u8; 32]; - let mut nonce1 = [0u8; 12]; - let mut nonce2 = [0u8; 12]; let mut part1_ciphertext = Vec::with_capacity(32); // just a guess - assert!(user_password.is_valid_utf16()); - let password: String = user_password.into(); - - let exif_image_bytes = - Bytes::from(read_exif(image_recover).map_err(|e| Error::msg(format!("{}", e)))?); - let mut reader = exif_image_bytes.reader(); + let mut reader = recover_data.reader(); reader.read_exact(&mut entropy1)?; reader.read_exact(&mut entropy2)?; - reader.read_exact(&mut nonce1)?; - reader.read_exact(&mut nonce2)?; reader.read_to_end(&mut part1_ciphertext)?; - retrieved_key[..16].copy_from_slice(&Self::recover_part1( - &password, - &entropy1, - &nonce1, - &part1_ciphertext, - )?); + retrieved_key[..16].copy_from_slice(&Self::recover_part1(&user_password, &entropy1, part1_ciphertext)?); //@todo: get shardings from member managers! - let shardings = self.sharding.shares_vec.clone(); // temporary + let shardings = sharding.shares_vec.clone(); // temporary retrieved_key[16..].copy_from_slice(&Self::recover_part2( - &password, &entropy2, &nonce2, shardings, + &user_password, + &entropy2, + shardings, )?); let key = SecretKey::from_slice(&retrieved_key)?; @@ -189,26 +164,21 @@ impl User { fn recover_part1( password: &str, entropy: &[u8], - nonce: &[u8], - part1_ciphertext: &[u8], + part1_ciphertext: Vec<u8>, ) -> Result<Vec<u8>> { let mut engine = sha256::HashEngine::default(); engine.write_all(&password.as_bytes()); engine.write_all(&entropy); let hash = sha256::Hash::from_engine(engine); - let key: &Key<Aes256Gcm> = hash.as_byte_array().try_into()?; - let cipher = Aes256Gcm::new(&key); + let aes_dec = Aes256Decryption::new(Purpose::Login, part1_ciphertext, hash.to_byte_array().to_vec(), None)?; - cipher - .decrypt(nonce.into(), part1_ciphertext) - .map_err(|e| anyhow::Error::msg(format!("{}", e))) + aes_dec.decrypt_with_key() } fn recover_part2( password: &str, entropy: &[u8], - nonce: &[u8], shares_vec: Vec<Vec<u8>>, ) -> Result<Vec<u8>> { let mut engine = sha256::HashEngine::default(); @@ -224,12 +194,9 @@ impl User { .ok_or_else(|| anyhow::Error::msg("Failed to retrieve the sharded secret"))?, )?; - let key: &Key<Aes256Gcm> = hash.as_byte_array().try_into()?; - let cipher = Aes256Gcm::new(&key); + let aes_dec = Aes256Decryption::new(Purpose::Login, part2_key_enc, hash.to_byte_array().to_vec(), None)?; - cipher - .decrypt(nonce.into(), &*part2_key_enc) - .map_err(|e| anyhow::Error::msg(format!("{}", e))) + aes_dec.decrypt_with_key() } //not used @@ -246,10 +213,6 @@ impl User { // sha_256(&password_hash) // } - pub fn get_exif_image(&self, image: &[u8]) -> Vec<u8> { - return read_exif(image).expect("Error reading the exif"); - } - // Test sharing JS side pub fn get_shares(&self) -> Vec<String> { self.sharding.shares_format_str.clone() @@ -285,7 +248,7 @@ impl BackUpImage { pub fn new_revoke(image: &[u8], data: &[u8]) -> Result<Self> { let img = write_exif(image, data)?; - Ok(Self::Recover(img)) + Ok(Self::Revoke(img)) } } @@ -384,3 +347,46 @@ pub fn read_exif(image: &[u8]) -> Result<Vec<u8>, String> { // let base64_string = base64::encode(decoded_data); // base64_string // } + +#[cfg(test)] +mod tests { + use super::*; // Import everything from the outer module + + const RECOVER_SPEND: &str = "394ef7757f5bc8cd692337c62abf6fa0ce9932fd4ec6676daddfbe3c1b3b9d11"; + const REVOKE_SPEND: &str = "821c1a84fa9ee718c02005505fb8315bd479c7b9a878b1eff45929c48dfcaf28"; + const REVOKE_SCAN: &str = "a0f36cbc380624fa7eef022f39cab2716333451649dd8eb78e86d2e76bdb3f47"; + const USER_PASSWORD: &str = "correct horse battery staple"; + + // Test 1: Create User + #[test] + fn test_successful_creation() { + let result = User::new( + SecretKey::from_str(RECOVER_SPEND).unwrap(), + SecretKey::from_str(REVOKE_SPEND).unwrap(), + SecretKey::from_str(REVOKE_SCAN).unwrap(), + USER_PASSWORD.to_owned(), + ); + + assert!(result.is_ok()); + let user = result.unwrap(); + } + + #[test] + fn test_login() { + let user = User::new( + SecretKey::from_str(RECOVER_SPEND).unwrap(), + SecretKey::from_str(REVOKE_SPEND).unwrap(), + SecretKey::from_str(REVOKE_SCAN).unwrap(), + USER_PASSWORD.to_owned(), + ).unwrap(); + + let recover_data = user.recover_data; + let sharding = user.sharding; + + let retrieved_recover_spend = User::login(USER_PASSWORD.to_owned(), &recover_data, sharding); + + assert!(retrieved_recover_spend.is_ok()); + + assert!(format!("{}", retrieved_recover_spend.unwrap().display_secret()) == RECOVER_SPEND) + } +} From 331d880d3521283d86501f3b234d51ded02321b2 Mon Sep 17 00:00:00 2001 From: Yousra Assouhaji <yousra.assouhaji@atos.net> Date: Wed, 27 Mar 2024 13:59:46 +0000 Subject: [PATCH 20/90] Replace process.rs --- crates/sp_client/src/process.rs | 87 +++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/crates/sp_client/src/process.rs b/crates/sp_client/src/process.rs index 427481d..1dd3248 100644 --- a/crates/sp_client/src/process.rs +++ b/crates/sp_client/src/process.rs @@ -1,5 +1,8 @@ use wasm_bindgen::prelude::*; +use serde::{Deserialize, Serialize}; +use serde_json::{json, Value}; +/* #[wasm_bindgen] pub fn get_process() -> Vec<String> { let mut data_process: Vec<String> = Vec::new(); @@ -7,4 +10,88 @@ pub fn get_process() -> Vec<String> { data_process.push(String::from("process2")); data_process.push(String::from("process3")); data_process +}*/ + +// process member (gestionnaire for now) +#[derive(Debug)] +pub enum Role { + manager, + // user } +#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[wasm_bindgen] +pub struct itemMember { + role: Role, //gestionnaire + sp_address: String, + //pre_id + //shard + //priv_key_mainnet_spend + //priv_key_mainnet_scan + //priv_key_signet_scan + +} +#[wasm_bindgen] +impl itemMember{ + pub fn new ( + role : Role, + sp_address: string) + ->Self { + itemMember{ + role, + sp_address, + } + } +} + +pub struct Process { + id: String, + version: String, + gestionnaires: Vec<itemMember>, + //item_name : String, +} +#[wasm_bindgen] +pub fn get_processes() -> Vec<JsValue> { + let member1 = itemMember { + role: Role ::Manager, + sp_address: String::from(""), + }; + + let member2 = itemMember { + role: Role ::Manager, + sp_address: String::from(""), + }; + + let member3 = itemMember { + role: Role ::Manager, + sp_address: String::from(""), + }; + /* + let member4= itemMember{ + role : Role :: User, + sp_address: String::from(""), + }; + */ + //instances of process + let process1 = Process { + id: String::from("1"), + version: String::from("1.0"), + gestionnaires: vec![member1, member2], + }; + let process2 = Process { + id: String::from("2"), + version: String::from("2.0"), + gestionnaires: vec![member2, member3], + }; + let process3 = Process { + id: String::from("3"), + version: String::from("1.0"), + gestionnaires: vec![member3, member1], + }; + + // vec with the instances of processes + let mut data_process: Vec<JsValue> = Vec::new(); + data_process.push(JsValue::from_serde(&process1).unwrap()); + data_process.push(JsValue::from_serde(&process2).unwrap()); + data_process.push(JsValue::from_serde(&process3).unwrap()); + data_process +} \ No newline at end of file From 70cf0e6040bd300cdca01f12e857804d6ff76139 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 27 Mar 2024 16:10:02 +0100 Subject: [PATCH 21/90] wasm_bindgen function in api --- crates/sp_client/src/api.rs | 52 +++++++++++++-- crates/sp_client/src/process.rs | 111 ++++++++------------------------ 2 files changed, 74 insertions(+), 89 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index d629df8..7f5b325 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -1,8 +1,8 @@ use rand::Rng; use anyhow::Error as AnyhowError; -use sp_backend::silentpayments::Error as SpError; use serde_json::Error as SerdeJsonError; +use sp_backend::silentpayments::Error as SpError; use serde::{Deserialize, Serialize}; use sp_backend::silentpayments::sending::SilentPaymentAddress; @@ -13,6 +13,8 @@ use wasm_bindgen::prelude::*; use sp_backend::spclient::SpendKey; use sp_backend::spclient::{derive_keys_from_seed, OutputList, SpClient}; +use crate::process::{ItemMember, Process, Role}; + type ApiResult<T: FromWasmAbi> = Result<T, ApiError>; const IS_TESTNET: bool = true; @@ -24,19 +26,25 @@ struct ApiError { impl From<AnyhowError> for ApiError { fn from(value: AnyhowError) -> Self { - ApiError {message: value.to_string()} + ApiError { + message: value.to_string(), + } } } impl From<SpError> for ApiError { fn from(value: SpError) -> Self { - ApiError { message: value.to_string() } + ApiError { + message: value.to_string(), + } } } impl From<SerdeJsonError> for ApiError { fn from(value: SerdeJsonError) -> Self { - ApiError { message: value.to_string() } + ApiError { + message: value.to_string(), + } } } @@ -104,3 +112,39 @@ pub fn get_receiving_address(sp_client: String) -> String { let sp_client: SpClient = serde_json::from_str(&sp_client).unwrap(); sp_client.get_receiving_address() } + +#[derive(Tsify, Serialize, Deserialize)] +#[tsify(into_wasm_abi)] +#[allow(non_camel_case_types)] +pub struct get_process_return(Vec<Process>); + +#[wasm_bindgen] +pub fn get_processes() -> ApiResult<get_process_return> { + let member1 = ItemMember::new(Role::Manager, String::from("")); + let member2 = ItemMember::new(Role::Manager, String::from("")); + let member3 = ItemMember::new(Role::Manager, String::from("")); + + //instances of process + let process1 = Process { + id: String::from("1"), + version: String::from("1.0"), + gestionnaires: vec![member1.clone(), member2.clone()], + }; + let process2 = Process { + id: String::from("2"), + version: String::from("2.0"), + gestionnaires: vec![member2.clone(), member3.clone()], + }; + let process3 = Process { + id: String::from("3"), + version: String::from("1.0"), + gestionnaires: vec![member3.clone(), member1.clone()], + }; + + // vec with the instances of processes + let mut data_process: Vec<Process> = Vec::new(); + data_process.push(process1); + data_process.push(process2); + data_process.push(process3); + Ok(get_process_return(data_process)) +} diff --git a/crates/sp_client/src/process.rs b/crates/sp_client/src/process.rs index 1dd3248..4f384e8 100644 --- a/crates/sp_client/src/process.rs +++ b/crates/sp_client/src/process.rs @@ -1,97 +1,38 @@ -use wasm_bindgen::prelude::*; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; - -/* -#[wasm_bindgen] -pub fn get_process() -> Vec<String> { - let mut data_process: Vec<String> = Vec::new(); - data_process.push(String::from("process1")); - data_process.push(String::from("process2")); - data_process.push(String::from("process3")); - data_process -}*/ +use tsify::Tsify; +use wasm_bindgen::prelude::*; // process member (gestionnaire for now) -#[derive(Debug)] +#[derive(Debug, Default, Serialize, Deserialize, Clone)] pub enum Role { - manager, - // user + Manager, + #[default] + User, } -#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[wasm_bindgen] -pub struct itemMember { - role: Role, //gestionnaire - sp_address: String, - //pre_id - //shard - //priv_key_mainnet_spend +#[derive(Debug, Serialize, Deserialize, Default, Tsify, Clone)] +#[tsify(into_wasm_abi)] +pub struct ItemMember { + pub role: Role, //gestionnaire + pub sp_address: String, + //pre_id + //shard + //priv_key_mainnet_spend //priv_key_mainnet_scan //priv_key_signet_scan - -} -#[wasm_bindgen] -impl itemMember{ - pub fn new ( - role : Role, - sp_address: string) - ->Self { - itemMember{ - role, - sp_address, - } - } } +impl ItemMember { + pub fn new(role: Role, sp_address: String) -> Self { + ItemMember { role, sp_address } + } +} + +#[derive(Debug, Serialize, Deserialize, Default, Tsify)] +#[tsify(into_wasm_abi, from_wasm_abi)] pub struct Process { - id: String, - version: String, - gestionnaires: Vec<itemMember>, - //item_name : String, + pub id: String, + pub version: String, + pub gestionnaires: Vec<ItemMember>, + //item_name : String, } -#[wasm_bindgen] -pub fn get_processes() -> Vec<JsValue> { - let member1 = itemMember { - role: Role ::Manager, - sp_address: String::from(""), - }; - - let member2 = itemMember { - role: Role ::Manager, - sp_address: String::from(""), - }; - - let member3 = itemMember { - role: Role ::Manager, - sp_address: String::from(""), - }; - /* - let member4= itemMember{ - role : Role :: User, - sp_address: String::from(""), - }; - */ - //instances of process - let process1 = Process { - id: String::from("1"), - version: String::from("1.0"), - gestionnaires: vec![member1, member2], - }; - let process2 = Process { - id: String::from("2"), - version: String::from("2.0"), - gestionnaires: vec![member2, member3], - }; - let process3 = Process { - id: String::from("3"), - version: String::from("1.0"), - gestionnaires: vec![member3, member1], - }; - - // vec with the instances of processes - let mut data_process: Vec<JsValue> = Vec::new(); - data_process.push(JsValue::from_serde(&process1).unwrap()); - data_process.push(JsValue::from_serde(&process2).unwrap()); - data_process.push(JsValue::from_serde(&process3).unwrap()); - data_process -} \ No newline at end of file From 9c551f5a5a64b9fd3ebf9910abc0893086890dac Mon Sep 17 00:00:00 2001 From: Alex Silva <alex.pereiradasilva@atos.net> Date: Fri, 29 Mar 2024 10:15:01 +0100 Subject: [PATCH 22/90] Userkeys and api update --- crates/sp_client/src/api.rs | 104 ++++++++++++++++++++++++++--------- crates/sp_client/src/user.rs | 69 +++++++++++++++++++++-- 2 files changed, 141 insertions(+), 32 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 5674539..48489dd 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -1,7 +1,10 @@ +use std::collections::HashMap; + use rand::Rng; use anyhow::Error as AnyhowError; use serde_json::Error as SerdeJsonError; +use shamir::SecretData; use sp_backend::bitcoin::secp256k1::SecretKey; use sp_backend::silentpayments::Error as SpError; @@ -15,7 +18,7 @@ use sp_backend::spclient::SpendKey; use sp_backend::spclient::{derive_keys_from_seed, OutputList, SpClient}; use web_sys::js_sys::JsString; -use crate::user::User; +use crate::user::{User, UserKeys}; type ApiResult<T: FromWasmAbi> = Result<T, ApiError>; @@ -59,9 +62,9 @@ impl Into<JsValue> for ApiError { #[derive(Tsify, Serialize, Deserialize)] #[tsify(into_wasm_abi)] #[allow(non_camel_case_types)] -pub struct generate_create_user_return { +pub struct GenerateCreateUserReturn { pub user: User, - pub output_list: OutputList + pub output_list_vec: Vec<OutputList>, } #[wasm_bindgen] @@ -69,11 +72,22 @@ pub fn setup() { wasm_logger::init(wasm_logger::Config::default()); } +#[wasm_bindgen] +pub fn test_fn() { + log::info!("test"); +} + +// Should be transfered to annother module +pub struct GenerateSPWallet { + pub sp_client: SpClient, + pub sp_outputs: OutputList, +} + pub fn generate_sp_wallet( label: Option<String>, birthday: u32, is_testnet: bool, -) -> ApiResult<generate_sp_wallet_return> { +) -> ApiResult<GenerateSPWallet> { let mut seed = [0u8; 64]; rand::thread_rng().fill(&mut seed); let (scan_sk, spend_sk) = derive_keys_from_seed(&seed, is_testnet)?; @@ -90,7 +104,7 @@ pub fn generate_sp_wallet( our_address.to_string() ); - let sp_client_json = serde_json::to_string(&sp_client)?; + //let sp_client_json = serde_json::to_string(&sp_client)?; // Generate an empty outputs let sp_outputs = OutputList::new( @@ -98,11 +112,11 @@ pub fn generate_sp_wallet( our_address.get_spend_key(), birthday, ); - let sp_outputs_json = serde_json::to_string(&sp_outputs)?; + //let sp_outputs_json = serde_json::to_string(&sp_outputs)?; - let res = generate_sp_wallet_return { - sp_client_json, - sp_outputs_json, + let res = GenerateSPWallet { + sp_client, + sp_outputs, }; Ok(res) @@ -116,26 +130,64 @@ pub fn get_receiving_address(sp_client: String) -> String { #[wasm_bindgen] pub fn create_user( - password: JsString, - image_to_recover: &[u8], - image_to_revoke: &[u8], + password: String, label: Option<String>, birthday: u32, -) -> ApiResult<User> { +) -> ApiResult<GenerateCreateUserReturn> { + let mut output_list: Vec<OutputList> = Vec::new(); + log::info!("Ok0"); + //recover + let sp_wallet_recover = generate_sp_wallet(label.clone(), birthday, true)?; + output_list.push(sp_wallet_recover.sp_outputs); + let recover_scan_key = sp_wallet_recover.sp_client.get_scan_key(); + let recover_spend_key = match sp_wallet_recover.sp_client.get_spend_key() { + SpendKey::Secret(key) => key, + SpendKey::Public(_) => { + return Err(ApiError::from(AnyhowError::msg( + "No recover spend key created on Signet", + ))) + } + }; + let recover_keys = UserKeys::add_keys_recover(recover_scan_key, recover_spend_key); + log::info!("Ok1"); + //revoke + let sp_wallet_revoke = generate_sp_wallet(label.clone(), birthday, true)?; + output_list.push(sp_wallet_revoke.sp_outputs); + let revoke_scan_key = sp_wallet_revoke.sp_client.get_scan_key(); + let revoke_spend_key = match sp_wallet_revoke.sp_client.get_spend_key() { + SpendKey::Secret(key) => key, + SpendKey::Public(_) => { + return Err(ApiError::from(AnyhowError::msg( + "No revoke spend key created on Signet", + ))) + } + }; + let revoke_keys = UserKeys::add_keys_revoke(revoke_scan_key, revoke_spend_key); + //mainet + let sp_wallet_main = generate_sp_wallet(label, birthday, false)?; + output_list.push(sp_wallet_main.sp_outputs); + let main_scan_key = sp_wallet_main.sp_client.get_scan_key(); + let main_spend_key = match sp_wallet_main.sp_client.get_spend_key() { + SpendKey::Secret(key) => key, + SpendKey::Public(_) => { + return Err(ApiError::from(AnyhowError::msg( + "No spend key created on Mainet", + ))) + } + }; + let main_keys = UserKeys::add_keys_main(main_scan_key, main_spend_key); - // todo: struct with sp_client{revoke, recover, main} - let sp_client_recover = generate_sp_wallet(label, birthday, true)?; - let sp_client_revoke = generate_sp_wallet(label, birthday, true)?; - let sp_client_main = generate_sp_wallet(label, birthday, false)?; + let user_keys = UserKeys::new(recover_keys, revoke_keys, main_keys); + log::info!("Ok2"); - let user = User::new( - recover_spend_key, - revoke_spend_key, - revoke_scan_key, - &password, - image_to_recover, - image_to_revoke, - )?; + let user = User::new(user_keys, password)?; - Ok(user) + let generate_user = GenerateCreateUserReturn { + user, + output_list_vec: output_list, + }; + log::info!("Ok3"); + + + Ok(generate_user) } diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index 844f283..fcadd92 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -37,6 +37,62 @@ use crate::aesgcm::{Aes256Encryption, Purpose}; //extern crate shamir; //use shamir::SecretData; +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum KeyType { + Recover(SpKeys), + Revoke(SpKeys), + Main(SpKeys), +} +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SpKeys { + pub scan_key: SecretKey, + pub spend_key: SecretKey, +} +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct UserKeys { + pub recover_keys: KeyType, + pub revoke_keys: KeyType, + pub main_keys: KeyType, +} + +impl UserKeys { + pub fn new(recover_keys: KeyType, revoke_keys: KeyType, main_keys: KeyType) -> Self { + UserKeys { + recover_keys, + revoke_keys, + main_keys, + } + } + pub fn add_keys_recover(scan_key: SecretKey, spend_key: SecretKey) -> KeyType { + let sp_keys = SpKeys { + scan_key, + spend_key, + }; + KeyType::Recover((sp_keys)) + } + pub fn add_keys_revoke(scan_key: SecretKey, spend_key: SecretKey) -> KeyType { + let sp_keys = SpKeys { + scan_key, + spend_key, + }; + KeyType::Revoke((sp_keys)) + } + pub fn add_keys_main(scan_key: SecretKey, spend_key: SecretKey) -> KeyType { + let sp_keys = SpKeys { + scan_key, + spend_key, + }; + KeyType::Main((sp_keys)) + } + + pub fn get_keys(&self, key_type: KeyType) -> SpKeys { + match key_type { + KeyType::Recover(keys) => keys, + KeyType::Revoke(keys) => keys, + KeyType::Main(keys) => keys, + } + } +} #[derive(Debug, Serialize, Deserialize, Clone, Tsify)] #[tsify(into_wasm_abi, from_wasm_abi)] @@ -50,20 +106,21 @@ pub struct User { impl User { pub fn new( - recover_spend_key: SecretKey, - revoke_spend_key: SecretKey, - revoke_scan_key: SecretKey, + user_keys: UserKeys, user_password: String, - ) -> Result<Self> { + ) -> Result<Self> { let mut rng = thread_rng(); // image revoke // We just take the 2 revoke keys + let revoke_scan_key = user_keys.get_keys(user_keys.revoke_keys.clone()).scan_key; + let revoke_spend_key = user_keys.get_keys(user_keys.revoke_keys.clone()).spend_key; let mut revoke_data = Vec::with_capacity(64); revoke_data.extend_from_slice(revoke_scan_key.as_ref()); revoke_data.extend_from_slice(revoke_spend_key.as_ref()); // split recover spend key + let recover_spend_key = user_keys.get_keys(user_keys.recover_keys.clone()).spend_key; let (part1_key, part2_key) = recover_spend_key.as_ref().split_at(SECRET_KEY_SIZE / 2); let mut recover_data = Vec::<u8>::with_capacity(64); // 32 * 2 @@ -347,7 +404,7 @@ pub fn read_exif(image: &[u8]) -> Result<Vec<u8>, String> { // let base64_string = base64::encode(decoded_data); // base64_string // } - +/* #[cfg(test)] mod tests { use super::*; // Import everything from the outer module @@ -389,4 +446,4 @@ mod tests { assert!(format!("{}", retrieved_recover_spend.unwrap().display_secret()) == RECOVER_SPEND) } -} +}*/ From e7d2ace04a90d0cd6df6cfd685a7093cabc092e5 Mon Sep 17 00:00:00 2001 From: Yousra Assouhaji <yousra.assouhaji@atos.net> Date: Fri, 29 Mar 2024 09:20:39 +0000 Subject: [PATCH 23/90] Exemple Prd list --- crates/sp_client/src/Prd_list.rs | 85 ++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 crates/sp_client/src/Prd_list.rs diff --git a/crates/sp_client/src/Prd_list.rs b/crates/sp_client/src/Prd_list.rs new file mode 100644 index 0000000..fea1218 --- /dev/null +++ b/crates/sp_client/src/Prd_list.rs @@ -0,0 +1,85 @@ +use serde::{Deserialize, Serialize}; +use serde_json::{json, Value}; +use tsify::Tsify; +use wasm_bindgen::prelude::*; +use std::marker::Copy; + + +#[wasm_bindgen] +#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)] +pub enum Role { + Manager, + #[default] + User, +} + + +#[derive(Serialize, Deserialize, Debug, Copy, Clone)] +//use std :: marker; +//strings can't implement copy +#[wasm_bindgen] +pub struct ItemMember { + pub role : Role, + pub sp_address: u32, + //pre_id: hash(password, part1) + //shard, + //priv_key_mainnet_spend, (enc) + //priv_key_mainnet_scan, + //priv_key_signet_scan, +} + +impl ItemMember { + pub fn new(role: Role, sp_address: u32) -> Self { + ItemMember {role, sp_address} + } +} + +#[derive(Debug, Serialize)] +#[wasm_bindgen] +pub struct Prdlist { + //pub id: String, + //pub version: String, + pub gestionnaires: Vec<ItemMember>, +} + +//auto inscription in the list (not included) +/* +fn auto_enroll(prdlist: &mut Prdlist, role: Role, sp_address: u32) { + let item_member = ItemMember { + role, //just as a user + sp_address, + }; + prdlist.gestionnaires.push(item_member); //not gestionnaires but users + +}*/ + +//fn send_transaction(prdlist: &Prdlist){} +//fn send_PrdMessage (prdlist: &Prdlist){} + +#[derive(Serialize)] +struct RequestBody { + message: String, +} + +#[wasm_bindgen] +pub async fn send_PrdRequest(prdlist: &Prdlist) -> Result<(), JsValue> { + let managers: Vec<&ItemMember> = prdlist.gestionnaires.iter().filter(|m| m.role == Role::Manager).collect(); + for manager in managers { + let request_body = RequestBody { + message: "Asking for the Prd list".to_string(), + }; + + let json_body = serde_json::to_string(&request_body).map_err(|e| JsValue::from_str(&format!("Failed to serialize request body: {:?}", e)))?; + println!("Sending request to manager {:?}", manager.sp_address); + } + Ok(()) +} + + + + + + + + + From 58de1c14ba20cc88ff08cd14eaf6995f58b5f969 Mon Sep 17 00:00:00 2001 From: Alex Silva <alex.pereiradasilva@atos.net> Date: Fri, 29 Mar 2024 11:30:22 +0100 Subject: [PATCH 24/90] Add scan key encryption --- crates/sp_client/src/api.rs | 10 ---------- crates/sp_client/src/user.rs | 33 ++++++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 48489dd..97d8cfb 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -72,11 +72,6 @@ pub fn setup() { wasm_logger::init(wasm_logger::Config::default()); } -#[wasm_bindgen] -pub fn test_fn() { - log::info!("test"); -} - // Should be transfered to annother module pub struct GenerateSPWallet { pub sp_client: SpClient, @@ -135,7 +130,6 @@ pub fn create_user( birthday: u32, ) -> ApiResult<GenerateCreateUserReturn> { let mut output_list: Vec<OutputList> = Vec::new(); - log::info!("Ok0"); //recover let sp_wallet_recover = generate_sp_wallet(label.clone(), birthday, true)?; output_list.push(sp_wallet_recover.sp_outputs); @@ -149,7 +143,6 @@ pub fn create_user( } }; let recover_keys = UserKeys::add_keys_recover(recover_scan_key, recover_spend_key); - log::info!("Ok1"); //revoke let sp_wallet_revoke = generate_sp_wallet(label.clone(), birthday, true)?; output_list.push(sp_wallet_revoke.sp_outputs); @@ -178,7 +171,6 @@ pub fn create_user( let main_keys = UserKeys::add_keys_main(main_scan_key, main_spend_key); let user_keys = UserKeys::new(recover_keys, revoke_keys, main_keys); - log::info!("Ok2"); let user = User::new(user_keys, password)?; @@ -186,8 +178,6 @@ pub fn create_user( user, output_list_vec: output_list, }; - log::info!("Ok3"); - Ok(generate_user) } diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index fcadd92..530f650 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -98,10 +98,11 @@ impl UserKeys { #[tsify(into_wasm_abi, from_wasm_abi)] pub struct User { recover_data: Vec<u8>, - revoke_data: Vec<u8>, + revoke_data: Option<Vec<u8>>, sharding: Sharding, pre_id: String, recovered_spend_key: Option<String>, + recovered_scan_key: Option<String>, } impl User { @@ -119,14 +120,17 @@ impl User { revoke_data.extend_from_slice(revoke_scan_key.as_ref()); revoke_data.extend_from_slice(revoke_spend_key.as_ref()); - // split recover spend key + // Take the 2 recover keys + let recover_scan_key = user_keys.get_keys(user_keys.recover_keys.clone()).scan_key; let recover_spend_key = user_keys.get_keys(user_keys.recover_keys.clone()).spend_key; + // split recover spend key let (part1_key, part2_key) = recover_spend_key.as_ref().split_at(SECRET_KEY_SIZE / 2); - let mut recover_data = Vec::<u8>::with_capacity(64); // 32 * 2 + let mut recover_data = Vec::<u8>::with_capacity(180); // 32 * 3 + (12+16)*3 - // generate 2 tokens of 32B entropy + // generate 3 tokens of 32B entropy let mut entropy_1: [u8; 32] = Aes256Gcm::generate_key(&mut rng).into(); let mut entropy_2: [u8; 32] = Aes256Gcm::generate_key(&mut rng).into(); + let mut entropy_3: [u8; 32] = Aes256Gcm::generate_key(&mut rng).into(); recover_data.extend_from_slice(&entropy_1); recover_data.extend_from_slice(&entropy_2); @@ -176,6 +180,24 @@ impl User { engine.write_all(&cipher_recover_part1); let pre_id = sha256::Hash::from_engine(engine); + //scan key: + let mut engine = sha256::HashEngine::default(); + engine.write_all(&user_password.as_bytes()); + engine.write_all(&entropy_3); + let hash3 = sha256::Hash::from_engine(engine); + + let scan_key_encryption = Aes256Encryption::import_key( + Purpose::Login, + recover_scan_key.secret_bytes().to_vec(), + hash3.to_byte_array(), + Aes256Gcm::generate_nonce(&mut rng).into(), + )?; + + // encrypt the scan key + let cipher_scan_key = scan_key_encryption.encrypt_with_aes_key()?; + + recover_data.extend_from_slice(&cipher_scan_key); + //Create PRDList //@todo //Send messages PRDList @@ -184,10 +206,11 @@ impl User { Ok(User { recover_data, - revoke_data, + revoke_data: Some(revoke_data), sharding, pre_id: pre_id.to_string(), recovered_spend_key: None, + recovered_scan_key: None, }) } From 8cd7a8f3613915d75de962736a29024cadd3305f Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Fri, 29 Mar 2024 12:37:17 +0100 Subject: [PATCH 25/90] Used forked shamir --- crates/sp_client/Cargo.toml | 2 +- crates/sp_client/src/lib.rs | 1 - crates/sp_client/src/secretdata.rs | 266 ----------------------------- 3 files changed, 1 insertion(+), 268 deletions(-) delete mode 100644 crates/sp_client/src/secretdata.rs diff --git a/crates/sp_client/Cargo.toml b/crates/sp_client/Cargo.toml index 52fc7ed..2c4acb8 100644 --- a/crates/sp_client/Cargo.toml +++ b/crates/sp_client/Cargo.toml @@ -29,7 +29,7 @@ image = "0.24.9" img-parts = "0.3.0" bytes = "1.5.0" scrypt = "0.11.0" -shamir = "2.0.0" +shamir = { git = "https://github.com/Sosthene00/shamir", branch = "master" } [dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index 637b54a..c7a01f3 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -3,5 +3,4 @@ mod aesgcm; pub mod api; mod injecteurhtml; mod process; -mod secretdata; mod user; diff --git a/crates/sp_client/src/secretdata.rs b/crates/sp_client/src/secretdata.rs deleted file mode 100644 index 3d84b62..0000000 --- a/crates/sp_client/src/secretdata.rs +++ /dev/null @@ -1,266 +0,0 @@ -use rand::{thread_rng, RngCore}; - -pub struct SecretData { - pub secret_data: Option<String>, - pub coefficients: Vec<Vec<u8>>, -} - -#[derive(Debug)] -pub enum ShamirError { - /// The number of shares must be between 1 and 255 - InvalidShareCount, -} - -impl SecretData { - pub fn with_secret(secret: &str, threshold: u8) -> SecretData { - let mut coefficients: Vec<Vec<u8>> = vec![]; - let mut rng = thread_rng(); - let mut rand_container = vec![0u8; (threshold - 1) as usize]; - for c in secret.as_bytes() { - rng.fill_bytes(&mut rand_container); - let mut coef: Vec<u8> = vec![*c]; - for r in rand_container.iter() { - coef.push(*r); - } - coefficients.push(coef); - } - - SecretData { - secret_data: Some(secret.to_string()), - coefficients, - } - } - - pub fn get_share(&self, id: u8) -> Result<Vec<u8>, ShamirError> { - if id == 0 { - return Err(ShamirError::InvalidShareCount); - } - let mut share_bytes: Vec<u8> = vec![]; - let coefficients = self.coefficients.clone(); - for coefficient in coefficients { - //let b = SecretData::accumulate_share_bytes(id, coefficient)?; - let b = r#try!(SecretData::accumulate_share_bytes(id, coefficient)); - share_bytes.push(b); - } - - share_bytes.insert(0, id); - Ok(share_bytes) - } - - pub fn is_valid_share(&self, share: &[u8]) -> bool { - let id = share[0]; - match self.get_share(id) { - Ok(s) => s == share, - _ => false, - } - } - - pub fn recover_secret(threshold: u8, shares: Vec<Vec<u8>>) -> Option<String> { - if threshold as usize > shares.len() { - println!("Number of shares is below the threshold"); - return None; - } - let mut xs: Vec<u8> = vec![]; - - for share in shares.iter() { - if xs.contains(&share[0]) { - println!("Multiple shares with the same first byte"); - return None; - } - - if share.len() != shares[0].len() { - println!("Shares have different lengths"); - return None; - } - - xs.push(share[0].to_owned()); - } - let mut mycoefficients: Vec<String> = vec![]; - let mut mysecretdata: Vec<u8> = vec![]; - let rounds = shares[0].len() - 1; - - for byte_to_use in 0..rounds { - let mut fxs: Vec<u8> = vec![]; - for share in shares.clone() { - fxs.push(share[1..][byte_to_use]); - } - - match SecretData::full_lagrange(&xs, &fxs) { - None => return None, - Some(resulting_poly) => { - mycoefficients.push(String::from_utf8_lossy(&resulting_poly[..]).to_string()); - mysecretdata.push(resulting_poly[0]); - } - } - } - - match String::from_utf8(mysecretdata) { - Ok(s) => Some(s), - Err(e) => { - println!("{:?}", e); - None - } - } - } - - fn accumulate_share_bytes(id: u8, coefficient_bytes: Vec<u8>) -> Result<u8, ShamirError> { - if id == 0 { - return Err(ShamirError::InvalidShareCount); - } - let mut accumulator: u8 = 0; - - let mut x_i: u8 = 1; - - for c in coefficient_bytes { - accumulator = SecretData::gf256_add(accumulator, SecretData::gf256_mul(c, x_i)); - x_i = SecretData::gf256_mul(x_i, id); - } - - Ok(accumulator) - } - - fn full_lagrange(xs: &[u8], fxs: &[u8]) -> Option<Vec<u8>> { - let mut returned_coefficients: Vec<u8> = vec![]; - let len = fxs.len(); - for i in 0..len { - let mut this_polynomial: Vec<u8> = vec![1]; - - for j in 0..len { - if i == j { - continue; - } - - let denominator = SecretData::gf256_sub(xs[i], xs[j]); - let first_term = SecretData::gf256_checked_div(xs[j], denominator); - let second_term = SecretData::gf256_checked_div(1, denominator); - match (first_term, second_term) { - (Some(a), Some(b)) => { - let this_term = vec![a, b]; - this_polynomial = - SecretData::multiply_polynomials(&this_polynomial, &this_term); - } - (_, _) => return None, - }; - } - if fxs.len() + 1 >= i { - this_polynomial = SecretData::multiply_polynomials(&this_polynomial, &[fxs[i]]) - } - returned_coefficients = - SecretData::add_polynomials(&returned_coefficients, &this_polynomial); - } - Some(returned_coefficients) - } - - #[inline] - fn gf256_add(a: u8, b: u8) -> u8 { - a ^ b - } - - #[inline] - fn gf256_sub(a: u8, b: u8) -> u8 { - SecretData::gf256_add(a, b) - } - - #[inline] - fn gf256_mul(a: u8, b: u8) -> u8 { - if a == 0 || b == 0 { - 0 - } else { - GF256_EXP[((u16::from(GF256_LOG[a as usize]) + u16::from(GF256_LOG[b as usize])) % 255) - as usize] - } - } - - #[inline] - fn gf256_checked_div(a: u8, b: u8) -> Option<u8> { - if a == 0 { - Some(0) - } else if b == 0 { - None - } else { - let a_log = i16::from(GF256_LOG[a as usize]); - let b_log = i16::from(GF256_LOG[b as usize]); - - let mut diff = a_log - b_log; - - if diff < 0 { - diff += 255; - } - Some(GF256_EXP[(diff % 255) as usize]) - } - } - - #[inline] - fn multiply_polynomials(a: &[u8], b: &[u8]) -> Vec<u8> { - let mut resultterms: Vec<u8> = vec![]; - - let mut termpadding: Vec<u8> = vec![]; - - for bterm in b { - let mut thisvalue = termpadding.clone(); - for aterm in a { - thisvalue.push(SecretData::gf256_mul(*aterm, *bterm)); - } - resultterms = SecretData::add_polynomials(&resultterms, &thisvalue); - termpadding.push(0); - } - resultterms - } - - #[inline] - fn add_polynomials(a: &[u8], b: &[u8]) -> Vec<u8> { - let mut a = a.to_owned(); - let mut b = b.to_owned(); - if a.len() < b.len() { - let mut t = vec![0; b.len() - a.len()]; - a.append(&mut t); - } else if a.len() > b.len() { - let mut t = vec![0; a.len() - b.len()]; - b.append(&mut t); - } - let mut results: Vec<u8> = vec![]; - - for i in 0..a.len() { - results.push(SecretData::gf256_add(a[i], b[i])); - } - results - } -} - -static GF256_EXP: [u8; 256] = [ - 0x01, 0x03, 0x05, 0x0f, 0x11, 0x33, 0x55, 0xff, 0x1a, 0x2e, 0x72, 0x96, 0xa1, 0xf8, 0x13, 0x35, - 0x5f, 0xe1, 0x38, 0x48, 0xd8, 0x73, 0x95, 0xa4, 0xf7, 0x02, 0x06, 0x0a, 0x1e, 0x22, 0x66, 0xaa, - 0xe5, 0x34, 0x5c, 0xe4, 0x37, 0x59, 0xeb, 0x26, 0x6a, 0xbe, 0xd9, 0x70, 0x90, 0xab, 0xe6, 0x31, - 0x53, 0xf5, 0x04, 0x0c, 0x14, 0x3c, 0x44, 0xcc, 0x4f, 0xd1, 0x68, 0xb8, 0xd3, 0x6e, 0xb2, 0xcd, - 0x4c, 0xd4, 0x67, 0xa9, 0xe0, 0x3b, 0x4d, 0xd7, 0x62, 0xa6, 0xf1, 0x08, 0x18, 0x28, 0x78, 0x88, - 0x83, 0x9e, 0xb9, 0xd0, 0x6b, 0xbd, 0xdc, 0x7f, 0x81, 0x98, 0xb3, 0xce, 0x49, 0xdb, 0x76, 0x9a, - 0xb5, 0xc4, 0x57, 0xf9, 0x10, 0x30, 0x50, 0xf0, 0x0b, 0x1d, 0x27, 0x69, 0xbb, 0xd6, 0x61, 0xa3, - 0xfe, 0x19, 0x2b, 0x7d, 0x87, 0x92, 0xad, 0xec, 0x2f, 0x71, 0x93, 0xae, 0xe9, 0x20, 0x60, 0xa0, - 0xfb, 0x16, 0x3a, 0x4e, 0xd2, 0x6d, 0xb7, 0xc2, 0x5d, 0xe7, 0x32, 0x56, 0xfa, 0x15, 0x3f, 0x41, - 0xc3, 0x5e, 0xe2, 0x3d, 0x47, 0xc9, 0x40, 0xc0, 0x5b, 0xed, 0x2c, 0x74, 0x9c, 0xbf, 0xda, 0x75, - 0x9f, 0xba, 0xd5, 0x64, 0xac, 0xef, 0x2a, 0x7e, 0x82, 0x9d, 0xbc, 0xdf, 0x7a, 0x8e, 0x89, 0x80, - 0x9b, 0xb6, 0xc1, 0x58, 0xe8, 0x23, 0x65, 0xaf, 0xea, 0x25, 0x6f, 0xb1, 0xc8, 0x43, 0xc5, 0x54, - 0xfc, 0x1f, 0x21, 0x63, 0xa5, 0xf4, 0x07, 0x09, 0x1b, 0x2d, 0x77, 0x99, 0xb0, 0xcb, 0x46, 0xca, - 0x45, 0xcf, 0x4a, 0xde, 0x79, 0x8b, 0x86, 0x91, 0xa8, 0xe3, 0x3e, 0x42, 0xc6, 0x51, 0xf3, 0x0e, - 0x12, 0x36, 0x5a, 0xee, 0x29, 0x7b, 0x8d, 0x8c, 0x8f, 0x8a, 0x85, 0x94, 0xa7, 0xf2, 0x0d, 0x17, - 0x39, 0x4b, 0xdd, 0x7c, 0x84, 0x97, 0xa2, 0xfd, 0x1c, 0x24, 0x6c, 0xb4, 0xc7, 0x52, 0xf6, 0x01, -]; - -static GF256_LOG: [u8; 256] = [ - 0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, 0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03, - 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, 0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1, - 0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78, - 0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, 0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e, - 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, 0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38, - 0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10, - 0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, 0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba, - 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, 0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57, - 0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8, - 0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, 0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0, - 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, 0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7, - 0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d, - 0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, 0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1, - 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab, - 0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5, - 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, 0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07, -]; From 98e94799ef28363930e2b5d732f516c5842855ac Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Fri, 29 Mar 2024 12:56:05 +0100 Subject: [PATCH 26/90] Create new user and write indexedDB --- crates/sp_client/src/api.rs | 9 ++-- crates/sp_client/src/user.rs | 14 +++--- src/database.ts | 20 ++++++--- src/index.ts | 15 +------ src/services.ts | 85 ++++++++++++++++-------------------- 5 files changed, 65 insertions(+), 78 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 97d8cfb..335cda8 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -62,7 +62,7 @@ impl Into<JsValue> for ApiError { #[derive(Tsify, Serialize, Deserialize)] #[tsify(into_wasm_abi)] #[allow(non_camel_case_types)] -pub struct GenerateCreateUserReturn { +pub struct create_user_return { pub user: User, pub output_list_vec: Vec<OutputList>, } @@ -128,7 +128,8 @@ pub fn create_user( password: String, label: Option<String>, birthday: u32, -) -> ApiResult<GenerateCreateUserReturn> { + process: String +) -> ApiResult<create_user_return> { let mut output_list: Vec<OutputList> = Vec::new(); //recover let sp_wallet_recover = generate_sp_wallet(label.clone(), birthday, true)?; @@ -172,9 +173,9 @@ pub fn create_user( let user_keys = UserKeys::new(recover_keys, revoke_keys, main_keys); - let user = User::new(user_keys, password)?; + let user = User::new(user_keys, password, process)?; - let generate_user = GenerateCreateUserReturn { + let generate_user = create_user_return { user, output_list_vec: output_list, }; diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index 530f650..bb939d0 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -97,18 +97,19 @@ impl UserKeys { #[derive(Debug, Serialize, Deserialize, Clone, Tsify)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct User { + pre_id: String, + process: String, recover_data: Vec<u8>, revoke_data: Option<Vec<u8>>, sharding: Sharding, - pre_id: String, - recovered_spend_key: Option<String>, - recovered_scan_key: Option<String>, + // recovered_spend_key: Option<String>, } impl User { pub fn new( user_keys: UserKeys, user_password: String, + process: String ) -> Result<Self> { let mut rng = thread_rng(); @@ -116,6 +117,7 @@ impl User { // We just take the 2 revoke keys let revoke_scan_key = user_keys.get_keys(user_keys.revoke_keys.clone()).scan_key; let revoke_spend_key = user_keys.get_keys(user_keys.revoke_keys.clone()).spend_key; + let mut revoke_data = Vec::with_capacity(64); revoke_data.extend_from_slice(revoke_scan_key.as_ref()); revoke_data.extend_from_slice(revoke_spend_key.as_ref()); @@ -205,12 +207,12 @@ impl User { //Receive List Items (PCD) Ok(User { + pre_id: pre_id.to_string(), + process, recover_data, revoke_data: Some(revoke_data), sharding, - pre_id: pre_id.to_string(), - recovered_spend_key: None, - recovered_scan_key: None, + // recovered_spend_key: None, }) } diff --git a/src/database.ts b/src/database.ts index e86404f..9d7245a 100644 --- a/src/database.ts +++ b/src/database.ts @@ -4,11 +4,11 @@ class Database { private dbName: string = '4nk'; private dbVersion: number = 1; private storeDefinitions = { - SpClient: { - name: "sp_client", - options: {}, - indices: [] - }, + // SpClient: { + // name: "sp_client", + // options: {}, + // indices: [] + // }, SpOutputs: { name: "sp_outputs", options: {'autoIncrement': true}, @@ -22,8 +22,14 @@ class Database { }, AnkUser: { name: "user", - options: {}, - indices: [] + options: {'keyPath': 'pre_id'}, + indices: [{ + name: 'by_process', + keyPath: 'process', + options: { + 'unique': false + } + }] }, AnkSession: { name: "session", diff --git a/src/index.ts b/src/index.ts index 891a579..90a47e7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,20 +5,7 @@ document.addEventListener('DOMContentLoaded', async () => { try { const services = await Services.getInstance(); - if ((await services.isNewUser())) { - services.displayCreateId(); - } - else { - services.displayRecover() - } - - let sp_wallet_return = services.new_sp_client("default", 0, true); - - const indexedDB = await IndexedDB.getInstance(); - const db = indexedDB.getDb(); - await indexedDB.writeObject(db, indexedDB.getStoreList().SpClient, sp_wallet_return.sp_client_json, "default"); - await indexedDB.writeObject(db, indexedDB.getStoreList().SpOutputs, sp_wallet_return.sp_outputs_json, null); - + await services.displayCreateId(); } catch (error) { console.error(error); } diff --git a/src/services.ts b/src/services.ts index 980e861..f6e15c6 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,11 +1,11 @@ -import { generate_sp_wallet_return, User } from '../dist/pkg/sdk_client'; +import { create_user_return, User } from '../dist/pkg/sdk_client'; import IndexedDB from './database' import Processstore from './store/processstore'; class Services { private static instance: Services; private sdkClient: any; - private static CURRENT_PROCESS = "currentprocess"; + private current_process: string | null = null; // Private constructor to prevent direct instantiation from outside private constructor() {} @@ -25,28 +25,24 @@ class Services { this.sdkClient.setup(); } - public new_sp_client(label: string, current_tip: number, is_testnet: boolean): generate_sp_wallet_return { - return this.sdkClient.generate_sp_wallet(label, current_tip, is_testnet); - } + // public async getSpAddressDefaultClient(): Promise<string | null> { + // try { + // const indexedDB = await IndexedDB.getInstance(); + // const db = indexedDB.getDb(); + // const spClient = await indexedDB.getObject<string>(db, indexedDB.getStoreList().SpClient, "default"); - public async getSpAddressDefaultClient(): Promise<string | null> { - try { - const indexedDB = await IndexedDB.getInstance(); - const db = indexedDB.getDb(); - const spClient = await indexedDB.getObject<string>(db, indexedDB.getStoreList().SpClient, "default"); + // if (spClient) { + // return this.sdkClient.get_receiving_address(spClient); + // } else { + // console.error("SP client not found"); + // return null; + // } + // } catch (error) { + // console.error("Failed to retrieve object or get sp address:", error); + // return null; + // } - if (spClient) { - return this.sdkClient.get_receiving_address(spClient); - } else { - console.error("SP client not found"); - return null; - } - } catch (error) { - console.error("Failed to retrieve object or get sp address:", error); - return null; - } - - } + // } public async isNewUser(): Promise<boolean> { let isNew = false; @@ -65,7 +61,7 @@ class Services { public async displayCreateId(): Promise<void> { Services.instance.injectHtml(Services.instance.get_html_create_id()); - Services.instance.attachSubmitListener("form4nk", Services.instance.createId); + Services.instance.attachSubmitListener("form4nk", (event) => this.createId(event)); Services.instance.attachClickListener("displayrecover", Services.instance.displayRecover); Services.instance.displayProcess(await Services.instance.getAllProcess()); } @@ -86,25 +82,22 @@ class Services { } const password = passwordElement.value; - const process = processElement.value; - console.log("JS password: " + password + " process: " + process); + this.current_process = processElement.value; + console.log("JS password: " + password + " process: " + this.current_process); // To comment if test - if (!Services.instance.isPasswordValid(password)) return; + // if (!Services.instance.isPasswordValid(password)) return; - const image_to_recover = Services.instance.getImage("assets/4nk_image.png"); - const image_to_revoke = Services.instance.getImage("assets/revoke.jpeg"); let label = null; let birthday = 50000; - const user: User = this.sdkClient.create_user(password, image_to_recover, image_to_revoke, label, birthday); + const user: create_user_return = this.sdkClient.create_user(password, label, birthday, this.current_process); try { const indexedDb = await IndexedDB.getInstance(); const db = indexedDb.getDb(); - await indexedDb.writeObject(db, indexedDb.getStoreList().AnkUser, user, process); - console.log("JS User added"); + await indexedDb.writeObject(db, indexedDb.getStoreList().AnkUser, user.user, null); + // console.log("JS User added"); - await indexedDb.writeObject(db, indexedDb.getStoreList().AnkSession, process, Services.CURRENT_PROCESS); - console.log("JS Sessionstore added currentprocess"); + await indexedDb.writeObject(db, indexedDb.getStoreList().SpOutputs, user.output_list_vec, null); } catch (error) { console.error("Failed to write user object :", error); } @@ -201,8 +194,6 @@ class Services { } public async displayUpdateAnId() { - let currentProcess = await this.getCurrentProcess(); - let body = ""; let style = ""; let script = ""; @@ -210,7 +201,7 @@ class Services { const indexedDB = await IndexedDB.getInstance(); const db = indexedDB.getDb(); try { - let processObject = await indexedDB.getObject<Processstore>(db, indexedDB.getStoreList().AnkProcess, currentProcess); + let processObject = await indexedDB.getObject<Processstore>(db, indexedDB.getStoreList().AnkProcess, this.current_process!); body = processObject.html; style = processObject.style; script = processObject.script; @@ -356,17 +347,17 @@ class Services { container.innerHTML = html; } - public async getCurrentProcess(): Promise<string> { - let currentProcess = ""; - try { - const indexedDB = await IndexedDB.getInstance(); - const db = indexedDB.getDb(); - currentProcess = await indexedDB.getObject<string>(db, indexedDB.getStoreList().AnkSession, Services.CURRENT_PROCESS); - } catch (error) { - console.error("Failed to retrieve currentprocess object :", error); - } - return currentProcess; - } + // public async getCurrentProcess(): Promise<string> { + // let currentProcess = ""; + // try { + // const indexedDB = await IndexedDB.getInstance(); + // const db = indexedDB.getDb(); + // currentProcess = await indexedDB.getObject<string>(db, indexedDB.getStoreList().AnkSession, Services.CURRENT_PROCESS); + // } catch (error) { + // console.error("Failed to retrieve currentprocess object :", error); + // } + // return currentProcess; + // } public isPasswordValid(password: string) { var alertElem = document.getElementById("passwordalert"); From c50be5177509cfadf6f633d98fd6cc15f57a0d8b Mon Sep 17 00:00:00 2001 From: Alex Silva <alex.pereiradasilva@atos.net> Date: Fri, 29 Mar 2024 15:26:46 +0100 Subject: [PATCH 27/90] Add scan key decryption --- crates/sp_client/src/user.rs | 40 ++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index bb939d0..6dba477 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -102,7 +102,8 @@ pub struct User { recover_data: Vec<u8>, revoke_data: Option<Vec<u8>>, sharding: Sharding, - // recovered_spend_key: Option<String>, + //recovered_spend_key: Option<String>, + //recovered_scan_key: Option<String>, } impl User { @@ -112,7 +113,7 @@ impl User { process: String ) -> Result<Self> { let mut rng = thread_rng(); - + // image revoke // We just take the 2 revoke keys let revoke_scan_key = user_keys.get_keys(user_keys.revoke_keys.clone()).scan_key; @@ -136,6 +137,7 @@ impl User { recover_data.extend_from_slice(&entropy_1); recover_data.extend_from_slice(&entropy_2); + recover_data.extend_from_slice(&entropy_3); // hash the concatenation let mut engine = sha256::HashEngine::default(); @@ -205,55 +207,63 @@ impl User { //Send messages PRDList //@todo //Receive List Items (PCD) - + Ok(User { pre_id: pre_id.to_string(), process, recover_data, revoke_data: Some(revoke_data), sharding, - // recovered_spend_key: None, + //recovered_spend_key: None, + //recovered_scan_key: None, }) } - pub fn login(user_password: String, recover_data: &[u8], sharding: Sharding) -> Result<SecretKey> { - let mut retrieved_key = [0u8; 32]; + pub fn login(&self,user_password: String, recover_data: &[u8], sharding: Sharding) -> Result<()> { + let mut retrieved_spend_key = [0u8; 32]; + let mut retrieved_scan_key = [0u8; 32]; let mut entropy1 = [0u8; 32]; let mut entropy2 = [0u8; 32]; + let mut entropy3 = [0u8; 32]; + let mut cipher_scan_key = Vec::with_capacity(32); let mut part1_ciphertext = Vec::with_capacity(32); // just a guess let mut reader = recover_data.reader(); reader.read_exact(&mut entropy1)?; reader.read_exact(&mut entropy2)?; - reader.read_to_end(&mut part1_ciphertext)?; + reader.read_exact(&mut entropy3)?; + reader.read_exact(&mut part1_ciphertext)?; + reader.read_to_end(&mut cipher_scan_key)?; - retrieved_key[..16].copy_from_slice(&Self::recover_part1(&user_password, &entropy1, part1_ciphertext)?); + retrieved_spend_key[..16].copy_from_slice(&Self::recover_key_slice(&user_password, &entropy1, part1_ciphertext)?); //@todo: get shardings from member managers! let shardings = sharding.shares_vec.clone(); // temporary - retrieved_key[16..].copy_from_slice(&Self::recover_part2( + retrieved_spend_key[16..].copy_from_slice(&Self::recover_part2( &user_password, &entropy2, shardings, )?); + + retrieved_scan_key[..32].copy_from_slice(&Self::recover_key_slice(&user_password, &entropy3, cipher_scan_key)?);; - let key = SecretKey::from_slice(&retrieved_key)?; - - Ok(key) + //@todo: retrieved_scan_key and retrieved_spend_key should be stored somewhere! + + Ok(()) } - fn recover_part1( + fn recover_key_slice( password: &str, entropy: &[u8], - part1_ciphertext: Vec<u8>, + ciphertext: Vec<u8>, ) -> Result<Vec<u8>> { let mut engine = sha256::HashEngine::default(); engine.write_all(&password.as_bytes()); engine.write_all(&entropy); let hash = sha256::Hash::from_engine(engine); - let aes_dec = Aes256Decryption::new(Purpose::Login, part1_ciphertext, hash.to_byte_array().to_vec(), None)?; + let aes_dec = Aes256Decryption::new(Purpose::Login, ciphertext, hash.to_byte_array().to_vec(), None)?; aes_dec.decrypt_with_key() } From 3af2f1e131dd0398e718691e60070cd67983b281 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Fri, 29 Mar 2024 20:08:02 +0100 Subject: [PATCH 28/90] Allow encryption of 32 bytes array --- crates/sp_client/src/aesgcm.rs | 37 ++++++++++++++++++++++++++++++++++ crates/sp_client/src/user.rs | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/crates/sp_client/src/aesgcm.rs b/crates/sp_client/src/aesgcm.rs index b3d55c7..ff4a8b0 100644 --- a/crates/sp_client/src/aesgcm.rs +++ b/crates/sp_client/src/aesgcm.rs @@ -29,6 +29,8 @@ use rand::{thread_rng, RngCore}; const HALFKEYSIZE: usize = SECRET_KEY_SIZE / 2; +const THIRTYTWO: usize = 32; + pub struct HalfKey([u8; HALFKEYSIZE]); impl TryFrom<Vec<u8>> for HalfKey { @@ -56,6 +58,7 @@ impl HalfKey { pub enum Purpose { Login, + ThirtyTwoBytes, } pub type CipherText = Vec<u8>; @@ -118,6 +121,10 @@ impl Aes256Decryption { Purpose::Login => { let half_key = self.decrypt_login()?; Ok(half_key.to_inner()) + }, + Purpose::ThirtyTwoBytes => { + let thirty_two_buf = self.decrypt_thirty_two()?; + Ok(thirty_two_buf.to_vec()) } } } @@ -134,6 +141,19 @@ impl Aes256Decryption { key_half.copy_from_slice(&plain); Ok(HalfKey(key_half)) } + + fn decrypt_thirty_two(&self) -> Result<[u8; THIRTYTWO]> { + let cipher = Aes256Gcm::new(&self.aes_key.into()); + let plain = cipher + .decrypt(&self.nonce.into(), &*self.cipher_text) + .map_err(|e| Error::msg(format!("{}", e)))?; + if plain.len() != THIRTYTWO { + return Err(Error::msg("Plain text of invalid length, should be 32")); + } + let mut thirty_two = [0u8; THIRTYTWO]; + thirty_two.copy_from_slice(&plain); + Ok(thirty_two) + } } pub struct Aes256Encryption { @@ -205,6 +225,7 @@ impl Aes256Encryption { pub fn encrypt_with_aes_key(&self) -> Result<CipherText> { match self.purpose { Purpose::Login => self.encrypt_login(), + Purpose::ThirtyTwoBytes => self.encrypt_thirty_two() } } @@ -219,6 +240,22 @@ impl Aes256Encryption { res.extend_from_slice(&cipher_text); Ok(res) } + + fn encrypt_thirty_two(&self) -> Result<CipherText> { + if self.plaintext.len() != 32 { + return Err(Error::msg("Invalid length, should be 32")); + } + let mut thirty_two = [0u8;32]; + thirty_two.copy_from_slice(&self.plaintext); + let cipher = Aes256Gcm::new(&self.aes_key.into()); + let cipher_text = cipher + .encrypt(&self.nonce.into(), thirty_two.as_slice()) + .map_err(|e| Error::msg(format!("{}", e)))?; + let mut res = Vec::with_capacity(self.nonce.len() + cipher_text.len()); + res.extend_from_slice(&self.nonce); + res.extend_from_slice(&cipher_text); + Ok(res) + } } #[cfg(test)] diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index 6dba477..d2f15db 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -191,7 +191,7 @@ impl User { let hash3 = sha256::Hash::from_engine(engine); let scan_key_encryption = Aes256Encryption::import_key( - Purpose::Login, + Purpose::ThirtyTwoBytes, recover_scan_key.secret_bytes().to_vec(), hash3.to_byte_array(), Aes256Gcm::generate_nonce(&mut rng).into(), From f2bb938fa4ad05ec2d18d919ee878bd2035d66d5 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Fri, 29 Mar 2024 20:08:46 +0100 Subject: [PATCH 29/90] Fix struct name --- crates/sp_client/src/api.rs | 6 +++--- src/services.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 335cda8..4ba3c13 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -62,7 +62,7 @@ impl Into<JsValue> for ApiError { #[derive(Tsify, Serialize, Deserialize)] #[tsify(into_wasm_abi)] #[allow(non_camel_case_types)] -pub struct create_user_return { +pub struct createUserReturn { pub user: User, pub output_list_vec: Vec<OutputList>, } @@ -129,7 +129,7 @@ pub fn create_user( label: Option<String>, birthday: u32, process: String -) -> ApiResult<create_user_return> { +) -> ApiResult<createUserReturn> { let mut output_list: Vec<OutputList> = Vec::new(); //recover let sp_wallet_recover = generate_sp_wallet(label.clone(), birthday, true)?; @@ -175,7 +175,7 @@ pub fn create_user( let user = User::new(user_keys, password, process)?; - let generate_user = create_user_return { + let generate_user = createUserReturn { user, output_list_vec: output_list, }; diff --git a/src/services.ts b/src/services.ts index f6e15c6..e93da51 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,4 +1,4 @@ -import { create_user_return, User } from '../dist/pkg/sdk_client'; +import { createUserReturn, User } from '../dist/pkg/sdk_client'; import IndexedDB from './database' import Processstore from './store/processstore'; @@ -89,7 +89,7 @@ class Services { let label = null; let birthday = 50000; - const user: create_user_return = this.sdkClient.create_user(password, label, birthday, this.current_process); + const user: createUserReturn = this.sdkClient.create_user(password, label, birthday, this.current_process); try { const indexedDb = await IndexedDB.getInstance(); From de14367ce0c68cdf2a7e5be328841348e122dbc9 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Fri, 29 Mar 2024 22:44:07 +0100 Subject: [PATCH 30/90] fmt --- crates/sp_client/src/aesgcm.rs | 55 +++++++++++++++++----------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/crates/sp_client/src/aesgcm.rs b/crates/sp_client/src/aesgcm.rs index ff4a8b0..59ab295 100644 --- a/crates/sp_client/src/aesgcm.rs +++ b/crates/sp_client/src/aesgcm.rs @@ -84,7 +84,7 @@ impl Aes256Decryption { if encrypted_aes_key.len() <= 12 { return Err(Error::msg("encrypted_aes_key is shorter than nonce length")); } // Actually we could probably test that if the remnant is not a multiple of 32, something's wrong - // take the first 12 bytes form encrypted_aes_key as nonce + // take the first 12 bytes form encrypted_aes_key as nonce let (decrypt_key_nonce, encrypted_key) = encrypted_aes_key.split_at(12); // decrypt key with shared_secret obtained from transaction let decrypt_key_cipher = Aes256Gcm::new_from_slice(shared_secret.as_ref()) @@ -121,7 +121,7 @@ impl Aes256Decryption { Purpose::Login => { let half_key = self.decrypt_login()?; Ok(half_key.to_inner()) - }, + } Purpose::ThirtyTwoBytes => { let thirty_two_buf = self.decrypt_thirty_two()?; Ok(thirty_two_buf.to_vec()) @@ -225,7 +225,7 @@ impl Aes256Encryption { pub fn encrypt_with_aes_key(&self) -> Result<CipherText> { match self.purpose { Purpose::Login => self.encrypt_login(), - Purpose::ThirtyTwoBytes => self.encrypt_thirty_two() + Purpose::ThirtyTwoBytes => self.encrypt_thirty_two(), } } @@ -245,13 +245,14 @@ impl Aes256Encryption { if self.plaintext.len() != 32 { return Err(Error::msg("Invalid length, should be 32")); } - let mut thirty_two = [0u8;32]; + let mut thirty_two = [0u8; 32]; thirty_two.copy_from_slice(&self.plaintext); let cipher = Aes256Gcm::new(&self.aes_key.into()); let cipher_text = cipher .encrypt(&self.nonce.into(), thirty_two.as_slice()) .map_err(|e| Error::msg(format!("{}", e)))?; let mut res = Vec::with_capacity(self.nonce.len() + cipher_text.len()); + log::info!("{}", cipher_text.len()); res.extend_from_slice(&self.nonce); res.extend_from_slice(&cipher_text); Ok(res) @@ -267,8 +268,10 @@ mod tests { const ALICE_SP_ADDRESS: &str = "tsp1qqw3lqr6xravz9nf8ntazgwwl0fqv47kfjdxsnxs6eutavqfwyv5q6qk97mmyf6dtkdyzqlu2zv6h9j2ggclk7vn705q5u2phglpq7yw3dg5rwpdz"; const BOB_SP_ADDRESS: &str = "tsp1qq2hlsgrj0gz8kcfkf9flqw5llz0u2vr04telqndku9mcqm6dl4fhvq60t8r78srrf56w9yr7w9e9dusc2wjqc30up6fjwnh9mw3e3veqegdmtf08"; const TRANSACTION: &str = "4e6d03dec558e1b6624f813bf2da7cd8d8fb1c2296684c08cf38724dcfd8d10b"; - const ALICE_SHARED_SECRET: &str = "ccf02d364c2641ca129a3fdf49de57b705896e233f7ba6d738991993ea7e2106"; - const BOB_SHARED_SECRET: &str = "15ef3e377fb842e81de52dbaaea8ba30aeb051a81043ee19264afd27353da521"; + const ALICE_SHARED_SECRET: &str = + "ccf02d364c2641ca129a3fdf49de57b705896e233f7ba6d738991993ea7e2106"; + const BOB_SHARED_SECRET: &str = + "15ef3e377fb842e81de52dbaaea8ba30aeb051a81043ee19264afd27353da521"; #[test] fn new_aes_empty_plaintext() { @@ -304,7 +307,12 @@ mod tests { let plaintext = [1u8; HALFKEYSIZE]; let aes_key = Aes256Gcm::generate_key(&mut thread_rng()); let nonce = Aes256Gcm::generate_nonce(&mut thread_rng()); - let aes_enc = Aes256Encryption::import_key(Purpose::Login, plaintext.to_vec(), aes_key.into(), nonce.into()); + let aes_enc = Aes256Encryption::import_key( + Purpose::Login, + plaintext.to_vec(), + aes_key.into(), + nonce.into(), + ); assert!(aes_enc.is_ok()); @@ -312,10 +320,11 @@ mod tests { assert!(cipher.is_ok()); - let mut plain_key = [0u8;32]; + let mut plain_key = [0u8; 32]; plain_key.copy_from_slice(&aes_key.to_vec()); - let aes_dec = Aes256Decryption::new(Purpose::Login, cipher.unwrap(), plain_key.to_vec(), None); + let aes_dec = + Aes256Decryption::new(Purpose::Login, cipher.unwrap(), plain_key.to_vec(), None); assert!(aes_dec.is_ok()); } @@ -370,8 +379,9 @@ mod tests { #[test] fn aes_encrypt_key_many() { - let plaintext = [1u8; HALFKEYSIZE]; - let mut aes_enc = Aes256Encryption::new(Purpose::Login, plaintext.to_vec()).unwrap(); + let plaintext = [1u8; THIRTYTWO]; + let mut aes_enc = + Aes256Encryption::new(Purpose::ThirtyTwoBytes, plaintext.to_vec()).unwrap(); let mut shared_secrets: HashMap<Txid, _> = HashMap::new(); let mut sp_address2shared_secrets: HashMap<SilentPaymentAddress, SharedSecret> = @@ -396,31 +406,26 @@ mod tests { assert!(sp_address2encrypted_keys.is_ok()); // Alice - let encrypted_key = sp_address2encrypted_keys.as_mut() + let encrypted_key = sp_address2encrypted_keys + .as_mut() .unwrap() .get(&ALICE_SP_ADDRESS.try_into().unwrap()) .cloned(); let ciphertext = aes_enc.encrypt_with_aes_key(); - assert!(ciphertext.is_ok()); - let aes_dec = Aes256Decryption::new( - Purpose::Login, + Purpose::ThirtyTwoBytes, ciphertext.unwrap(), encrypted_key.unwrap(), Some(SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap()), ); - assert!(aes_dec.is_ok()); - let retrieved_plain = aes_dec.unwrap().decrypt_with_key(); - assert!(retrieved_plain.is_ok()); - assert!(retrieved_plain.unwrap() == plaintext); - - // Bob + + // Bob let encrypted_key = sp_address2encrypted_keys .unwrap() .get(&BOB_SP_ADDRESS.try_into().unwrap()) @@ -428,21 +433,15 @@ mod tests { let ciphertext = aes_enc.encrypt_with_aes_key(); - assert!(ciphertext.is_ok()); - let aes_dec = Aes256Decryption::new( - Purpose::Login, + Purpose::ThirtyTwoBytes, ciphertext.unwrap(), encrypted_key.unwrap(), Some(SharedSecret::from_str(BOB_SHARED_SECRET).unwrap()), ); - assert!(aes_dec.is_ok()); - let retrieved_plain = aes_dec.unwrap().decrypt_with_key(); - assert!(retrieved_plain.is_ok()); - assert!(retrieved_plain.unwrap() == plaintext); } } From c656a852ee623e1588a892fc6ef98852d81140e9 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Fri, 29 Mar 2024 22:46:24 +0100 Subject: [PATCH 31/90] Persistent user and wallets --- crates/sp_client/src/api.rs | 41 +---- crates/sp_client/src/user.rs | 317 ++++++++++++++++++++++------------- 2 files changed, 213 insertions(+), 145 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 4ba3c13..1d36711 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::sync::{Mutex, OnceLock}; use rand::Rng; @@ -18,7 +19,7 @@ use sp_backend::spclient::SpendKey; use sp_backend::spclient::{derive_keys_from_seed, OutputList, SpClient}; use web_sys::js_sys::JsString; -use crate::user::{User, UserKeys}; +use crate::user::{User, UserKeys, CONNECTED_USERS}; type ApiResult<T: FromWasmAbi> = Result<T, ApiError>; @@ -128,50 +129,24 @@ pub fn create_user( password: String, label: Option<String>, birthday: u32, - process: String + process: String, ) -> ApiResult<createUserReturn> { let mut output_list: Vec<OutputList> = Vec::new(); //recover let sp_wallet_recover = generate_sp_wallet(label.clone(), birthday, true)?; output_list.push(sp_wallet_recover.sp_outputs); - let recover_scan_key = sp_wallet_recover.sp_client.get_scan_key(); - let recover_spend_key = match sp_wallet_recover.sp_client.get_spend_key() { - SpendKey::Secret(key) => key, - SpendKey::Public(_) => { - return Err(ApiError::from(AnyhowError::msg( - "No recover spend key created on Signet", - ))) - } - }; - let recover_keys = UserKeys::add_keys_recover(recover_scan_key, recover_spend_key); //revoke let sp_wallet_revoke = generate_sp_wallet(label.clone(), birthday, true)?; output_list.push(sp_wallet_revoke.sp_outputs); - let revoke_scan_key = sp_wallet_revoke.sp_client.get_scan_key(); - let revoke_spend_key = match sp_wallet_revoke.sp_client.get_spend_key() { - SpendKey::Secret(key) => key, - SpendKey::Public(_) => { - return Err(ApiError::from(AnyhowError::msg( - "No revoke spend key created on Signet", - ))) - } - }; - let revoke_keys = UserKeys::add_keys_revoke(revoke_scan_key, revoke_spend_key); //mainet let sp_wallet_main = generate_sp_wallet(label, birthday, false)?; output_list.push(sp_wallet_main.sp_outputs); - let main_scan_key = sp_wallet_main.sp_client.get_scan_key(); - let main_spend_key = match sp_wallet_main.sp_client.get_spend_key() { - SpendKey::Secret(key) => key, - SpendKey::Public(_) => { - return Err(ApiError::from(AnyhowError::msg( - "No spend key created on Mainet", - ))) - } - }; - let main_keys = UserKeys::add_keys_main(main_scan_key, main_spend_key); - let user_keys = UserKeys::new(recover_keys, revoke_keys, main_keys); + let user_keys = UserKeys::new( + Some(sp_wallet_main.sp_client), + sp_wallet_recover.sp_client, + Some(sp_wallet_revoke.sp_client), + ); let user = User::new(user_keys, password, process)?; diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index d2f15db..852327c 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -12,15 +12,18 @@ use sp_backend::bitcoin::hashes::Hash; use sp_backend::bitcoin::hashes::HashEngine; use sp_backend::bitcoin::hex::{DisplayHex, FromHex}; use sp_backend::bitcoin::secp256k1::SecretKey; +use sp_backend::bitcoin::secp256k1::ThirtyTwoByteHash; use tsify::Tsify; use wasm_bindgen::prelude::*; use bytes::Bytes; use shamir::SecretData; +use std::collections::HashMap; use std::fs::File; use std::io::Read; use std::io::Write; use std::str::FromStr; +use std::sync::{Mutex, OnceLock}; use sp_backend::bitcoin::secp256k1::constants::SECRET_KEY_SIZE; use sp_backend::silentpayments::bitcoin_hashes::sha256; @@ -34,99 +37,60 @@ use img_parts::{ImageEXIF, ImageICC}; use crate::aesgcm::Aes256Decryption; use crate::aesgcm::HalfKey; use crate::aesgcm::{Aes256Encryption, Purpose}; +use crate::user; + +type PreId = String; + +pub static CONNECTED_USERS: OnceLock<Mutex<HashMap<PreId, UserKeys>>> = OnceLock::new(); -//extern crate shamir; -//use shamir::SecretData; -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum KeyType { - Recover(SpKeys), - Revoke(SpKeys), - Main(SpKeys), -} -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct SpKeys { - pub scan_key: SecretKey, - pub spend_key: SecretKey, -} #[derive(Debug, Clone, Serialize, Deserialize)] pub struct UserKeys { - pub recover_keys: KeyType, - pub revoke_keys: KeyType, - pub main_keys: KeyType, + pub main: Option<SpClient>, + pub recover: SpClient, + pub revoke: Option<SpClient>, } impl UserKeys { - pub fn new(recover_keys: KeyType, revoke_keys: KeyType, main_keys: KeyType) -> Self { - UserKeys { - recover_keys, - revoke_keys, - main_keys, + pub fn new(main: Option<SpClient>, recover: SpClient, revoke: Option<SpClient>) -> Self { + Self { + main, + recover, + revoke, } } - pub fn add_keys_recover(scan_key: SecretKey, spend_key: SecretKey) -> KeyType { - let sp_keys = SpKeys { - scan_key, - spend_key, - }; - KeyType::Recover((sp_keys)) - } - pub fn add_keys_revoke(scan_key: SecretKey, spend_key: SecretKey) -> KeyType { - let sp_keys = SpKeys { - scan_key, - spend_key, - }; - KeyType::Revoke((sp_keys)) - } - pub fn add_keys_main(scan_key: SecretKey, spend_key: SecretKey) -> KeyType { - let sp_keys = SpKeys { - scan_key, - spend_key, - }; - KeyType::Main((sp_keys)) - } - pub fn get_keys(&self, key_type: KeyType) -> SpKeys { - match key_type { - KeyType::Recover(keys) => keys, - KeyType::Revoke(keys) => keys, - KeyType::Main(keys) => keys, - } + pub fn try_get_revoke(&self) -> Option<&SpClient> { + self.revoke.as_ref() } } #[derive(Debug, Serialize, Deserialize, Clone, Tsify)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct User { - pre_id: String, - process: String, + pub pre_id: String, + pub process: String, recover_data: Vec<u8>, revoke_data: Option<Vec<u8>>, sharding: Sharding, - //recovered_spend_key: Option<String>, - //recovered_scan_key: Option<String>, } impl User { - pub fn new( - user_keys: UserKeys, - user_password: String, - process: String - ) -> Result<Self> { + pub fn new(user_keys: UserKeys, user_password: String, process: String) -> Result<Self> { let mut rng = thread_rng(); - + // image revoke // We just take the 2 revoke keys - let revoke_scan_key = user_keys.get_keys(user_keys.revoke_keys.clone()).scan_key; - let revoke_spend_key = user_keys.get_keys(user_keys.revoke_keys.clone()).spend_key; - let mut revoke_data = Vec::with_capacity(64); - revoke_data.extend_from_slice(revoke_scan_key.as_ref()); - revoke_data.extend_from_slice(revoke_spend_key.as_ref()); + if let Some(revoke) = user_keys.try_get_revoke() { + revoke_data.extend_from_slice(revoke.get_scan_key().as_ref()); + revoke_data.extend_from_slice(revoke.try_get_secret_spend_key()?.as_ref()); + } else { + return Err(Error::msg("No revoke wallet available")); + } // Take the 2 recover keys - let recover_scan_key = user_keys.get_keys(user_keys.recover_keys.clone()).scan_key; - let recover_spend_key = user_keys.get_keys(user_keys.recover_keys.clone()).spend_key; // split recover spend key + let recover_spend_key = user_keys.recover.try_get_secret_spend_key()?.clone(); let (part1_key, part2_key) = recover_spend_key.as_ref().split_at(SECRET_KEY_SIZE / 2); let mut recover_data = Vec::<u8>::with_capacity(180); // 32 * 3 + (12+16)*3 @@ -158,6 +122,9 @@ impl User { recover_data.extend_from_slice(&cipher_recover_part1); + //Pre ID + let pre_id: PreId = Self::compute_pre_id(&user_password, &cipher_recover_part1); + // encrypt the part 2 of the key let mut engine = sha256::HashEngine::default(); engine.write_all(&user_password.as_bytes()); @@ -178,12 +145,6 @@ impl User { //create shardings let sharding = Sharding::new(&cipher_recover_part2.to_lower_hex_string(), 10u8); //nMembers = 10 for testing, need to recover nmember elsewhere - //Pre ID - let mut engine = sha256::HashEngine::default(); - engine.write_all(&user_password.as_bytes()); - engine.write_all(&cipher_recover_part1); - let pre_id = sha256::Hash::from_engine(engine); - //scan key: let mut engine = sha256::HashEngine::default(); engine.write_all(&user_password.as_bytes()); @@ -192,7 +153,7 @@ impl User { let scan_key_encryption = Aes256Encryption::import_key( Purpose::ThirtyTwoBytes, - recover_scan_key.secret_bytes().to_vec(), + user_keys.recover.get_scan_key().secret_bytes().to_vec(), hash3.to_byte_array(), Aes256Gcm::generate_nonce(&mut rng).into(), )?; @@ -207,35 +168,65 @@ impl User { //Send messages PRDList //@todo //Receive List Items (PCD) - + Ok(User { pre_id: pre_id.to_string(), process, recover_data, revoke_data: Some(revoke_data), sharding, - //recovered_spend_key: None, - //recovered_scan_key: None, }) } - pub fn login(&self,user_password: String, recover_data: &[u8], sharding: Sharding) -> Result<()> { + pub fn login( + pre_id: PreId, + user_password: String, + recover_data: &[u8], + sharding: Sharding, + ) -> Result<()> { let mut retrieved_spend_key = [0u8; 32]; let mut retrieved_scan_key = [0u8; 32]; let mut entropy1 = [0u8; 32]; let mut entropy2 = [0u8; 32]; let mut entropy3 = [0u8; 32]; - let mut cipher_scan_key = Vec::with_capacity(32); - let mut part1_ciphertext = Vec::with_capacity(32); // just a guess + let mut cipher_scan_key = [0u8; 60]; + let mut part1_ciphertext = [0u8; 44]; let mut reader = recover_data.reader(); reader.read_exact(&mut entropy1)?; reader.read_exact(&mut entropy2)?; reader.read_exact(&mut entropy3)?; reader.read_exact(&mut part1_ciphertext)?; - reader.read_to_end(&mut cipher_scan_key)?; + reader.read_exact(&mut cipher_scan_key)?; - retrieved_spend_key[..16].copy_from_slice(&Self::recover_key_slice(&user_password, &entropy1, part1_ciphertext)?); + // We can retrieve the pre_id and check that it matches + let retrieved_pre_id = Self::compute_pre_id(&user_password, &part1_ciphertext); + + // If pre_id is not the same, password is probably false, or the client is feeding us garbage + if retrieved_pre_id != pre_id { + return Err(Error::msg("pre_id and recover_data don't match")); + } + + // If we already have loaded a user with this pre_id, abort + if let Some(current_users) = CONNECTED_USERS.get() { + if current_users + .to_owned() + .lock() + .unwrap() + .contains_key(&pre_id) + { + return Err(Error::msg(format!( + "User with pre_id {} already logged in", + pre_id + ))); + } + } + + retrieved_spend_key[..16].copy_from_slice(&Self::recover_part1( + &user_password, + &entropy1, + part1_ciphertext.to_vec(), + )?); //@todo: get shardings from member managers! let shardings = sharding.shares_vec.clone(); // temporary @@ -245,34 +236,80 @@ impl User { &entropy2, shardings, )?); - - retrieved_scan_key[..32].copy_from_slice(&Self::recover_key_slice(&user_password, &entropy3, cipher_scan_key)?);; - //@todo: retrieved_scan_key and retrieved_spend_key should be stored somewhere! - + retrieved_scan_key.copy_from_slice(&Self::recover_key_slice( + &user_password, + &entropy3, + cipher_scan_key.to_vec(), + )?); + + // we can create the recover sp_client + let recover_client = SpClient::new( + "".to_owned(), + SecretKey::from_slice(&retrieved_scan_key)?, + SpendKey::Secret(SecretKey::from_slice(&retrieved_spend_key)?), + None, + true, + )?; + + // Adding user to CONNECTED_USERS + if let Some(current_users) = CONNECTED_USERS.get() { + let mut lock = current_users.to_owned().lock().unwrap(); + if lock.contains_key(&pre_id) { + return Err(Error::msg(format!( + "User with pre_id {} already exists", + pre_id + ))); + } else { + lock.insert(pre_id.clone(), UserKeys::new(None, recover_client, None)); + } + } else { + let mut user_map = HashMap::new(); + user_map.insert(pre_id, UserKeys::new(None, recover_client, None)); + let new_value = Mutex::new(user_map); + if let Err(error) = CONNECTED_USERS.set(new_value) { + return Err(Error::msg( + "Failed to set the CONNECTED_USERS static variable", + )); + } + } + Ok(()) } - fn recover_key_slice( - password: &str, - entropy: &[u8], - ciphertext: Vec<u8>, - ) -> Result<Vec<u8>> { + fn recover_key_slice(password: &str, entropy: &[u8], ciphertext: Vec<u8>) -> Result<Vec<u8>> { let mut engine = sha256::HashEngine::default(); engine.write_all(&password.as_bytes()); engine.write_all(&entropy); let hash = sha256::Hash::from_engine(engine); - let aes_dec = Aes256Decryption::new(Purpose::Login, ciphertext, hash.to_byte_array().to_vec(), None)?; + let aes_dec = Aes256Decryption::new( + Purpose::ThirtyTwoBytes, + ciphertext, + hash.to_byte_array().to_vec(), + None, + )?; aes_dec.decrypt_with_key() } - fn recover_part2( - password: &str, - entropy: &[u8], - shares_vec: Vec<Vec<u8>>, - ) -> Result<Vec<u8>> { + fn recover_part1(password: &str, entropy: &[u8], ciphertext: Vec<u8>) -> Result<Vec<u8>> { + let mut engine = sha256::HashEngine::default(); + engine.write_all(&password.as_bytes()); + engine.write_all(&entropy); + let hash = sha256::Hash::from_engine(engine); + + let aes_dec = Aes256Decryption::new( + Purpose::Login, + ciphertext, + hash.to_byte_array().to_vec(), + None, + )?; + + aes_dec.decrypt_with_key() + } + + fn recover_part2(password: &str, entropy: &[u8], shares_vec: Vec<Vec<u8>>) -> Result<Vec<u8>> { let mut engine = sha256::HashEngine::default(); engine.write_all(&password.as_bytes()); engine.write_all(&entropy); @@ -286,11 +323,25 @@ impl User { .ok_or_else(|| anyhow::Error::msg("Failed to retrieve the sharded secret"))?, )?; - let aes_dec = Aes256Decryption::new(Purpose::Login, part2_key_enc, hash.to_byte_array().to_vec(), None)?; + let aes_dec = Aes256Decryption::new( + Purpose::Login, + part2_key_enc, + hash.to_byte_array().to_vec(), + None, + )?; aes_dec.decrypt_with_key() } + fn compute_pre_id(user_password: &str, cipher_recover_part1: &[u8]) -> PreId { + let mut engine = sha256::HashEngine::default(); + engine.write_all(&user_password.as_bytes()); + engine.write_all(&cipher_recover_part1); + let pre_id = sha256::Hash::from_engine(engine); + + pre_id.to_string() + } + //not used // pub fn pbkdf2(password: &str, data: &str) -> String { // let data_salt = data.trim_end_matches('='); @@ -439,25 +490,56 @@ pub fn read_exif(image: &[u8]) -> Result<Vec<u8>, String> { // let base64_string = base64::encode(decoded_data); // base64_string // } -/* + #[cfg(test)] mod tests { use super::*; // Import everything from the outer module const RECOVER_SPEND: &str = "394ef7757f5bc8cd692337c62abf6fa0ce9932fd4ec6676daddfbe3c1b3b9d11"; + const RECOVER_SCAN: &str = "3aa8cc570d17ec3a4dc4136e50151cc6de26052d968abfe02a5fea724ce38205"; const REVOKE_SPEND: &str = "821c1a84fa9ee718c02005505fb8315bd479c7b9a878b1eff45929c48dfcaf28"; const REVOKE_SCAN: &str = "a0f36cbc380624fa7eef022f39cab2716333451649dd8eb78e86d2e76bdb3f47"; + const MAIN_SPEND: &str = "b9098a6598ac55d8dd0e6b7aab0d1f63eb8792d06143f3c0fb6f5b80476a1c0d"; + const MAIN_SCAN: &str = "79dda4031663ac2cb250c46d896dc92b3c027a48a761b2342fabf1e441ea2857"; const USER_PASSWORD: &str = "correct horse battery staple"; + const PROCESS: &str = "example"; + + fn helper_create_user_keys() -> UserKeys { + let label = "default".to_owned(); + let sp_main = SpClient::new( + label.clone(), + SecretKey::from_str(MAIN_SCAN).unwrap(), + SpendKey::Secret(SecretKey::from_str(MAIN_SPEND).unwrap()), + None, + true, + ) + .unwrap(); + let sp_recover = SpClient::new( + label.clone(), + SecretKey::from_str(RECOVER_SCAN).unwrap(), + SpendKey::Secret(SecretKey::from_str(RECOVER_SPEND).unwrap()), + None, + true, + ) + .unwrap(); + let sp_revoke = SpClient::new( + label.clone(), + SecretKey::from_str(REVOKE_SCAN).unwrap(), + SpendKey::Secret(SecretKey::from_str(REVOKE_SPEND).unwrap()), + None, + true, + ) + .unwrap(); + let user_keys = UserKeys::new(Some(sp_main), sp_recover, Some(sp_revoke)); + + user_keys + } // Test 1: Create User #[test] fn test_successful_creation() { - let result = User::new( - SecretKey::from_str(RECOVER_SPEND).unwrap(), - SecretKey::from_str(REVOKE_SPEND).unwrap(), - SecretKey::from_str(REVOKE_SCAN).unwrap(), - USER_PASSWORD.to_owned(), - ); + let user_keys = helper_create_user_keys(); + let result = User::new(user_keys, USER_PASSWORD.to_owned(), PROCESS.to_owned()); assert!(result.is_ok()); let user = result.unwrap(); @@ -465,20 +547,31 @@ mod tests { #[test] fn test_login() { - let user = User::new( - SecretKey::from_str(RECOVER_SPEND).unwrap(), - SecretKey::from_str(REVOKE_SPEND).unwrap(), - SecretKey::from_str(REVOKE_SCAN).unwrap(), - USER_PASSWORD.to_owned(), - ).unwrap(); + let user_keys = helper_create_user_keys(); + let user = User::new(user_keys, USER_PASSWORD.to_owned(), PROCESS.to_owned()).unwrap(); + let pre_id = user.pre_id; let recover_data = user.recover_data; let sharding = user.sharding; - let retrieved_recover_spend = User::login(USER_PASSWORD.to_owned(), &recover_data, sharding); + let retrieved_recover_spend = User::login( + pre_id.clone(), + USER_PASSWORD.to_owned(), + &recover_data, + sharding, + ); assert!(retrieved_recover_spend.is_ok()); - assert!(format!("{}", retrieved_recover_spend.unwrap().display_secret()) == RECOVER_SPEND) + let connected = CONNECTED_USERS.get().unwrap().lock().unwrap(); + + let recover = &connected.get(&pre_id).unwrap().recover; + + assert!( + format!( + "{}", + recover.try_get_secret_spend_key().unwrap().display_secret() + ) == RECOVER_SPEND + ) } -}*/ +} From 7eb1ee9c1dc9f8ad3f7841d74f6b445561c9279e Mon Sep 17 00:00:00 2001 From: franck <franck.petretto@atos.net> Date: Mon, 1 Apr 2024 22:35:26 +0200 Subject: [PATCH 32/90] Modify revoke page and service to download revoke image --- .gitignore | 1 + crates/sp_client/src/injecteurhtml.rs | 18 +++++----- src/assets/4nk_revoke.jpg | Bin 0 -> 68608 bytes src/assets/revoke.jpeg | Bin 417434 -> 0 bytes src/services.ts | 47 ++++++++++++++------------ src/style/4nk.css | 14 ++++++-- 6 files changed, 48 insertions(+), 32 deletions(-) create mode 100644 src/assets/4nk_revoke.jpg delete mode 100644 src/assets/revoke.jpeg diff --git a/.gitignore b/.gitignore index 8100c14..ded76cb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ pkg/ Cargo.lock node_modules/ dist/ +.vscode \ No newline at end of file diff --git a/crates/sp_client/src/injecteurhtml.rs b/crates/sp_client/src/injecteurhtml.rs index 9a2ca73..1d18e90 100644 --- a/crates/sp_client/src/injecteurhtml.rs +++ b/crates/sp_client/src/injecteurhtml.rs @@ -56,20 +56,22 @@ pub fn inject_html_recover() -> String { #[wasm_bindgen] pub fn inject_html_revokeimage() -> String { String::from(" - <div class='card2'> - <form id='form4nk' action='#'> - <input type='hidden' id='currentpage' value='revokeimage' /> - <button type='submit' id='submitButton'> + <div class='card'> + <div class='side-by-side'> + <h3>Revoke image</h3> + <div><a href='#' id='displayupdateanid'>Update an Id</a></div> + </div> + </div> + <div class='card-revoke'> + <a href='#' download='revoke_4NK.jpg' id='revoke'> <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'> <path d='M246.6 9.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 109.3V320c0 17.7 14.3 32 32 32s32-14.3 32-32V109.3l73.4 73.4c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-128-128zM64 352c0-17.7-14.3-32-32-32s-32 14.3-32 32v64c0 53 43 96 96 96H352c53 0 96-43 96-96V352c0-17.7-14.3-32-32-32s-32 14.3-32 32v64c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V352z' /> </svg> - </button> - </form> + </a> <div class='image-container'> - <label class='image-label bg-secondary'>Revoke image</label> - <img src='assets/revoke.jpeg' alt='' /> + <img src='assets/4nk_revoke.jpg' alt='' /> </div> </div> ") diff --git a/src/assets/4nk_revoke.jpg b/src/assets/4nk_revoke.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9fba6de5941ffa993d5d5895e85b9d48cb2427d9 GIT binary patch literal 68608 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%0DYc5Ix@OkTuxh-{Zct&L%f}l! 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 U;dRa>rjT_Gmj3|bujfDi+2{c=761SM literal 0 HcmV?d00001 diff --git a/src/assets/revoke.jpeg b/src/assets/revoke.jpeg deleted file mode 100644 index 232dcb96a0ac15baff215afeb1ba5429e7cb8f86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 417434 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 T1!(C1SP8wQp5?UoclQ4QXxZ^} diff --git a/src/services.ts b/src/services.ts index e93da51..8667a03 100644 --- a/src/services.ts +++ b/src/services.ts @@ -105,22 +105,6 @@ class Services { await Services.instance.displayRevokeImage(); } - private async getImage(imageUrl:string): Promise<Uint8Array|null> { - let imageBytes = null; - try { - const response = await fetch(imageUrl); - if (!response.ok) { - throw new Error(`Failed to fetch image: ${response.status} ${response.statusText}`); - } - const arrayBuffer = await response.arrayBuffer(); - imageBytes = new Uint8Array(arrayBuffer); - console.log(imageBytes); - } catch (error) { - console.error("Failed to get image : "+imageUrl, error); - } - return imageBytes; - } - public async displayRecover(): Promise<void> { Services.instance.injectHtml(Services.instance.get_html_recover()); Services.instance.attachSubmitListener("form4nk", Services.instance.recover); @@ -159,19 +143,39 @@ class Services { public async displayRevokeImage(): Promise<void> { const html = Services.instance.get_html_revokeimage(); Services.instance.injectHtml(html); - Services.instance.attachSubmitListener("form4nk", Services.instance.revokeimage); + Services.instance.attachClickListener("displayupdateanid", Services.instance.revokeimage); + + let imageBytes = await Services.instance.getRecoverImage('assets/4nk_revoke.jpg'); + if (imageBytes != null) { + let blob = new Blob([imageBytes], {type: 'image/png'}); + var elem = document.getElementById("revoke") as HTMLAnchorElement; + if (elem != null) { + elem.href = URL.createObjectURL(blob); + } + } } public get_html_revokeimage(): string { return this.sdkClient.inject_html_revokeimage(); } + private async getRecoverImage(imageUrl:string): Promise<Uint8Array|null> { + let imageBytes = null; + try { + const response = await fetch(imageUrl); + if (!response.ok) { + throw new Error(`Failed to fetch image: ${response.status} ${response.statusText}`); + } + const arrayBuffer = await response.arrayBuffer(); + imageBytes = new Uint8Array(arrayBuffer); + } catch (error) { + console.error("Failed to get image : "+imageUrl, error); + } + return imageBytes; + } + public async revokeimage(event: Event): Promise<void> { event.preventDefault(); - console.log("JS revokeimage submit "); - // TODO - alert("Revokeimage submit to do ..., next page Update an id ..."); - await Services.instance.displayUpdateAnId(); } @@ -194,6 +198,7 @@ class Services { } public async displayUpdateAnId() { + console.log("JS displayUpdateAnId process : "+this.current_process); let body = ""; let style = ""; let script = ""; diff --git a/src/style/4nk.css b/src/style/4nk.css index 39377bb..09b1116 100644 --- a/src/style/4nk.css +++ b/src/style/4nk.css @@ -114,7 +114,7 @@ a { .bg-primary:hover { background-color: #457be8; } -.card2 { +.card-revoke { display: flex; flex-direction: column; max-width: 400px; @@ -127,14 +127,22 @@ a { align-items: center; overflow: hidden; } -.card2 button { +.card-revoke a { max-width: 50px; width: 100%; background: none; border: none; cursor: pointer; } -.card2 svg { +.card-revoke button { + max-width: 200px; + width: 100%; + background: none; + border: none; + cursor: pointer; + color: #78a6de; +} +.card-revoke svg { width: 100%; height: auto; fill: #333; From 2726522e99ccdc90342d501b02b590465e54c5b4 Mon Sep 17 00:00:00 2001 From: Yousra Assouhaji <yousra.assouhaji@atos.net> Date: Tue, 2 Apr 2024 07:26:48 +0000 Subject: [PATCH 33/90] Replace Prd_list.rs --- crates/sp_client/src/Prd_list.rs | 44 +++++++++++++++----------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/crates/sp_client/src/Prd_list.rs b/crates/sp_client/src/Prd_list.rs index fea1218..2a3923b 100644 --- a/crates/sp_client/src/Prd_list.rs +++ b/crates/sp_client/src/Prd_list.rs @@ -1,26 +1,34 @@ +use bitcoin::PublicKey; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; +//use sp_backend::silentpayments::sending::SilentPaymentAddress; use tsify::Tsify; use wasm_bindgen::prelude::*; use std::marker::Copy; #[wasm_bindgen] -#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)] + +#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq, Copy)] pub enum Role { Manager, #[default] User, } +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub struct SilentPaymentAddress { + version : u8, + scan_pubkey : PublicKey, + m_pubkey : PublicKey, + is_testnet : bool, +} -#[derive(Serialize, Deserialize, Debug, Copy, Clone)] -//use std :: marker; -//strings can't implement copy -#[wasm_bindgen] + +#[derive(Debug, Copy, Clone)] pub struct ItemMember { pub role : Role, - pub sp_address: u32, + pub sp_address: SilentPaymentAddress, //pre_id: hash(password, part1) //shard, //priv_key_mainnet_spend, (enc) @@ -29,40 +37,29 @@ pub struct ItemMember { } impl ItemMember { - pub fn new(role: Role, sp_address: u32) -> Self { + pub fn new(role: Role, sp_address: SilentPaymentAddress) -> Self { ItemMember {role, sp_address} } } -#[derive(Debug, Serialize)] -#[wasm_bindgen] +#[derive(Debug, Clone)] pub struct Prdlist { //pub id: String, //pub version: String, pub gestionnaires: Vec<ItemMember>, + // pub gestionnaires: Box<Vec<ItemMember>>, } -//auto inscription in the list (not included) -/* -fn auto_enroll(prdlist: &mut Prdlist, role: Role, sp_address: u32) { - let item_member = ItemMember { - role, //just as a user - sp_address, - }; - prdlist.gestionnaires.push(item_member); //not gestionnaires but users - -}*/ -//fn send_transaction(prdlist: &Prdlist){} -//fn send_PrdMessage (prdlist: &Prdlist){} + #[derive(Serialize)] +#[wasm_bindgen] struct RequestBody { message: String, } -#[wasm_bindgen] -pub async fn send_PrdRequest(prdlist: &Prdlist) -> Result<(), JsValue> { +pub fn send_PrdRequest(prdlist: &Prdlist) -> Result<(), JsValue> { let managers: Vec<&ItemMember> = prdlist.gestionnaires.iter().filter(|m| m.role == Role::Manager).collect(); for manager in managers { let request_body = RequestBody { @@ -83,3 +80,4 @@ pub async fn send_PrdRequest(prdlist: &Prdlist) -> Result<(), JsValue> { + From d5a1dc5ddfd30e91f9c8132b0f7557e6169b0a70 Mon Sep 17 00:00:00 2001 From: franck <franck.petretto@atos.net> Date: Tue, 2 Apr 2024 09:40:08 +0200 Subject: [PATCH 34/90] add recover page, change this. to Services.instance. --- src/index.ts | 8 ++++++-- src/services.ts | 13 ++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/index.ts b/src/index.ts index 90a47e7..ee9560d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,8 +4,12 @@ import IndexedDB from './database' document.addEventListener('DOMContentLoaded', async () => { try { const services = await Services.getInstance(); - - await services.displayCreateId(); + if ((await services.isNewUser())) { + await services.displayCreateId(); + } + else { + await services.displayRecover() + } } catch (error) { console.error(error); } diff --git a/src/services.ts b/src/services.ts index 8667a03..59f7215 100644 --- a/src/services.ts +++ b/src/services.ts @@ -61,7 +61,7 @@ class Services { public async displayCreateId(): Promise<void> { Services.instance.injectHtml(Services.instance.get_html_create_id()); - Services.instance.attachSubmitListener("form4nk", (event) => this.createId(event)); + Services.instance.attachSubmitListener("form4nk", (event) => Services.instance.createId(event)); Services.instance.attachClickListener("displayrecover", Services.instance.displayRecover); Services.instance.displayProcess(await Services.instance.getAllProcess()); } @@ -143,7 +143,7 @@ class Services { public async displayRevokeImage(): Promise<void> { const html = Services.instance.get_html_revokeimage(); Services.instance.injectHtml(html); - Services.instance.attachClickListener("displayupdateanid", Services.instance.revokeimage); + Services.instance.attachClickListener("displayupdateanid", Services.instance.displayUpdateAnId); let imageBytes = await Services.instance.getRecoverImage('assets/4nk_revoke.jpg'); if (imageBytes != null) { @@ -174,11 +174,6 @@ class Services { return imageBytes; } - public async revokeimage(event: Event): Promise<void> { - event.preventDefault(); - await Services.instance.displayUpdateAnId(); - } - public async displayRevoke(): Promise<void> { const html = Services.instance.get_html_revoke(); Services.instance.injectHtml(html); @@ -198,7 +193,7 @@ class Services { } public async displayUpdateAnId() { - console.log("JS displayUpdateAnId process : "+this.current_process); + console.log("JS displayUpdateAnId process : "+Services.instance.current_process); let body = ""; let style = ""; let script = ""; @@ -206,7 +201,7 @@ class Services { const indexedDB = await IndexedDB.getInstance(); const db = indexedDB.getDb(); try { - let processObject = await indexedDB.getObject<Processstore>(db, indexedDB.getStoreList().AnkProcess, this.current_process!); + let processObject = await indexedDB.getObject<Processstore>(db, indexedDB.getStoreList().AnkProcess, Services.instance.current_process!); body = processObject.html; style = processObject.style; script = processObject.script; From db4a3fd1fc063e8526ba5be8553d16090afedb34 Mon Sep 17 00:00:00 2001 From: Yousra Assouhaji <yousra.assouhaji@atos.net> Date: Tue, 2 Apr 2024 07:53:40 +0000 Subject: [PATCH 35/90] Replace lib.rs --- crates/sp_client/src/lib.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index c7a01f3..367b9a9 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -1,6 +1,8 @@ #![allow(warnings)] -mod aesgcm; pub mod api; mod injecteurhtml; -mod process; mod user; +mod aesgcm; +mod secretdata; +mod Prd_list; + From 030cc0231a084cb727e0954c1eada1316f325d16 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Tue, 2 Apr 2024 14:19:25 +0200 Subject: [PATCH 36/90] User creation + login --- crates/sp_client/src/Prd_list.rs | 56 ++++----- crates/sp_client/src/api.rs | 45 ++++++- crates/sp_client/src/lib.rs | 8 +- crates/sp_client/src/peers.rs | 9 ++ crates/sp_client/src/user.rs | 209 ++++++++----------------------- 5 files changed, 128 insertions(+), 199 deletions(-) create mode 100644 crates/sp_client/src/peers.rs diff --git a/crates/sp_client/src/Prd_list.rs b/crates/sp_client/src/Prd_list.rs index dc0867d..e8e8185 100644 --- a/crates/sp_client/src/Prd_list.rs +++ b/crates/sp_client/src/Prd_list.rs @@ -1,14 +1,12 @@ -use sp_backend::bitcoin::PublicKey; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; +use sp_backend::bitcoin::PublicKey; //use sp_backend::silentpayments::sending::SilentPaymentAddress; +use std::marker::Copy; use tsify::Tsify; use wasm_bindgen::prelude::*; -use std::marker::Copy; - #[wasm_bindgen] - #[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq, Copy)] pub enum Role { Manager, @@ -18,27 +16,26 @@ pub enum Role { #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] pub struct SilentPaymentAddress { - version : u8, - scan_pubkey : PublicKey, - m_pubkey : PublicKey, - is_testnet : bool, + version: u8, + scan_pubkey: PublicKey, + m_pubkey: PublicKey, + is_testnet: bool, } - #[derive(Debug, Copy, Clone)] pub struct ItemMember { - pub role : Role, - pub sp_address: SilentPaymentAddress, + pub role: Role, + pub sp_address: SilentPaymentAddress, //pre_id: hash(password, part1) //shard, //priv_key_mainnet_spend, (enc) - //priv_key_mainnet_scan, - //priv_key_signet_scan, + //priv_key_mainnet_scan, + //priv_key_signet_scan, } impl ItemMember { pub fn new(role: Role, sp_address: SilentPaymentAddress) -> Self { - ItemMember {role, sp_address} + ItemMember { role, sp_address } } } @@ -46,38 +43,31 @@ impl ItemMember { pub struct Prdlist { //pub id: String, //pub version: String, - pub gestionnaires: Vec<ItemMember>, - // pub gestionnaires: Box<Vec<ItemMember>>, + pub gestionnaires: Vec<ItemMember>, + // pub gestionnaires: Box<Vec<ItemMember>>, } - - - #[derive(Serialize)] #[wasm_bindgen] struct RequestBody { message: String, } -pub fn send_PrdRequest(prdlist: &Prdlist) -> Result<(), JsValue> { - let managers: Vec<&ItemMember> = prdlist.gestionnaires.iter().filter(|m| m.role == Role::Manager).collect(); +pub fn send_PrdRequest(prdlist: &Prdlist) -> Result<(), JsValue> { + let managers: Vec<&ItemMember> = prdlist + .gestionnaires + .iter() + .filter(|m| m.role == Role::Manager) + .collect(); for manager in managers { let request_body = RequestBody { message: "Asking for the Prd list".to_string(), }; - - let json_body = serde_json::to_string(&request_body).map_err(|e| JsValue::from_str(&format!("Failed to serialize request body: {:?}", e)))?; + + let json_body = serde_json::to_string(&request_body).map_err(|e| { + JsValue::from_str(&format!("Failed to serialize request body: {:?}", e)) + })?; println!("Sending request to manager {:?}", manager.sp_address); } Ok(()) } - - - - - - - - - - diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 145dccf..ae4752c 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -128,20 +128,21 @@ pub fn get_receiving_address(sp_client: String) -> String { #[wasm_bindgen] pub fn create_user( - password: String, + password: String, // Attention à la conversion depuis le js label: Option<String>, - birthday: u32, + birthday_main: u32, + birthday_signet: u32, process: String, ) -> ApiResult<createUserReturn> { let mut output_list: Vec<OutputList> = Vec::new(); //recover - let sp_wallet_recover = generate_sp_wallet(label.clone(), birthday, true)?; + let sp_wallet_recover = generate_sp_wallet(label.clone(), birthday_signet, true)?; output_list.push(sp_wallet_recover.sp_outputs); //revoke - let sp_wallet_revoke = generate_sp_wallet(label.clone(), birthday, true)?; + let sp_wallet_revoke = generate_sp_wallet(label.clone(), birthday_signet, true)?; output_list.push(sp_wallet_revoke.sp_outputs); //mainet - let sp_wallet_main = generate_sp_wallet(label, birthday, false)?; + let sp_wallet_main = generate_sp_wallet(label, birthday_main, false)?; output_list.push(sp_wallet_main.sp_outputs); let user_keys = UserKeys::new( @@ -195,3 +196,37 @@ pub fn get_processes() -> ApiResult<get_process_return> { data_process.push(process3); Ok(get_process_return(data_process)) } + +#[derive(Debug, Tsify, Serialize, Deserialize)] +#[tsify(from_wasm_abi)] +#[allow(non_camel_case_types)] +pub struct recover_data(Vec<u8>); + +impl recover_data { + fn as_inner(&self) -> &[u8] { + &self.0 + } +} + +#[derive(Debug, Tsify, Serialize, Deserialize)] +#[tsify(from_wasm_abi)] +#[allow(non_camel_case_types)] +pub struct shamir_shares(Vec<Vec<u8>>); + +impl shamir_shares { + fn as_inner(&self) -> &[Vec<u8>] { + &self.0 + } +} + +#[wasm_bindgen] +pub fn login_user( + user_password: String, + pre_id: String, + recover: recover_data, + shares: shamir_shares, +) -> ApiResult<()> { + let res = User::login(pre_id, user_password, recover.as_inner(), shares.as_inner())?; + + Ok(res) +} diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index 4f1409e..bceda87 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -1,8 +1,8 @@ #![allow(warnings)] +mod Prd_list; +mod aesgcm; pub mod api; mod injecteurhtml; -mod user; -mod aesgcm; -mod Prd_list; +mod peers; mod process; - +mod user; diff --git a/crates/sp_client/src/peers.rs b/crates/sp_client/src/peers.rs new file mode 100644 index 0000000..5f7d207 --- /dev/null +++ b/crates/sp_client/src/peers.rs @@ -0,0 +1,9 @@ +use std::net::SocketAddr; + +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Peer { + pub addr: SocketAddr, + pub processes: Vec<String>, +} diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index 852327c..50ee132 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -16,7 +16,6 @@ use sp_backend::bitcoin::secp256k1::ThirtyTwoByteHash; use tsify::Tsify; use wasm_bindgen::prelude::*; -use bytes::Bytes; use shamir::SecretData; use std::collections::HashMap; use std::fs::File; @@ -37,10 +36,14 @@ use img_parts::{ImageEXIF, ImageICC}; use crate::aesgcm::Aes256Decryption; use crate::aesgcm::HalfKey; use crate::aesgcm::{Aes256Encryption, Purpose}; +use crate::peers::Peer; use crate::user; type PreId = String; +const MANAGERS_NUMBER: u8 = 10; +const QUORUM_SHARD: f32 = 0.8; + pub static CONNECTED_USERS: OnceLock<Mutex<HashMap<PreId, UserKeys>>> = OnceLock::new(); #[derive(Debug, Clone, Serialize, Deserialize)] @@ -67,11 +70,12 @@ impl UserKeys { #[derive(Debug, Serialize, Deserialize, Clone, Tsify)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct User { - pub pre_id: String, - pub process: String, + pub pre_id: PreId, + pub processes: Vec<String>, + pub peers: Vec<Peer>, recover_data: Vec<u8>, revoke_data: Option<Vec<u8>>, - sharding: Sharding, + shares: Vec<Vec<u8>>, } impl User { @@ -143,7 +147,18 @@ impl User { let cipher_recover_part2 = part2_encryption.encrypt_with_aes_key()?; //create shardings - let sharding = Sharding::new(&cipher_recover_part2.to_lower_hex_string(), 10u8); //nMembers = 10 for testing, need to recover nmember elsewhere + let threshold = (MANAGERS_NUMBER as f32 * QUORUM_SHARD).floor(); + debug_assert!(threshold > 0.0 && threshold <= u8::MAX as f32); + let sharding = shamir::SecretData::with_secret( + &cipher_recover_part2.to_lower_hex_string(), + threshold as u8, + ); + + let shares: Vec<Vec<u8>> = (1..MANAGERS_NUMBER) + .map(|x| { + sharding.get_share(x).unwrap() // Let's trust it for now + }) + .collect(); //scan key: let mut engine = sha256::HashEngine::default(); @@ -171,10 +186,11 @@ impl User { Ok(User { pre_id: pre_id.to_string(), - process, + processes: vec![process], + peers: vec![], recover_data, revoke_data: Some(revoke_data), - sharding, + shares, }) } @@ -182,7 +198,7 @@ impl User { pre_id: PreId, user_password: String, recover_data: &[u8], - sharding: Sharding, + shares: &[Vec<u8>], ) -> Result<()> { let mut retrieved_spend_key = [0u8; 32]; let mut retrieved_scan_key = [0u8; 32]; @@ -228,13 +244,10 @@ impl User { part1_ciphertext.to_vec(), )?); - //@todo: get shardings from member managers! - let shardings = sharding.shares_vec.clone(); // temporary - retrieved_spend_key[16..].copy_from_slice(&Self::recover_part2( &user_password, &entropy2, - shardings, + shares, )?); retrieved_scan_key.copy_from_slice(&Self::recover_key_slice( @@ -309,17 +322,17 @@ impl User { aes_dec.decrypt_with_key() } - fn recover_part2(password: &str, entropy: &[u8], shares_vec: Vec<Vec<u8>>) -> Result<Vec<u8>> { + fn recover_part2(password: &str, entropy: &[u8], shares: &[Vec<u8>]) -> Result<Vec<u8>> { let mut engine = sha256::HashEngine::default(); engine.write_all(&password.as_bytes()); engine.write_all(&entropy); let hash = sha256::Hash::from_engine(engine); - let shares_total: f32 = u8::try_from(shares_vec.len())?.try_into()?; - let quorum_sharding: u8 = (Sharding::QUORUM_SHARD * shares_total).round() as u8; + let threshold = (MANAGERS_NUMBER as f32 * QUORUM_SHARD).floor(); + debug_assert!(threshold > 0.0 && threshold <= u8::MAX as f32); let part2_key_enc = Vec::from_hex( - &SecretData::recover_secret(quorum_sharding, shares_vec) + &SecretData::recover_secret(threshold as u8, shares.to_vec()) .ok_or_else(|| anyhow::Error::msg("Failed to retrieve the sharded secret"))?, )?; @@ -356,141 +369,27 @@ impl User { // sha_256(&password_hash) // } - // Test sharing JS side - pub fn get_shares(&self) -> Vec<String> { - self.sharding.shares_format_str.clone() - } + // // Test sharing JS side + // pub fn get_shares(&self) -> Vec<String> { + // self.sharding.shares_format_str.clone() + // } - //Test sharing Js side - pub fn get_secret(&self, shardings: Vec<String>) -> String { - let mut shares_vec = Vec::new(); + // //Test sharing Js side + // pub fn get_secret(&self, shardings: Vec<String>) -> String { + // let mut shares_vec = Vec::new(); - for s in shardings.iter() { - let bytes_vec: Vec<u8> = s - .trim_matches(|c| c == '[' || c == ']') - .split(',') - .filter_map(|s| s.trim().parse().ok()) - .collect(); - shares_vec.push(bytes_vec); - } - self.sharding.recover_secrete(shares_vec.clone()) - } + // for s in shardings.iter() { + // let bytes_vec: Vec<u8> = s + // .trim_matches(|c| c == '[' || c == ']') + // .split(',') + // .filter_map(|s| s.trim().parse().ok()) + // .collect(); + // shares_vec.push(bytes_vec); + // } + // self.sharding.recover_secrete(shares_vec.clone()) + // } } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum BackUpImage { - Recover(Vec<u8>), - Revoke(Vec<u8>), -} - -impl BackUpImage { - pub fn new_recover(image: &[u8], data: &[u8]) -> Result<Self> { - let img = write_exif(image, data)?; - Ok(Self::Recover(img)) - } - - pub fn new_revoke(image: &[u8], data: &[u8]) -> Result<Self> { - let img = write_exif(image, data)?; - Ok(Self::Revoke(img)) - } -} - -#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct Sharding { - shares_vec: Vec<Vec<u8>>, - shares_format_str: Vec<String>, -} - -impl Sharding { - const QUORUM_SHARD: f32 = 0.80_f32; - pub fn new(part2_key_enc: &str, number_members: u8) -> Self { - let secret_data = SecretData::with_secret(part2_key_enc, number_members); - let mut shares_format_str: Vec<String> = Vec::new(); - let shares_vec = (1..=number_members) - .map(|i| match secret_data.get_share(i) { - Ok(share) => { - let string = format!( - "[{}]", - share - .clone() - .iter() - .map(|b| format!("{}", b)) - .collect::<Vec<_>>() - .join(",") - ); - shares_format_str.push(string.clone()); - share - } - Err(_) => panic!("Not able to recover the shares!"), - }) - .collect::<Vec<_>>(); - - Sharding { - shares_vec, - shares_format_str, - } - } - - pub fn recover_secrete(&self, shares: Vec<Vec<u8>>) -> String { - let quorum_sharding = (Self::QUORUM_SHARD * f32::from(shares.len() as u8)).round() as u8; - SecretData::recover_secret(quorum_sharding, shares).unwrap() - } -} - -pub fn write_exif(image_to_recover: &[u8], data: &[u8]) -> Result<Vec<u8>> { - let mut jpeg = Jpeg::from_bytes(Bytes::from(image_to_recover.to_vec()))?; - let data_bytes = Bytes::from(data.to_owned()); - jpeg.set_exif(Some(data_bytes)); - let output_image_bytes = jpeg.encoder().bytes(); - let output_image = output_image_bytes.to_vec(); - Ok(output_image) -} - -pub fn read_exif(image: &[u8]) -> Result<Vec<u8>, String> { - let image_bytes = Bytes::from(image.to_vec()); - let jpeg = Jpeg::from_bytes(image_bytes).unwrap(); - - //exif out - let mut exif_image = Bytes::new(); - if let Some(ref meta) = jpeg.exif() { - exif_image = meta.clone(); - } else { - return Err("No exif data".to_string()); - } - let exif_bytes = exif_image.as_ref(); - Ok(exif_bytes.to_vec()) -} - -// //change for return Result? -// pub fn from_hex_to_b58(hex_string: &str) -> String { -// let decoded_data = hex::decode(hex_string).expect("Failed to decode hex string"); -// let base58_string = bs58::encode(decoded_data).into_string(); -// base58_string -// } -// //change for return Result? -// pub fn from_b58_to_hex(base58_string: &str) -> String { -// let decoded_data = bs58::decode(base58_string.to_owned()).into_vec().unwrap(); -// let hex_string = decoded_data -// .iter() -// .map(|b| format!("{:02x}", b)) -// .collect::<String>(); -// hex_string -// } - -// fn from_b64_to_hex(base64_string: &str) -> String { -// let decoded_data = base64::decode(base64_string).unwrap(); -// let hex_string = decoded_data -// .iter() -// .map(|b| format!("{:02x}", b)) -// .collect::<String>(); -// hex_string -// } -// fn from_hex_to_b64(hex_string: &str) -> String { -// let decoded_data = hex::decode(hex_string).expect("Failed to decode hex string"); -// let base64_string = base64::encode(decoded_data); -// base64_string -// } - #[cfg(test)] mod tests { use super::*; // Import everything from the outer module @@ -550,22 +449,18 @@ mod tests { let user_keys = helper_create_user_keys(); let user = User::new(user_keys, USER_PASSWORD.to_owned(), PROCESS.to_owned()).unwrap(); - let pre_id = user.pre_id; - let recover_data = user.recover_data; - let sharding = user.sharding; - - let retrieved_recover_spend = User::login( - pre_id.clone(), + let res = User::login( + user.pre_id.clone(), USER_PASSWORD.to_owned(), - &recover_data, - sharding, + &user.recover_data, + &user.shares, ); - assert!(retrieved_recover_spend.is_ok()); + assert!(res.is_ok()); let connected = CONNECTED_USERS.get().unwrap().lock().unwrap(); - let recover = &connected.get(&pre_id).unwrap().recover; + let recover = &connected.get(&user.pre_id).unwrap().recover; assert!( format!( From f0bf17dd6a261031e61954c44294a61fe79750c0 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Tue, 2 Apr 2024 14:20:33 +0200 Subject: [PATCH 37/90] rm unnecessary dependencies --- crates/sp_client/Cargo.toml | 8 -------- crates/sp_client/src/api.rs | 1 - crates/sp_client/src/user.rs | 3 --- 3 files changed, 12 deletions(-) diff --git a/crates/sp_client/Cargo.toml b/crates/sp_client/Cargo.toml index 2c4acb8..46cdf31 100644 --- a/crates/sp_client/Cargo.toml +++ b/crates/sp_client/Cargo.toml @@ -18,17 +18,9 @@ wasm-logger = "0.2.0" rand = "0.8.5" log = "0.4.6" tsify = { git = "https://github.com/Sosthene00/tsify", branch = "next" } -web-sys = { version = "0.3", features = ["console"] } -bs58 = "0.4" -hex = "0.4.3" -sha2 = "0.10.8" aes-gcm = "0.10.3" aes = "0.8.3" -base64 = "0.21.7" -image = "0.24.9" -img-parts = "0.3.0" bytes = "1.5.0" -scrypt = "0.11.0" shamir = { git = "https://github.com/Sosthene00/shamir", branch = "master" } [dev-dependencies] diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index ae4752c..c28fd22 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -17,7 +17,6 @@ use wasm_bindgen::prelude::*; use sp_backend::spclient::SpendKey; use sp_backend::spclient::{derive_keys_from_seed, OutputList, SpClient}; -use web_sys::js_sys::JsString; use crate::user::{User, UserKeys, CONNECTED_USERS}; diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index 50ee132..e793f74 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -30,9 +30,6 @@ use sp_backend::silentpayments::sending::SilentPaymentAddress; use sp_backend::spclient::SpendKey; use sp_backend::spclient::{OutputList, SpClient}; -use img_parts::jpeg::Jpeg; -use img_parts::{ImageEXIF, ImageICC}; - use crate::aesgcm::Aes256Decryption; use crate::aesgcm::HalfKey; use crate::aesgcm::{Aes256Encryption, Purpose}; From fbddacdeb889ef1301ad7b1c595305e549c08543 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Tue, 2 Apr 2024 14:30:10 +0200 Subject: [PATCH 38/90] rm bytes dependency --- crates/sp_client/Cargo.toml | 1 - crates/sp_client/src/user.rs | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/sp_client/Cargo.toml b/crates/sp_client/Cargo.toml index 46cdf31..3a82e7a 100644 --- a/crates/sp_client/Cargo.toml +++ b/crates/sp_client/Cargo.toml @@ -20,7 +20,6 @@ log = "0.4.6" tsify = { git = "https://github.com/Sosthene00/tsify", branch = "next" } aes-gcm = "0.10.3" aes = "0.8.3" -bytes = "1.5.0" shamir = { git = "https://github.com/Sosthene00/shamir", branch = "master" } [dev-dependencies] diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index e793f74..8058cdd 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -4,7 +4,6 @@ use aes_gcm::AeadCore; use aes_gcm::KeyInit; use aes_gcm::{aead::Buffer, Aes256Gcm, Key}; use anyhow::{Error, Result}; -use bytes::Buf; use rand::{self, thread_rng, Rng, RngCore}; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; @@ -19,8 +18,7 @@ use wasm_bindgen::prelude::*; use shamir::SecretData; use std::collections::HashMap; use std::fs::File; -use std::io::Read; -use std::io::Write; +use std::io::{Read, Write, Cursor}; use std::str::FromStr; use std::sync::{Mutex, OnceLock}; @@ -205,7 +203,7 @@ impl User { let mut cipher_scan_key = [0u8; 60]; let mut part1_ciphertext = [0u8; 44]; - let mut reader = recover_data.reader(); + let mut reader = Cursor::new(recover_data); reader.read_exact(&mut entropy1)?; reader.read_exact(&mut entropy2)?; reader.read_exact(&mut entropy3)?; From c209bee651af579188b97dd96b4f1572a554437a Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 3 Apr 2024 10:02:05 +0200 Subject: [PATCH 39/90] Integrate process wasm/ts --- crates/sp_client/src/aesgcm.rs | 447 ------------------------- crates/sp_client/src/api.rs | 46 ++- crates/sp_client/src/crypto.rs | 448 +++++++++++++++++++++++++- crates/sp_client/src/injecteurhtml.rs | 105 ------ crates/sp_client/src/lib.rs | 3 +- crates/sp_client/src/process.rs | 324 ++++++++++++++++++- crates/sp_client/src/user.rs | 8 +- src/database.ts | 33 +- src/index.ts | 1 + src/services.ts | 176 +++++----- src/store/processstore.ts | 237 -------------- 11 files changed, 923 insertions(+), 905 deletions(-) delete mode 100644 crates/sp_client/src/aesgcm.rs delete mode 100644 crates/sp_client/src/injecteurhtml.rs delete mode 100644 src/store/processstore.ts diff --git a/crates/sp_client/src/aesgcm.rs b/crates/sp_client/src/aesgcm.rs deleted file mode 100644 index 59ab295..0000000 --- a/crates/sp_client/src/aesgcm.rs +++ /dev/null @@ -1,447 +0,0 @@ -use std::collections::HashMap; - -use anyhow::{Error, Result}; -use sp_backend::{ - bitcoin::{ - consensus::serde::hex, - hex::DisplayHex, - key::constants::SECRET_KEY_SIZE, - secp256k1::{ecdh::SharedSecret, SecretKey}, - Txid, - }, - silentpayments::sending::SilentPaymentAddress, -}; -use wasm_bindgen::JsValue; - -use serde::{Deserialize, Serialize}; -use serde_json::{json, Value}; - -use aes::cipher::generic_array::GenericArray; -use aes::{ - cipher::consts::{U32, U8}, - Aes256, -}; -use aes_gcm::{ - aead::{Aead, AeadInPlace, KeyInit, Nonce}, - AeadCore, Aes256Gcm, AesGcm, Key, TagSize, -}; -use rand::{thread_rng, RngCore}; - -const HALFKEYSIZE: usize = SECRET_KEY_SIZE / 2; - -const THIRTYTWO: usize = 32; - -pub struct HalfKey([u8; HALFKEYSIZE]); - -impl TryFrom<Vec<u8>> for HalfKey { - type Error = anyhow::Error; - fn try_from(value: Vec<u8>) -> std::prelude::v1::Result<Self, Error> { - if value.len() == HALFKEYSIZE { - let mut buf = [0u8; HALFKEYSIZE]; - buf.copy_from_slice(&value); - Ok(HalfKey(buf)) - } else { - Err(Error::msg("Invalid length for HalfKey")) - } - } -} - -impl HalfKey { - pub fn as_slice(&self) -> &[u8] { - &self.0 - } - - pub fn to_inner(&self) -> Vec<u8> { - self.0.to_vec() - } -} - -pub enum Purpose { - Login, - ThirtyTwoBytes, -} - -pub type CipherText = Vec<u8>; - -pub type EncryptedKey = Vec<u8>; - -pub struct Aes256Decryption { - pub purpose: Purpose, - cipher_text: CipherText, - aes_key: [u8; 32], - nonce: [u8; 12], -} - -impl Aes256Decryption { - pub fn new( - purpose: Purpose, - cipher_text: CipherText, - encrypted_aes_key: Vec<u8>, // If shared_secret is none this is actually the aes_key - shared_secret: Option<SharedSecret>, // We don't need that for certain purpose, like Login - ) -> Result<Self> { - let mut aes_key = [0u8; 32]; - if let Some(shared_secret) = shared_secret { - if encrypted_aes_key.len() <= 12 { - return Err(Error::msg("encrypted_aes_key is shorter than nonce length")); - } // Actually we could probably test that if the remnant is not a multiple of 32, something's wrong - // take the first 12 bytes form encrypted_aes_key as nonce - let (decrypt_key_nonce, encrypted_key) = encrypted_aes_key.split_at(12); - // decrypt key with shared_secret obtained from transaction - let decrypt_key_cipher = Aes256Gcm::new_from_slice(shared_secret.as_ref()) - .map_err(|e| Error::msg(format!("{}", e)))?; - let aes_key_plain = decrypt_key_cipher - .decrypt(decrypt_key_nonce.into(), encrypted_key) - .map_err(|e| Error::msg(format!("{}", e)))?; - if aes_key_plain.len() != 32 { - return Err(Error::msg("Invalid length for decrypted key")); - } - aes_key.copy_from_slice(&aes_key_plain); - } else { - if encrypted_aes_key.len() != 32 { - return Err(Error::msg("Invalid length for decrypted key")); - } - aes_key.copy_from_slice(&encrypted_aes_key); - } - if cipher_text.len() <= 12 { - return Err(Error::msg("cipher_text is shorter than nonce length")); - } - let (message_nonce, message_cipher) = cipher_text.split_at(12); - let mut nonce = [0u8; 12]; - nonce.copy_from_slice(message_nonce); - Ok(Self { - purpose, - cipher_text: message_cipher.to_vec(), - aes_key, - nonce, - }) - } - - pub fn decrypt_with_key(&self) -> Result<Vec<u8>> { - match self.purpose { - Purpose::Login => { - let half_key = self.decrypt_login()?; - Ok(half_key.to_inner()) - } - Purpose::ThirtyTwoBytes => { - let thirty_two_buf = self.decrypt_thirty_two()?; - Ok(thirty_two_buf.to_vec()) - } - } - } - - fn decrypt_login(&self) -> Result<HalfKey> { - let cipher = Aes256Gcm::new(&self.aes_key.into()); - let plain = cipher - .decrypt(&self.nonce.into(), &*self.cipher_text) - .map_err(|e| Error::msg(format!("{}", e)))?; - if plain.len() != SECRET_KEY_SIZE / 2 { - return Err(Error::msg("Plain text of invalid lenght for a login")); - } - let mut key_half = [0u8; SECRET_KEY_SIZE / 2]; - key_half.copy_from_slice(&plain); - Ok(HalfKey(key_half)) - } - - fn decrypt_thirty_two(&self) -> Result<[u8; THIRTYTWO]> { - let cipher = Aes256Gcm::new(&self.aes_key.into()); - let plain = cipher - .decrypt(&self.nonce.into(), &*self.cipher_text) - .map_err(|e| Error::msg(format!("{}", e)))?; - if plain.len() != THIRTYTWO { - return Err(Error::msg("Plain text of invalid length, should be 32")); - } - let mut thirty_two = [0u8; THIRTYTWO]; - thirty_two.copy_from_slice(&plain); - Ok(thirty_two) - } -} - -pub struct Aes256Encryption { - pub purpose: Purpose, - plaintext: Vec<u8>, - aes_key: [u8; 32], - nonce: [u8; 12], - shared_secrets: HashMap<Txid, HashMap<SilentPaymentAddress, SharedSecret>>, -} - -impl Aes256Encryption { - pub fn new(purpose: Purpose, plaintext: Vec<u8>) -> Result<Self> { - let mut rng = thread_rng(); - let aes_key: [u8; 32] = Aes256Gcm::generate_key(&mut rng).into(); - let nonce: [u8; 12] = Aes256Gcm::generate_nonce(&mut rng).into(); - Self::import_key(purpose, plaintext, aes_key, nonce) - } - - pub fn set_shared_secret( - &mut self, - shared_secrets: HashMap<Txid, HashMap<SilentPaymentAddress, SharedSecret>>, - ) { - self.shared_secrets = shared_secrets; - } - - pub fn encrypt_keys_with_shared_secrets( - &self, - ) -> Result<HashMap<SilentPaymentAddress, EncryptedKey>> { - let mut res = HashMap::new(); - let mut rng = thread_rng(); - - for (_, sp_address2shared_secret) in self.shared_secrets.iter() { - for (sp_address, shared_secret) in sp_address2shared_secret { - let cipher = Aes256Gcm::new_from_slice(shared_secret.as_ref()) - .map_err(|e| Error::msg(format!("{}", e)))?; - let nonce = Aes256Gcm::generate_nonce(&mut rng); - let encrypted_key = cipher - .encrypt(&nonce, self.aes_key.as_slice()) - .map_err(|e| Error::msg(format!("{}", e)))?; - - let mut ciphertext = Vec::<u8>::with_capacity(nonce.len() + encrypted_key.len()); - ciphertext.extend(nonce); - ciphertext.extend(encrypted_key); - - res.insert(sp_address.to_owned(), ciphertext); - } - } - Ok(res) - } - - pub fn import_key( - purpose: Purpose, - plaintext: Vec<u8>, - aes_key: [u8; 32], - nonce: [u8; 12], - ) -> Result<Self> { - if plaintext.len() == 0 { - return Err(Error::msg("Can't create encryption for an empty message")); - } - Ok(Self { - purpose, - plaintext, - aes_key, - nonce, - shared_secrets: HashMap::new(), - }) - } - - pub fn encrypt_with_aes_key(&self) -> Result<CipherText> { - match self.purpose { - Purpose::Login => self.encrypt_login(), - Purpose::ThirtyTwoBytes => self.encrypt_thirty_two(), - } - } - - fn encrypt_login(&self) -> Result<CipherText> { - let half_key: HalfKey = self.plaintext.clone().try_into()?; - let cipher = Aes256Gcm::new(&self.aes_key.into()); - let cipher_text = cipher - .encrypt(&self.nonce.into(), half_key.as_slice()) - .map_err(|e| Error::msg(format!("{}", e)))?; - let mut res = Vec::with_capacity(self.nonce.len() + cipher_text.len()); - res.extend_from_slice(&self.nonce); - res.extend_from_slice(&cipher_text); - Ok(res) - } - - fn encrypt_thirty_two(&self) -> Result<CipherText> { - if self.plaintext.len() != 32 { - return Err(Error::msg("Invalid length, should be 32")); - } - let mut thirty_two = [0u8; 32]; - thirty_two.copy_from_slice(&self.plaintext); - let cipher = Aes256Gcm::new(&self.aes_key.into()); - let cipher_text = cipher - .encrypt(&self.nonce.into(), thirty_two.as_slice()) - .map_err(|e| Error::msg(format!("{}", e)))?; - let mut res = Vec::with_capacity(self.nonce.len() + cipher_text.len()); - log::info!("{}", cipher_text.len()); - res.extend_from_slice(&self.nonce); - res.extend_from_slice(&cipher_text); - Ok(res) - } -} - -#[cfg(test)] -mod tests { - use std::str::FromStr; - - use super::*; - - const ALICE_SP_ADDRESS: &str = "tsp1qqw3lqr6xravz9nf8ntazgwwl0fqv47kfjdxsnxs6eutavqfwyv5q6qk97mmyf6dtkdyzqlu2zv6h9j2ggclk7vn705q5u2phglpq7yw3dg5rwpdz"; - const BOB_SP_ADDRESS: &str = "tsp1qq2hlsgrj0gz8kcfkf9flqw5llz0u2vr04telqndku9mcqm6dl4fhvq60t8r78srrf56w9yr7w9e9dusc2wjqc30up6fjwnh9mw3e3veqegdmtf08"; - const TRANSACTION: &str = "4e6d03dec558e1b6624f813bf2da7cd8d8fb1c2296684c08cf38724dcfd8d10b"; - const ALICE_SHARED_SECRET: &str = - "ccf02d364c2641ca129a3fdf49de57b705896e233f7ba6d738991993ea7e2106"; - const BOB_SHARED_SECRET: &str = - "15ef3e377fb842e81de52dbaaea8ba30aeb051a81043ee19264afd27353da521"; - - #[test] - fn new_aes_empty_plaintext() { - let plaintext = Vec::new(); - let aes_enc = Aes256Encryption::new(Purpose::Login, plaintext); - - assert!(aes_enc.is_err()); - } - - #[test] - fn aes_encrypt_login_invalid_length() { - let plaintext = "example"; - let aes_enc_short = Aes256Encryption::new(Purpose::Login, plaintext.as_bytes().to_vec()); - - assert!(aes_enc_short.is_ok()); - - let cipher = aes_enc_short.unwrap().encrypt_with_aes_key(); - - assert!(cipher.is_err()); - - let plaintext = [1u8; 64]; - let aes_enc_long = Aes256Encryption::new(Purpose::Login, plaintext.to_vec()); - - assert!(aes_enc_long.is_ok()); - - let cipher = aes_enc_long.unwrap().encrypt_with_aes_key(); - - assert!(cipher.is_err()); - } - - #[test] - fn aes_encrypt_login() { - let plaintext = [1u8; HALFKEYSIZE]; - let aes_key = Aes256Gcm::generate_key(&mut thread_rng()); - let nonce = Aes256Gcm::generate_nonce(&mut thread_rng()); - let aes_enc = Aes256Encryption::import_key( - Purpose::Login, - plaintext.to_vec(), - aes_key.into(), - nonce.into(), - ); - - assert!(aes_enc.is_ok()); - - let cipher = aes_enc.unwrap().encrypt_with_aes_key(); - - assert!(cipher.is_ok()); - - let mut plain_key = [0u8; 32]; - plain_key.copy_from_slice(&aes_key.to_vec()); - - let aes_dec = - Aes256Decryption::new(Purpose::Login, cipher.unwrap(), plain_key.to_vec(), None); - - assert!(aes_dec.is_ok()); - } - - #[test] - fn aes_encrypt_key() { - let plaintext = [1u8; HALFKEYSIZE]; - let mut aes_enc = Aes256Encryption::new(Purpose::Login, plaintext.to_vec()).unwrap(); - - let mut shared_secrets: HashMap<Txid, _> = HashMap::new(); - let mut sp_address2shared_secrets: HashMap<SilentPaymentAddress, SharedSecret> = - HashMap::new(); - sp_address2shared_secrets.insert( - ALICE_SP_ADDRESS.try_into().unwrap(), - SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap(), - ); - shared_secrets.insert( - Txid::from_str(TRANSACTION).unwrap(), - sp_address2shared_secrets, - ); - - aes_enc.set_shared_secret(shared_secrets); - - let sp_address2encrypted_keys = aes_enc.encrypt_keys_with_shared_secrets(); - - assert!(sp_address2encrypted_keys.is_ok()); - - let encrypted_key = sp_address2encrypted_keys - .unwrap() - .get(&ALICE_SP_ADDRESS.try_into().unwrap()) - .cloned(); - - let ciphertext = aes_enc.encrypt_with_aes_key(); - - assert!(ciphertext.is_ok()); - - let aes_dec = Aes256Decryption::new( - Purpose::Login, - ciphertext.unwrap(), - encrypted_key.unwrap(), - Some(SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap()), - ); - - assert!(aes_dec.is_ok()); - - let retrieved_plain = aes_dec.unwrap().decrypt_with_key(); - - assert!(retrieved_plain.is_ok()); - - assert!(retrieved_plain.unwrap() == plaintext); - } - - #[test] - fn aes_encrypt_key_many() { - let plaintext = [1u8; THIRTYTWO]; - let mut aes_enc = - Aes256Encryption::new(Purpose::ThirtyTwoBytes, plaintext.to_vec()).unwrap(); - - let mut shared_secrets: HashMap<Txid, _> = HashMap::new(); - let mut sp_address2shared_secrets: HashMap<SilentPaymentAddress, SharedSecret> = - HashMap::new(); - sp_address2shared_secrets.insert( - ALICE_SP_ADDRESS.try_into().unwrap(), - SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap(), - ); - sp_address2shared_secrets.insert( - BOB_SP_ADDRESS.try_into().unwrap(), - SharedSecret::from_str(BOB_SHARED_SECRET).unwrap(), - ); - shared_secrets.insert( - Txid::from_str(TRANSACTION).unwrap(), - sp_address2shared_secrets, - ); - - aes_enc.set_shared_secret(shared_secrets); - - let mut sp_address2encrypted_keys = aes_enc.encrypt_keys_with_shared_secrets(); - - assert!(sp_address2encrypted_keys.is_ok()); - - // Alice - let encrypted_key = sp_address2encrypted_keys - .as_mut() - .unwrap() - .get(&ALICE_SP_ADDRESS.try_into().unwrap()) - .cloned(); - - let ciphertext = aes_enc.encrypt_with_aes_key(); - - let aes_dec = Aes256Decryption::new( - Purpose::ThirtyTwoBytes, - ciphertext.unwrap(), - encrypted_key.unwrap(), - Some(SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap()), - ); - - let retrieved_plain = aes_dec.unwrap().decrypt_with_key(); - - assert!(retrieved_plain.unwrap() == plaintext); - - // Bob - let encrypted_key = sp_address2encrypted_keys - .unwrap() - .get(&BOB_SP_ADDRESS.try_into().unwrap()) - .cloned(); - - let ciphertext = aes_enc.encrypt_with_aes_key(); - - let aes_dec = Aes256Decryption::new( - Purpose::ThirtyTwoBytes, - ciphertext.unwrap(), - encrypted_key.unwrap(), - Some(SharedSecret::from_str(BOB_SHARED_SECRET).unwrap()), - ); - - let retrieved_plain = aes_dec.unwrap().decrypt_with_key(); - - assert!(retrieved_plain.unwrap() == plaintext); - } -} diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index c28fd22..4c44949 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -173,19 +173,49 @@ pub fn get_processes() -> ApiResult<get_process_return> { //instances of process let process1 = Process { - id: String::from("1"), + id: 1, + name: String::from("CREATE_ID"), version: String::from("1.0"), - gestionnaires: vec![member1.clone(), member2.clone()], + members: vec![member1.clone(), member2.clone()], + html: crate::process::HTML_CREATE_ID.to_owned(), + style: crate::process::CSS.to_owned(), + script: "".to_owned(), }; let process2 = Process { - id: String::from("2"), - version: String::from("2.0"), - gestionnaires: vec![member2.clone(), member3.clone()], + id: 2, + name: String::from("UPDATE_ID"), + version: String::from("1.0"), + members: vec![member1.clone(), member2.clone()], + html: crate::process::HTML_UPDATE_ID.to_owned(), + style: crate::process::CSS.to_owned(), + script: "".to_owned(), }; let process3 = Process { - id: String::from("3"), + id: 3, + name: String::from("RECOVER"), version: String::from("1.0"), - gestionnaires: vec![member3.clone(), member1.clone()], + members: vec![member1.clone(), member2.clone()], + html: crate::process::HTML_RECOVER.to_owned(), + style: crate::process::CSS.to_owned(), + script: "".to_owned(), + }; + let process4 = Process { + id: 4, + name: String::from("REVOKE_IMAGE"), + version: String::from("1.0"), + members: vec![member1.clone(), member2.clone()], + html: crate::process::HTML_REVOKE_IMAGE.to_owned(), + style: crate::process::CSS.to_owned(), + script: "".to_owned(), + }; + let process5 = Process { + id: 5, + name: String::from("REVOKE"), + version: String::from("1.0"), + members: vec![member1.clone(), member2.clone()], + html: crate::process::HTML_REVOKE.to_owned(), + style: crate::process::CSS.to_owned(), + script: "".to_owned(), }; // vec with the instances of processes @@ -193,6 +223,8 @@ pub fn get_processes() -> ApiResult<get_process_return> { data_process.push(process1); data_process.push(process2); data_process.push(process3); + data_process.push(process4); + data_process.push(process5); Ok(get_process_return(data_process)) } diff --git a/crates/sp_client/src/crypto.rs b/crates/sp_client/src/crypto.rs index 0372315..59ab295 100644 --- a/crates/sp_client/src/crypto.rs +++ b/crates/sp_client/src/crypto.rs @@ -1,9 +1,447 @@ -use aes_gcm; +use std::collections::HashMap; -pub enum KeyType { - Aes256GcmIv96BitKey([u8;32]) +use anyhow::{Error, Result}; +use sp_backend::{ + bitcoin::{ + consensus::serde::hex, + hex::DisplayHex, + key::constants::SECRET_KEY_SIZE, + secp256k1::{ecdh::SharedSecret, SecretKey}, + Txid, + }, + silentpayments::sending::SilentPaymentAddress, +}; +use wasm_bindgen::JsValue; + +use serde::{Deserialize, Serialize}; +use serde_json::{json, Value}; + +use aes::cipher::generic_array::GenericArray; +use aes::{ + cipher::consts::{U32, U8}, + Aes256, +}; +use aes_gcm::{ + aead::{Aead, AeadInPlace, KeyInit, Nonce}, + AeadCore, Aes256Gcm, AesGcm, Key, TagSize, +}; +use rand::{thread_rng, RngCore}; + +const HALFKEYSIZE: usize = SECRET_KEY_SIZE / 2; + +const THIRTYTWO: usize = 32; + +pub struct HalfKey([u8; HALFKEYSIZE]); + +impl TryFrom<Vec<u8>> for HalfKey { + type Error = anyhow::Error; + fn try_from(value: Vec<u8>) -> std::prelude::v1::Result<Self, Error> { + if value.len() == HALFKEYSIZE { + let mut buf = [0u8; HALFKEYSIZE]; + buf.copy_from_slice(&value); + Ok(HalfKey(buf)) + } else { + Err(Error::msg("Invalid length for HalfKey")) + } + } } -pub struct EncryptionKey { - sk: KeyType +impl HalfKey { + pub fn as_slice(&self) -> &[u8] { + &self.0 + } + + pub fn to_inner(&self) -> Vec<u8> { + self.0.to_vec() + } +} + +pub enum Purpose { + Login, + ThirtyTwoBytes, +} + +pub type CipherText = Vec<u8>; + +pub type EncryptedKey = Vec<u8>; + +pub struct Aes256Decryption { + pub purpose: Purpose, + cipher_text: CipherText, + aes_key: [u8; 32], + nonce: [u8; 12], +} + +impl Aes256Decryption { + pub fn new( + purpose: Purpose, + cipher_text: CipherText, + encrypted_aes_key: Vec<u8>, // If shared_secret is none this is actually the aes_key + shared_secret: Option<SharedSecret>, // We don't need that for certain purpose, like Login + ) -> Result<Self> { + let mut aes_key = [0u8; 32]; + if let Some(shared_secret) = shared_secret { + if encrypted_aes_key.len() <= 12 { + return Err(Error::msg("encrypted_aes_key is shorter than nonce length")); + } // Actually we could probably test that if the remnant is not a multiple of 32, something's wrong + // take the first 12 bytes form encrypted_aes_key as nonce + let (decrypt_key_nonce, encrypted_key) = encrypted_aes_key.split_at(12); + // decrypt key with shared_secret obtained from transaction + let decrypt_key_cipher = Aes256Gcm::new_from_slice(shared_secret.as_ref()) + .map_err(|e| Error::msg(format!("{}", e)))?; + let aes_key_plain = decrypt_key_cipher + .decrypt(decrypt_key_nonce.into(), encrypted_key) + .map_err(|e| Error::msg(format!("{}", e)))?; + if aes_key_plain.len() != 32 { + return Err(Error::msg("Invalid length for decrypted key")); + } + aes_key.copy_from_slice(&aes_key_plain); + } else { + if encrypted_aes_key.len() != 32 { + return Err(Error::msg("Invalid length for decrypted key")); + } + aes_key.copy_from_slice(&encrypted_aes_key); + } + if cipher_text.len() <= 12 { + return Err(Error::msg("cipher_text is shorter than nonce length")); + } + let (message_nonce, message_cipher) = cipher_text.split_at(12); + let mut nonce = [0u8; 12]; + nonce.copy_from_slice(message_nonce); + Ok(Self { + purpose, + cipher_text: message_cipher.to_vec(), + aes_key, + nonce, + }) + } + + pub fn decrypt_with_key(&self) -> Result<Vec<u8>> { + match self.purpose { + Purpose::Login => { + let half_key = self.decrypt_login()?; + Ok(half_key.to_inner()) + } + Purpose::ThirtyTwoBytes => { + let thirty_two_buf = self.decrypt_thirty_two()?; + Ok(thirty_two_buf.to_vec()) + } + } + } + + fn decrypt_login(&self) -> Result<HalfKey> { + let cipher = Aes256Gcm::new(&self.aes_key.into()); + let plain = cipher + .decrypt(&self.nonce.into(), &*self.cipher_text) + .map_err(|e| Error::msg(format!("{}", e)))?; + if plain.len() != SECRET_KEY_SIZE / 2 { + return Err(Error::msg("Plain text of invalid lenght for a login")); + } + let mut key_half = [0u8; SECRET_KEY_SIZE / 2]; + key_half.copy_from_slice(&plain); + Ok(HalfKey(key_half)) + } + + fn decrypt_thirty_two(&self) -> Result<[u8; THIRTYTWO]> { + let cipher = Aes256Gcm::new(&self.aes_key.into()); + let plain = cipher + .decrypt(&self.nonce.into(), &*self.cipher_text) + .map_err(|e| Error::msg(format!("{}", e)))?; + if plain.len() != THIRTYTWO { + return Err(Error::msg("Plain text of invalid length, should be 32")); + } + let mut thirty_two = [0u8; THIRTYTWO]; + thirty_two.copy_from_slice(&plain); + Ok(thirty_two) + } +} + +pub struct Aes256Encryption { + pub purpose: Purpose, + plaintext: Vec<u8>, + aes_key: [u8; 32], + nonce: [u8; 12], + shared_secrets: HashMap<Txid, HashMap<SilentPaymentAddress, SharedSecret>>, +} + +impl Aes256Encryption { + pub fn new(purpose: Purpose, plaintext: Vec<u8>) -> Result<Self> { + let mut rng = thread_rng(); + let aes_key: [u8; 32] = Aes256Gcm::generate_key(&mut rng).into(); + let nonce: [u8; 12] = Aes256Gcm::generate_nonce(&mut rng).into(); + Self::import_key(purpose, plaintext, aes_key, nonce) + } + + pub fn set_shared_secret( + &mut self, + shared_secrets: HashMap<Txid, HashMap<SilentPaymentAddress, SharedSecret>>, + ) { + self.shared_secrets = shared_secrets; + } + + pub fn encrypt_keys_with_shared_secrets( + &self, + ) -> Result<HashMap<SilentPaymentAddress, EncryptedKey>> { + let mut res = HashMap::new(); + let mut rng = thread_rng(); + + for (_, sp_address2shared_secret) in self.shared_secrets.iter() { + for (sp_address, shared_secret) in sp_address2shared_secret { + let cipher = Aes256Gcm::new_from_slice(shared_secret.as_ref()) + .map_err(|e| Error::msg(format!("{}", e)))?; + let nonce = Aes256Gcm::generate_nonce(&mut rng); + let encrypted_key = cipher + .encrypt(&nonce, self.aes_key.as_slice()) + .map_err(|e| Error::msg(format!("{}", e)))?; + + let mut ciphertext = Vec::<u8>::with_capacity(nonce.len() + encrypted_key.len()); + ciphertext.extend(nonce); + ciphertext.extend(encrypted_key); + + res.insert(sp_address.to_owned(), ciphertext); + } + } + Ok(res) + } + + pub fn import_key( + purpose: Purpose, + plaintext: Vec<u8>, + aes_key: [u8; 32], + nonce: [u8; 12], + ) -> Result<Self> { + if plaintext.len() == 0 { + return Err(Error::msg("Can't create encryption for an empty message")); + } + Ok(Self { + purpose, + plaintext, + aes_key, + nonce, + shared_secrets: HashMap::new(), + }) + } + + pub fn encrypt_with_aes_key(&self) -> Result<CipherText> { + match self.purpose { + Purpose::Login => self.encrypt_login(), + Purpose::ThirtyTwoBytes => self.encrypt_thirty_two(), + } + } + + fn encrypt_login(&self) -> Result<CipherText> { + let half_key: HalfKey = self.plaintext.clone().try_into()?; + let cipher = Aes256Gcm::new(&self.aes_key.into()); + let cipher_text = cipher + .encrypt(&self.nonce.into(), half_key.as_slice()) + .map_err(|e| Error::msg(format!("{}", e)))?; + let mut res = Vec::with_capacity(self.nonce.len() + cipher_text.len()); + res.extend_from_slice(&self.nonce); + res.extend_from_slice(&cipher_text); + Ok(res) + } + + fn encrypt_thirty_two(&self) -> Result<CipherText> { + if self.plaintext.len() != 32 { + return Err(Error::msg("Invalid length, should be 32")); + } + let mut thirty_two = [0u8; 32]; + thirty_two.copy_from_slice(&self.plaintext); + let cipher = Aes256Gcm::new(&self.aes_key.into()); + let cipher_text = cipher + .encrypt(&self.nonce.into(), thirty_two.as_slice()) + .map_err(|e| Error::msg(format!("{}", e)))?; + let mut res = Vec::with_capacity(self.nonce.len() + cipher_text.len()); + log::info!("{}", cipher_text.len()); + res.extend_from_slice(&self.nonce); + res.extend_from_slice(&cipher_text); + Ok(res) + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use super::*; + + const ALICE_SP_ADDRESS: &str = "tsp1qqw3lqr6xravz9nf8ntazgwwl0fqv47kfjdxsnxs6eutavqfwyv5q6qk97mmyf6dtkdyzqlu2zv6h9j2ggclk7vn705q5u2phglpq7yw3dg5rwpdz"; + const BOB_SP_ADDRESS: &str = "tsp1qq2hlsgrj0gz8kcfkf9flqw5llz0u2vr04telqndku9mcqm6dl4fhvq60t8r78srrf56w9yr7w9e9dusc2wjqc30up6fjwnh9mw3e3veqegdmtf08"; + const TRANSACTION: &str = "4e6d03dec558e1b6624f813bf2da7cd8d8fb1c2296684c08cf38724dcfd8d10b"; + const ALICE_SHARED_SECRET: &str = + "ccf02d364c2641ca129a3fdf49de57b705896e233f7ba6d738991993ea7e2106"; + const BOB_SHARED_SECRET: &str = + "15ef3e377fb842e81de52dbaaea8ba30aeb051a81043ee19264afd27353da521"; + + #[test] + fn new_aes_empty_plaintext() { + let plaintext = Vec::new(); + let aes_enc = Aes256Encryption::new(Purpose::Login, plaintext); + + assert!(aes_enc.is_err()); + } + + #[test] + fn aes_encrypt_login_invalid_length() { + let plaintext = "example"; + let aes_enc_short = Aes256Encryption::new(Purpose::Login, plaintext.as_bytes().to_vec()); + + assert!(aes_enc_short.is_ok()); + + let cipher = aes_enc_short.unwrap().encrypt_with_aes_key(); + + assert!(cipher.is_err()); + + let plaintext = [1u8; 64]; + let aes_enc_long = Aes256Encryption::new(Purpose::Login, plaintext.to_vec()); + + assert!(aes_enc_long.is_ok()); + + let cipher = aes_enc_long.unwrap().encrypt_with_aes_key(); + + assert!(cipher.is_err()); + } + + #[test] + fn aes_encrypt_login() { + let plaintext = [1u8; HALFKEYSIZE]; + let aes_key = Aes256Gcm::generate_key(&mut thread_rng()); + let nonce = Aes256Gcm::generate_nonce(&mut thread_rng()); + let aes_enc = Aes256Encryption::import_key( + Purpose::Login, + plaintext.to_vec(), + aes_key.into(), + nonce.into(), + ); + + assert!(aes_enc.is_ok()); + + let cipher = aes_enc.unwrap().encrypt_with_aes_key(); + + assert!(cipher.is_ok()); + + let mut plain_key = [0u8; 32]; + plain_key.copy_from_slice(&aes_key.to_vec()); + + let aes_dec = + Aes256Decryption::new(Purpose::Login, cipher.unwrap(), plain_key.to_vec(), None); + + assert!(aes_dec.is_ok()); + } + + #[test] + fn aes_encrypt_key() { + let plaintext = [1u8; HALFKEYSIZE]; + let mut aes_enc = Aes256Encryption::new(Purpose::Login, plaintext.to_vec()).unwrap(); + + let mut shared_secrets: HashMap<Txid, _> = HashMap::new(); + let mut sp_address2shared_secrets: HashMap<SilentPaymentAddress, SharedSecret> = + HashMap::new(); + sp_address2shared_secrets.insert( + ALICE_SP_ADDRESS.try_into().unwrap(), + SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap(), + ); + shared_secrets.insert( + Txid::from_str(TRANSACTION).unwrap(), + sp_address2shared_secrets, + ); + + aes_enc.set_shared_secret(shared_secrets); + + let sp_address2encrypted_keys = aes_enc.encrypt_keys_with_shared_secrets(); + + assert!(sp_address2encrypted_keys.is_ok()); + + let encrypted_key = sp_address2encrypted_keys + .unwrap() + .get(&ALICE_SP_ADDRESS.try_into().unwrap()) + .cloned(); + + let ciphertext = aes_enc.encrypt_with_aes_key(); + + assert!(ciphertext.is_ok()); + + let aes_dec = Aes256Decryption::new( + Purpose::Login, + ciphertext.unwrap(), + encrypted_key.unwrap(), + Some(SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap()), + ); + + assert!(aes_dec.is_ok()); + + let retrieved_plain = aes_dec.unwrap().decrypt_with_key(); + + assert!(retrieved_plain.is_ok()); + + assert!(retrieved_plain.unwrap() == plaintext); + } + + #[test] + fn aes_encrypt_key_many() { + let plaintext = [1u8; THIRTYTWO]; + let mut aes_enc = + Aes256Encryption::new(Purpose::ThirtyTwoBytes, plaintext.to_vec()).unwrap(); + + let mut shared_secrets: HashMap<Txid, _> = HashMap::new(); + let mut sp_address2shared_secrets: HashMap<SilentPaymentAddress, SharedSecret> = + HashMap::new(); + sp_address2shared_secrets.insert( + ALICE_SP_ADDRESS.try_into().unwrap(), + SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap(), + ); + sp_address2shared_secrets.insert( + BOB_SP_ADDRESS.try_into().unwrap(), + SharedSecret::from_str(BOB_SHARED_SECRET).unwrap(), + ); + shared_secrets.insert( + Txid::from_str(TRANSACTION).unwrap(), + sp_address2shared_secrets, + ); + + aes_enc.set_shared_secret(shared_secrets); + + let mut sp_address2encrypted_keys = aes_enc.encrypt_keys_with_shared_secrets(); + + assert!(sp_address2encrypted_keys.is_ok()); + + // Alice + let encrypted_key = sp_address2encrypted_keys + .as_mut() + .unwrap() + .get(&ALICE_SP_ADDRESS.try_into().unwrap()) + .cloned(); + + let ciphertext = aes_enc.encrypt_with_aes_key(); + + let aes_dec = Aes256Decryption::new( + Purpose::ThirtyTwoBytes, + ciphertext.unwrap(), + encrypted_key.unwrap(), + Some(SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap()), + ); + + let retrieved_plain = aes_dec.unwrap().decrypt_with_key(); + + assert!(retrieved_plain.unwrap() == plaintext); + + // Bob + let encrypted_key = sp_address2encrypted_keys + .unwrap() + .get(&BOB_SP_ADDRESS.try_into().unwrap()) + .cloned(); + + let ciphertext = aes_enc.encrypt_with_aes_key(); + + let aes_dec = Aes256Decryption::new( + Purpose::ThirtyTwoBytes, + ciphertext.unwrap(), + encrypted_key.unwrap(), + Some(SharedSecret::from_str(BOB_SHARED_SECRET).unwrap()), + ); + + let retrieved_plain = aes_dec.unwrap().decrypt_with_key(); + + assert!(retrieved_plain.unwrap() == plaintext); + } } diff --git a/crates/sp_client/src/injecteurhtml.rs b/crates/sp_client/src/injecteurhtml.rs deleted file mode 100644 index 1d18e90..0000000 --- a/crates/sp_client/src/injecteurhtml.rs +++ /dev/null @@ -1,105 +0,0 @@ -use wasm_bindgen::prelude::*; - -#[wasm_bindgen] -pub fn inject_html_create_id() -> String { - String::from( - " - <div class='card'> - <div class='side-by-side'> - <h3>Create an Id</h3> - <div><a href='#'>Processes</a></div> - </div> - <form id='form4nk' action='#'> - <label for='password'>Password :</label> - <input type='password' id='password' /><hr/> - <input type='hidden' id='currentpage' value='creatid' /> - <select id='selectProcess' class='custom-select'></select><hr/> - <div class='side-by-side'> - <button type='submit' id='submitButton' class='bg-primary'>Create</button> - <div> - <a href='#' id='displayrecover'>Recover</a> - </div> - </div> - </form><br/> - <div id='passwordalert' class='passwordalert'></div> - </div> - ", - ) -} - -#[wasm_bindgen] -pub fn inject_html_recover() -> String { - String::from(" - <div class='card'> - <div class='side-by-side'> - <h3>Recover my Id</h3> - <div><a href='#'>Processes</a></div> - </div> - <form id='form4nk' action='#'> - <label for='password'>Password :</label> - <input type='password' id='password' /> - <input type='hidden' id='currentpage' value='recover' /> - <select id='selectProcess' class='custom-select'></select><hr/> - <div class='side-by-side'> - <button type='submit' id='submitButton' class='recover bg-primary'>Recover</button> - <div> - <a href='#' id='displaycreateid'>Create an Id</a> - </div> - </div><hr/> - <a href='#' id='displayrevoke' class='btn'>Revoke</a> - </form><br/> - <div id='passwordalert' class='passwordalert'></div> - </div> - ") -} - -#[wasm_bindgen] -pub fn inject_html_revokeimage() -> String { - String::from(" - <div class='card'> - <div class='side-by-side'> - <h3>Revoke image</h3> - <div><a href='#' id='displayupdateanid'>Update an Id</a></div> - </div> - </div> - <div class='card-revoke'> - <a href='#' download='revoke_4NK.jpg' id='revoke'> - <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'> - <path - d='M246.6 9.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 109.3V320c0 17.7 14.3 32 32 32s32-14.3 32-32V109.3l73.4 73.4c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-128-128zM64 352c0-17.7-14.3-32-32-32s-32 14.3-32 32v64c0 53 43 96 96 96H352c53 0 96-43 96-96V352c0-17.7-14.3-32-32-32s-32 14.3-32 32v64c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V352z' - /> - </svg> - </a> - <div class='image-container'> - <img src='assets/4nk_revoke.jpg' alt='' /> - </div> - </div> - ") -} - -#[wasm_bindgen] -pub fn inject_html_revoke() -> String { - String::from( - " - <div class='card'> - <div class='side-by-side'> - <h3>Revoke an Id</h3> - <div> - <a href='#' id='displayrecover'>Recover</a> - </div> - </div> - <form id='form4nk' action='#'> - <label for='password'>Password :</label> - <input type='password' id='password' /> - <hr/> - <div class='image-container'> - <label class='image-label'>Revoke image</label> - <img src='assets/revoke.jpeg' alt='' /> - </div> - <hr/> - <button type='submit' id='submitButton' class='recover bg-primary'>Revoke</button> - </form> - </div> - ", - ) -} diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index bceda87..9898215 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -1,8 +1,7 @@ #![allow(warnings)] mod Prd_list; -mod aesgcm; pub mod api; -mod injecteurhtml; +mod crypto; mod peers; mod process; mod user; diff --git a/crates/sp_client/src/process.rs b/crates/sp_client/src/process.rs index 4f384e8..3338cf6 100644 --- a/crates/sp_client/src/process.rs +++ b/crates/sp_client/src/process.rs @@ -3,6 +3,321 @@ use serde_json::{json, Value}; use tsify::Tsify; use wasm_bindgen::prelude::*; +pub const HTML_CREATE_ID: &str = " + <div class='card'> + <div class='side-by-side'> + <h3>Create an Id</h3> + <div><a href='#'>Processes</a></div> + </div> + <form id='form4nk' action='#'> + <label for='password'>Password :</label> + <input type='password' id='password' /><hr/> + <input type='hidden' id='currentpage' value='creatid' /> + <select id='selectProcess' class='custom-select'></select><hr/> + <div class='side-by-side'> + <button type='submit' id='submitButton' class='bg-primary'>Create</button> + <div> + <a href='#' id='displayrecover'>Recover</a> + </div> + </div> + </form><br/> + <div id='passwordalert' class='passwordalert'></div> + </div> + "; + +pub const HTML_UPDATE_ID: &str = " + <body> + <div class='container'> + <div> + <h3>Update an Id</h3> + </div> + <hr /> + <form id='form4nk' action='#'> + <label for='firstName'>First Name:</label> + <input type='text' id='firstName' name='firstName' required /> + + <label for='lastName'>Last Name:</label> + <input type='text' id='lastName' name='lastName' required /> + + <label for='Birthday'>Birthday:</label> + <input type='date' id='Birthday' name='birthday' /> + + <label for='file'>File:</label> + <input type='file' id='fileInput' name='file' /> + + <label>Third parties:</label> + <div id='sp-address-block'> + <div class='side-by-side'> + <input + type='text' + name='sp-address' + id='sp-address' + placeholder='sp address' + form='no-form' + /> + <button + type='button' + class='circle-btn bg-secondary' + id='add-sp-address-btn' + > + + + </button> + </div> + </div> + <div class='div-text-area'> + <textarea + name='bio' + id='' + cols='30' + rows='10' + placeholder='Bio' + ></textarea> + </div> + <button type='submit' class='bg-primary'>Update</button> + </form> + </div> + </body> + "; + +pub const HTML_RECOVER: &str = " + <div class='card'> + <div class='side-by-side'> + <h3>Recover my Id</h3> + <div><a href='#'>Processes</a></div> + </div> + <form id='form4nk' action='#'> + <label for='password'>Password :</label> + <input type='password' id='password' /> + <input type='hidden' id='currentpage' value='recover' /> + <select id='selectProcess' class='custom-select'></select><hr/> + <div class='side-by-side'> + <button type='submit' id='submitButton' class='recover bg-primary'>Recover</button> + <div> + <a href='#' id='displaycreateid'>Create an Id</a> + </div> + </div><hr/> + <a href='#' id='displayrevoke' class='btn'>Revoke</a> + </form><br/> + <div id='passwordalert' class='passwordalert'></div> + </div> + "; + +pub const HTML_REVOKE_IMAGE: &str = " + <div class='card'> + <div class='side-by-side'> + <h3>Revoke image</h3> + <div><a href='#' id='displayupdateanid'>Update an Id</a></div> + </div> + </div> + <div class='card-revoke'> + <a href='#' download='revoke_4NK.jpg' id='revoke'> + <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'> + <path + d='M246.6 9.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 109.3V320c0 17.7 14.3 32 32 32s32-14.3 32-32V109.3l73.4 73.4c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-128-128zM64 352c0-17.7-14.3-32-32-32s-32 14.3-32 32v64c0 53 43 96 96 96H352c53 0 96-43 96-96V352c0-17.7-14.3-32-32-32s-32 14.3-32 32v64c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V352z' + /> + </svg> + </a> + <div class='image-container'> + <img src='assets/4nk_revoke.jpg' alt='' /> + </div> + </div> + "; + +pub const HTML_REVOKE: &str = " + <div class='card'> + <div class='side-by-side'> + <h3>Revoke an Id</h3> + <div> + <a href='#' id='displayrecover'>Recover</a> + </div> + </div> + <form id='form4nk' action='#'> + <label for='password'>Password :</label> + <input type='password' id='password' /> + <hr/> + <div class='image-container'> + <label class='image-label'>Revoke image</label> + <img src='assets/revoke.jpeg' alt='' /> + </div> + <hr/> + <button type='submit' id='submitButton' class='recover bg-primary'>Revoke</button> + </form> + </div> + "; + +pub const CSS: &str = " + body { + margin: 0; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + min-height: 100vh; + background-color: #f4f4f4; + font-family: 'Arial', sans-serif; + } + .container { + text-align: center; + } + .card { + max-width: 400px; + width: 100%; + padding: 20px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + background-color: #ffffff; + border-radius: 8px; + text-align: left; + overflow: hidden; + } + form { + display: flex; + flex-direction: column; + /* flex-wrap: wrap; */ + } + label { + font-weight: bold; + margin-bottom: 8px; + } + hr { + border: 0; + height: 1px; + background-color: #ddd; + margin: 10px 0; + } + input, select { + width: 100%; + padding: 10px; + margin: 8px 0; + box-sizing: border-box; + } + select { + padding: 10px; + background-color: #f9f9f9; + border: 1px solid #ddd; + border-radius: 4px; + cursor: pointer; + } + button { + display: inline-block; + background-color: #4caf50; + color: #fff; + border: none; + padding: 12px 17px; + border-radius: 4px; + cursor: pointer; + } + button:hover { + background-color: #45a049; + } + .side-by-side { + display: flex; + align-items: center; + justify-content: space-between; + } + .side-by-side>* { + display: inline-block; + } + button.recover { + display: inline-block; + text-align: center; + text-decoration: none; + display: inline-block; + background-color: #4caf50; + color: #fff; + border: none; + padding: 12px 17px; + border-radius: 4px; + cursor: pointer; + } + button.recover:hover { + background-color: #45a049; + } + a.btn { + display: inline-block; + text-align: center; + text-decoration: none; + display: inline-block; + background-color: #4caf50; + color: #fff; + border: none; + padding: 12px 17px; + border-radius: 4px; + cursor: pointer; + } + + a.btn:hover { + background-color: #45a049; + } + + a { + text-decoration: none; + color: #78a6de; + } + .bg-secondary { + background-color: #2b81ed; + } + .bg-primary { + background-color: #1A61ED; + } + .bg-primary:hover { + background-color: #457be8; + } + .card-revoke { + display: flex; + flex-direction: column; + max-width: 400px; + width: 100%; + padding: 20px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + background-color: #ffffff; + border-radius: 8px; + text-align: center; + align-items: center; + overflow: hidden; + } + .card-revoke a { + max-width: 50px; + width: 100%; + background: none; + border: none; + cursor: pointer; + } + .card-revoke button { + max-width: 200px; + width: 100%; + background: none; + border: none; + cursor: pointer; + color: #78a6de; + } + .card-revoke svg { + width: 100%; + height: auto; + fill: #333; + } + .image-label { + display: block; + color: #fff; + padding: 5px; + margin-top: 10px; + } + .image-container { + width: 400px; + height: 300px; + overflow: hidden; + } + .image-container img { + text-align: center; + width: 100%; + height: 100%; + object-fit: cover; + object-position: center center; + } + .passwordalert { + color: #FF0000; + } +"; + // process member (gestionnaire for now) #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub enum Role { @@ -10,6 +325,7 @@ pub enum Role { #[default] User, } + #[derive(Debug, Serialize, Deserialize, Default, Tsify, Clone)] #[tsify(into_wasm_abi)] pub struct ItemMember { @@ -31,8 +347,12 @@ impl ItemMember { #[derive(Debug, Serialize, Deserialize, Default, Tsify)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct Process { - pub id: String, + pub id: u32, + pub name: String, pub version: String, - pub gestionnaires: Vec<ItemMember>, + pub members: Vec<ItemMember>, + pub html: String, + pub style: String, + pub script: String, //item_name : String, } diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index 8058cdd..70835e2 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -18,7 +18,7 @@ use wasm_bindgen::prelude::*; use shamir::SecretData; use std::collections::HashMap; use std::fs::File; -use std::io::{Read, Write, Cursor}; +use std::io::{Cursor, Read, Write}; use std::str::FromStr; use std::sync::{Mutex, OnceLock}; @@ -28,9 +28,7 @@ use sp_backend::silentpayments::sending::SilentPaymentAddress; use sp_backend::spclient::SpendKey; use sp_backend::spclient::{OutputList, SpClient}; -use crate::aesgcm::Aes256Decryption; -use crate::aesgcm::HalfKey; -use crate::aesgcm::{Aes256Encryption, Purpose}; +use crate::crypto::{Aes256Decryption, Aes256Encryption, HalfKey, Purpose}; use crate::peers::Peer; use crate::user; @@ -200,7 +198,7 @@ impl User { let mut entropy1 = [0u8; 32]; let mut entropy2 = [0u8; 32]; let mut entropy3 = [0u8; 32]; - let mut cipher_scan_key = [0u8; 60]; + let mut cipher_scan_key = [0u8; 60]; // cipher length == plain.len() + 16 + nonce.len() let mut part1_ciphertext = [0u8; 44]; let mut reader = Cursor::new(recover_data); diff --git a/src/database.ts b/src/database.ts index 9d7245a..7413e88 100644 --- a/src/database.ts +++ b/src/database.ts @@ -38,8 +38,14 @@ class Database { }, AnkProcess: { name: "process", - options: {}, - indices: [] + options: {'keyPath': 'id'}, + indices: [{ + name: 'by_name', + keyPath: 'name', + options: { + 'unique': true + } + }] } } @@ -101,7 +107,7 @@ class Database { return objectList; } - public writeObject(db: IDBDatabase, storeName: string, obj: any, key: string | null): Promise<IDBRequest> { + public writeObject(db: IDBDatabase, storeName: string, obj: any, key: IDBValidKey | null): Promise<IDBRequest> { return new Promise((resolve, reject) => { const transaction = db.transaction(storeName, 'readwrite'); const store = transaction.objectStore(storeName); @@ -117,7 +123,7 @@ class Database { }); } - public getObject<T>(db: IDBDatabase, storeName: string, key: string | number): Promise<T> { + public getObject<T>(db: IDBDatabase, storeName: string, key: IDBValidKey): Promise<T> { return new Promise((resolve, reject) => { const transaction = db.transaction(storeName, 'readonly'); const store = transaction.objectStore(storeName); @@ -128,6 +134,25 @@ class Database { }); } + public getFirstMatchWithIndex<T>(db: IDBDatabase, storeName: string, indexName: string, lookup: string): Promise<T | null> { + return new Promise((resolve, reject) => { + const transaction = db.transaction(storeName, 'readonly'); + const store = transaction.objectStore(storeName); + const index = store.index(indexName); + const request = index.openCursor(IDBKeyRange.only(lookup)); + + request.onerror = () => reject(request.error); + request.onsuccess = () => { + const cursor = request.result; + if (cursor) { + resolve(cursor.value); + } else { + resolve(null) + } + } + }); + } + public setObject(db: IDBDatabase, storeName: string, obj: any, key: string | null): Promise<IDBRequest> { return new Promise((resolve, reject) => { const transaction = db.transaction(storeName, 'readwrite'); diff --git a/src/index.ts b/src/index.ts index ee9560d..4327e11 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,7 @@ import IndexedDB from './database' document.addEventListener('DOMContentLoaded', async () => { try { const services = await Services.getInstance(); + if ((await services.isNewUser())) { await services.displayCreateId(); } diff --git a/src/services.ts b/src/services.ts index 59f7215..a44ca3b 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,6 +1,5 @@ -import { createUserReturn, User } from '../dist/pkg/sdk_client'; +import { createUserReturn, User, Process } from '../dist/pkg/sdk_client'; import IndexedDB from './database' -import Processstore from './store/processstore'; class Services { private static instance: Services; @@ -60,14 +59,11 @@ class Services { } public async displayCreateId(): Promise<void> { - Services.instance.injectHtml(Services.instance.get_html_create_id()); - Services.instance.attachSubmitListener("form4nk", (event) => Services.instance.createId(event)); - Services.instance.attachClickListener("displayrecover", Services.instance.displayRecover); - Services.instance.displayProcess(await Services.instance.getAllProcess()); - } - - public get_html_create_id(): string { - return this.sdkClient.inject_html_create_id(); + const services = await Services.getInstance(); + await services.injectHtml('CREATE_ID'); + services.attachSubmitListener("form4nk", (event) => services.createId(event)); + services.attachClickListener("displayrecover", services.displayRecover); + services.displayProcess(); } public async createId(event: Event): Promise<void> { @@ -88,15 +84,14 @@ class Services { // if (!Services.instance.isPasswordValid(password)) return; let label = null; - let birthday = 50000; - const user: createUserReturn = this.sdkClient.create_user(password, label, birthday, this.current_process); + let birthday_signet = 50000; + let birthday_main = 500000; + const user: createUserReturn = this.sdkClient.create_user(password, label, birthday_main, birthday_signet, this.current_process); try { const indexedDb = await IndexedDB.getInstance(); const db = indexedDb.getDb(); await indexedDb.writeObject(db, indexedDb.getStoreList().AnkUser, user.user, null); - // console.log("JS User added"); - await indexedDb.writeObject(db, indexedDb.getStoreList().SpOutputs, user.output_list_vec, null); } catch (error) { console.error("Failed to write user object :", error); @@ -106,16 +101,13 @@ class Services { } public async displayRecover(): Promise<void> { - Services.instance.injectHtml(Services.instance.get_html_recover()); - Services.instance.attachSubmitListener("form4nk", Services.instance.recover); - Services.instance.attachClickListener("displaycreateid", Services.instance.displayCreateId); - Services.instance.attachClickListener("displayrevoke", Services.instance.displayRevoke); - Services.instance.attachClickListener("submitButtonRevoke", Services.instance.revoke); - Services.instance.displayProcess(await Services.instance.getAllUserProcess()); - } - - public get_html_recover(): string { - return this.sdkClient.inject_html_recover(); + const services = await Services.getInstance(); + services.injectHtml('RECOVER'); + services.attachSubmitListener("form4nk", services.recover); + services.attachClickListener("displaycreateid", services.displayCreateId); + services.attachClickListener("displayrevoke", services.displayRevoke); + services.attachClickListener("submitButtonRevoke", services.revoke); + services.displayProcess(); } public async recover(event: Event) { @@ -141,8 +133,7 @@ class Services { } public async displayRevokeImage(): Promise<void> { - const html = Services.instance.get_html_revokeimage(); - Services.instance.injectHtml(html); + Services.instance.injectHtml('REVOKE_IMAGE'); Services.instance.attachClickListener("displayupdateanid", Services.instance.displayUpdateAnId); let imageBytes = await Services.instance.getRecoverImage('assets/4nk_revoke.jpg'); @@ -155,10 +146,6 @@ class Services { } } - public get_html_revokeimage(): string { - return this.sdkClient.inject_html_revokeimage(); - } - private async getRecoverImage(imageUrl:string): Promise<Uint8Array|null> { let imageBytes = null; try { @@ -175,16 +162,11 @@ class Services { } public async displayRevoke(): Promise<void> { - const html = Services.instance.get_html_revoke(); - Services.instance.injectHtml(html); + Services.instance.injectHtml('REVOKE'); Services.instance.attachClickListener("displayrecover", Services.instance.displayRecover); Services.instance.attachSubmitListener("form4nk", Services.instance.revoke); } - public get_html_revoke(): string { - return this.sdkClient.inject_html_revoke(); - } - public async revoke(event: Event): Promise<void> { event.preventDefault(); console.log("JS revoke click "); @@ -198,18 +180,14 @@ class Services { let style = ""; let script = ""; try { - const indexedDB = await IndexedDB.getInstance(); - const db = indexedDB.getDb(); - try { - let processObject = await indexedDB.getObject<Processstore>(db, indexedDB.getStoreList().AnkProcess, Services.instance.current_process!); + const processObject = await this.getProcessByName(Services.instance.current_process!); + if (processObject) { body = processObject.html; style = processObject.style; script = processObject.script; - } catch (error) { - console.log("JS Processstore not exist "); } } catch (error) { - console.error("Failed to retrieve user object :", error); + console.error("Failed to retrieve process with Error:", error); } Services.instance.injectUpdateAnIdHtml(body, style, script); @@ -253,76 +231,82 @@ class Services { // TODO Mock add user member to process } - public displayProcess(processList: string[]): void { - console.log("JS processList : "+processList); + public async displayProcess(): Promise<void> { + const services = await Services.getInstance(); + const processList = await services.getAllProcess(); const selectProcess = document.getElementById("selectProcess"); if (selectProcess) { processList.forEach((process) => { - let child = new Option(process, process); + let child = new Option(process.name, process.name); if (!selectProcess.contains(child)) { selectProcess.appendChild(child); } }) } } - - public async getAllUserProcess(): Promise<string[]> { - let userProcessList: string[] = []; + + public async getAllProcess(): Promise<Process[]> { try { const indexedDB = await IndexedDB.getInstance(); const db = indexedDB.getDb(); - let processListObject = await indexedDB.getAll<Processstore>(db, indexedDB.getStoreList().AnkProcess); + let processListObject = await indexedDB.getAll<Process>(db, indexedDB.getStoreList().AnkProcess); + return processListObject; + } catch (error) { + console.log('getAllProcess failed: ',error); + return []; + } + } + + public async getAllProcessForUser(pre_id: string): Promise<Process[]> { + const services = await Services.getInstance(); + let user: User; + let userProcessList: Process[] = []; + try { + const indexedDB = await IndexedDB.getInstance(); + const db = indexedDB.getDb(); + user = await indexedDB.getObject<User>(db, indexedDB.getStoreList().AnkUser, pre_id); + } catch (error) { + console.error('getAllUserProcess failed: ',error); + return []; + } + + try { + const processListObject = await services.getAllProcess(); processListObject.forEach(async (processObject) => { - const listMember = processObject.listMember; - const processName = processObject.process; - listMember.forEach(async (member) => { - if (member == "user1") { - userProcessList.push(processName); - console.log("JS UserProcess found"); - } - }) + if (processObject.members.includes(user.pre_id)) { + userProcessList.push(processObject); + } }) } catch (error) { - console.log("JS Processstore not found"); + console.error('getAllUserProcess failed: ',error); + return []; } return userProcessList; } - public async getAllProcess(): Promise<string[]> { - // if indexedDB is empty, get list from wasm - let processList: string[] = []; - try { - const indexedDB = await IndexedDB.getInstance(); - const db = indexedDB.getDb(); - let processListObject = await indexedDB.getAll<Processstore>(db, indexedDB.getStoreList().AnkProcess); - processListObject.forEach(async (processObject) => { - const processName = processObject.process; - processList.push(processName); - console.log("JS Processstore found"); - }) - } catch (error) { - console.log("JS Processstore not found"); - } - if (processList.length == 0) { - processList = await this.addProcessStore(); - } - return processList; + public async getProcessByName(name: string): Promise<Process | null> { + const indexedDB = await IndexedDB.getInstance(); + const db = indexedDB.getDb(); + const process = await indexedDB.getFirstMatchWithIndex<Process>(db, indexedDB.getStoreList().AnkProcess, 'by_name', name); + + return process; } - public async addProcessStore(): Promise<string[]> { - const processList = this.sdkClient.get_process() - processList.forEach(async (process: string) => { - // TODO process mock - let processstore = new Processstore; - processstore.process = process; + public async loadProcesses(): Promise<void> { + const services = await Services.getInstance(); + const processList: Process[] = services.sdkClient.get_processes(); + processList.forEach(async (process: Process) => { const indexedDB = await IndexedDB.getInstance(); const db = indexedDB.getDb(); - await indexedDB.writeObject(db, indexedDB.getStoreList().AnkProcess, processstore, process); - console.log("JS Processstore mock added"); + try { + if (await indexedDB.getObject<Process>(db, indexedDB.getStoreList().AnkProcess, process.id) === null) { + await indexedDB.writeObject(db, indexedDB.getStoreList().AnkProcess, process, null); + } + } catch (error) { + console.warn('Error while writing process', process.name, 'to indexedDB:', error); + } }) - return processList; } - public attachClickListener(elementId: string, callback: (event: Event) => void): void { const element = document.getElementById(elementId); @@ -336,15 +320,25 @@ class Services { element?.addEventListener("submit", callback); } - public injectHtml(html: string) { - console.log("JS html : "+html); + public async injectHtml(processName: string) { + // console.log("JS html : "+html); const container = document.getElementById('containerId'); if (!container) { console.error("No html container"); return; } - container.innerHTML = html; + + const services = await Services.getInstance(); + + await services.loadProcesses(); + + const process = await services.getProcessByName(processName); + if (process) { + container.innerHTML = process.html; + } else { + console.error("No process ", processName); + } } // public async getCurrentProcess(): Promise<string> { diff --git a/src/store/processstore.ts b/src/store/processstore.ts deleted file mode 100644 index 76eb6b5..0000000 --- a/src/store/processstore.ts +++ /dev/null @@ -1,237 +0,0 @@ -class Processstore { - process: string; - html: string; - style: string; - script: string; - listMember: string[]; - createDate: Date; - - constructor() { - this.process = ""; - this.html = getMockHtml(); - this.style = getMockStyle(); - this.script = getMockScript(); - this.script = getMockScript(); - this.listMember = getMockListMember(); - this.createDate = new Date; - } -} - -export default Processstore; - -function getMockHtml(): string { - let html: string = ` - <body> - <div class='container'> - <div> - <h3>Update an Id</h3> - </div> - <hr /> - <form id='form4nk' action='#'> - <label for='firstName'>First Name:</label> - <input type='text' id='firstName' name='firstName' required /> - - <label for='lastName'>Last Name:</label> - <input type='text' id='lastName' name='lastName' required /> - - <label for='Birthday'>Birthday:</label> - <input type='date' id='Birthday' name='birthday' /> - - <label for='file'>File:</label> - <input type='file' id='fileInput' name='file' /> - - <label>Third parties:</label> - <div id='sp-address-block'> - <div class='side-by-side'> - <input - type='text' - name='sp-address' - id='sp-address' - placeholder='sp address' - form='no-form' - /> - <button - type='button' - class='circle-btn bg-secondary' - id='add-sp-address-btn' - > - + - </button> - </div> - </div> - <div class='div-text-area'> - <textarea - name='bio' - id='' - cols='30' - rows='10' - placeholder='Bio' - ></textarea> - </div> - <button type='submit' class='bg-primary'>Update</button> - </form> - </div> - </body> - `; - return html; -} - -function getMockStyle(): string { - let style: string = ` - <style> - body { - margin: 0; - padding: 0; - display: flex; - align-items: center; - justify-content: center; - min-height: 100vh; - background-color: #f4f4f4; - font-family: 'Arial', sans-serif; - } - - .container { - max-width: 400px; - width: 100%; - padding: 20px; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); - background-color: #ffffff; - border-radius: 8px; - text-align: left; - overflow: hidden; - } - - form { - display: grid; - grid-template-columns: repeat(1fr, 2fr); - gap: 10px; - max-width: 400px; - margin: auto; - } - - .bg-primary { - background-color: #1a61ed; - } - - .bg-primary:hover { - background-color: #457be8; - } - - .bg-secondary { - background-color: #2b81ed; - } - - .bg-secondary:hover { - background-color: #5f9bff; - } - - label { - text-align: left; - padding-right: 10px; - line-height: 2; - } - - input { - width: 100%; - padding: 8px; - box-sizing: border-box; - } - - button { - grid-column: span 2; - display: inline-block; - color: #fff; - border: none; - padding: 12px 17px; - border-radius: 4px; - cursor: pointer; - } - - .div-text-area { - grid-column: span 2; - } - - textarea { - width: 100%; - padding: 8px; - box-sizing: border-box; - } - - .side-by-side { - display: flex; - align-items: center; - justify-content: space-between; - gap: 10px; - margin-bottom: 5px; - } - .circle-btn { - width: 25px; - height: 25px; - border-radius: 50%; - border: none; - color: white; - padding: 0px; - text-align: center; - } - - #fileInput { - width: 100%; - padding: 8px; - padding-left: 0px; - box-sizing: border-box; - } - </style>`; - return style; -} - -function getMockScript(): string { - let script: string = ` - var addSpAddressBtn = document.getElementById('add-sp-address-btn'); - var removeSpAddressBtn = document.querySelectorAll('.minus-sp-address-btn'); - - addSpAddressBtn.addEventListener('click', function (event) { - addDynamicField(this); - }); - - function addDynamicField(element) { - var addSpAddressBlock = document.getElementById('sp-address-block'); - var spAddress = addSpAddressBlock.querySelector('#sp-address').value; - addSpAddressBlock.querySelector('#sp-address').value = ''; - spAddress = spAddress.trim(); - if (spAddress != '') { - var sideBySideDiv = document.createElement('div'); - sideBySideDiv.className = 'side-by-side'; - - var inputElement = document.createElement('input'); - inputElement.type = 'text'; - inputElement.name = 'spAddresses[]'; - inputElement.setAttribute('form', 'no-form'); - inputElement.value = spAddress; - inputElement.disabled = true; - - var buttonElement = document.createElement('button'); - buttonElement.type = 'button'; - buttonElement.className = - 'circle-btn bg-secondary minus-sp-address-btn'; - buttonElement.innerHTML = '-'; - - buttonElement.addEventListener('click', function (event) { - removeDynamicField(this.parentElement); - }); - - sideBySideDiv.appendChild(inputElement); - sideBySideDiv.appendChild(buttonElement); - - addSpAddressBlock.appendChild(sideBySideDiv); - } - function removeDynamicField(element) { - element.remove(); - } - } - `; - return script; -} - -function getMockListMember(): string[] { - return ["user1","user2","user3"]; -} \ No newline at end of file From e5f7339ff8948ec478737cbb6799c3a56bdb131f Mon Sep 17 00:00:00 2001 From: franck <franck.petretto@atos.net> Date: Wed, 3 Apr 2024 11:35:40 +0200 Subject: [PATCH 40/90] Modify to add process in indexedDB. --- src/services.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/services.ts b/src/services.ts index a44ca3b..7d11b65 100644 --- a/src/services.ts +++ b/src/services.ts @@ -180,7 +180,7 @@ class Services { let style = ""; let script = ""; try { - const processObject = await this.getProcessByName(Services.instance.current_process!); + const processObject = await Services.instance.getProcessByName(Services.instance.current_process!); if (processObject) { body = processObject.html; style = processObject.style; @@ -237,7 +237,7 @@ class Services { const selectProcess = document.getElementById("selectProcess"); if (selectProcess) { processList.forEach((process) => { - let child = new Option(process.name, process.name); + let child = new Option(process.id.toString(), process.id.toString()); if (!selectProcess.contains(child)) { selectProcess.appendChild(child); } @@ -285,9 +285,11 @@ class Services { } public async getProcessByName(name: string): Promise<Process | null> { + console.error('getProcessByName name: '+name); const indexedDB = await IndexedDB.getInstance(); const db = indexedDB.getDb(); const process = await indexedDB.getFirstMatchWithIndex<Process>(db, indexedDB.getStoreList().AnkProcess, 'by_name', name); + console.error('getProcessByName process: '+process); return process; } @@ -295,11 +297,15 @@ class Services { public async loadProcesses(): Promise<void> { const services = await Services.getInstance(); const processList: Process[] = services.sdkClient.get_processes(); + console.error('processList size: '+processList.length); + processList.forEach(async (process: Process) => { const indexedDB = await IndexedDB.getInstance(); const db = indexedDB.getDb(); try { - if (await indexedDB.getObject<Process>(db, indexedDB.getStoreList().AnkProcess, process.id) === null) { + const processStore = await indexedDB.getObject<Process>(db, indexedDB.getStoreList().AnkProcess, process.id); + if (!processStore) { + console.error('Add process.id : '+process.id); await indexedDB.writeObject(db, indexedDB.getStoreList().AnkProcess, process, null); } } catch (error) { From c239cfec623c0f6ddd8c533d62b6cba1b2dd584c Mon Sep 17 00:00:00 2001 From: franck <franck.petretto@atos.net> Date: Thu, 4 Apr 2024 11:49:16 +0200 Subject: [PATCH 41/90] fix recover <=> creatid switch --- src/services.ts | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/services.ts b/src/services.ts index 7d11b65..685d41d 100644 --- a/src/services.ts +++ b/src/services.ts @@ -63,7 +63,7 @@ class Services { await services.injectHtml('CREATE_ID'); services.attachSubmitListener("form4nk", (event) => services.createId(event)); services.attachClickListener("displayrecover", services.displayRecover); - services.displayProcess(); + await services.displayProcess(); } public async createId(event: Event): Promise<void> { @@ -102,12 +102,12 @@ class Services { public async displayRecover(): Promise<void> { const services = await Services.getInstance(); - services.injectHtml('RECOVER'); + await services.injectHtml('RECOVER'); services.attachSubmitListener("form4nk", services.recover); services.attachClickListener("displaycreateid", services.displayCreateId); services.attachClickListener("displayrevoke", services.displayRevoke); services.attachClickListener("submitButtonRevoke", services.revoke); - services.displayProcess(); + await services.displayProcess(); } public async recover(event: Event) { @@ -133,10 +133,11 @@ class Services { } public async displayRevokeImage(): Promise<void> { - Services.instance.injectHtml('REVOKE_IMAGE'); - Services.instance.attachClickListener("displayupdateanid", Services.instance.displayUpdateAnId); + const services = await Services.getInstance(); + await services.injectHtml('REVOKE_IMAGE'); + services.attachClickListener("displayupdateanid", services.displayUpdateAnId); - let imageBytes = await Services.instance.getRecoverImage('assets/4nk_revoke.jpg'); + let imageBytes = await services.getRecoverImage('assets/4nk_revoke.jpg'); if (imageBytes != null) { let blob = new Blob([imageBytes], {type: 'image/png'}); var elem = document.getElementById("revoke") as HTMLAnchorElement; @@ -162,9 +163,10 @@ class Services { } public async displayRevoke(): Promise<void> { - Services.instance.injectHtml('REVOKE'); - Services.instance.attachClickListener("displayrecover", Services.instance.displayRecover); - Services.instance.attachSubmitListener("form4nk", Services.instance.revoke); + const services = await Services.getInstance(); + services.injectHtml('REVOKE'); + services.attachClickListener("displayrecover", Services.instance.displayRecover); + services.attachSubmitListener("form4nk", Services.instance.revoke); } public async revoke(event: Event): Promise<void> { @@ -175,12 +177,14 @@ class Services { } public async displayUpdateAnId() { - console.log("JS displayUpdateAnId process : "+Services.instance.current_process); + const services = await Services.getInstance(); + + console.log("JS displayUpdateAnId process : "+services.current_process); let body = ""; let style = ""; let script = ""; try { - const processObject = await Services.instance.getProcessByName(Services.instance.current_process!); + const processObject = await services.getProcessByName(Services.instance.current_process!); if (processObject) { body = processObject.html; style = processObject.style; @@ -190,8 +194,8 @@ class Services { console.error("Failed to retrieve process with Error:", error); } - Services.instance.injectUpdateAnIdHtml(body, style, script); - Services.instance.attachSubmitListener("form4nk", Services.instance.updateAnId); + services.injectUpdateAnIdHtml(body, style, script); + services.attachSubmitListener("form4nk", services.updateAnId); } public injectUpdateAnIdHtml(bodyToInject: string, styleToInject: string, scriptToInject: string) { @@ -237,7 +241,7 @@ class Services { const selectProcess = document.getElementById("selectProcess"); if (selectProcess) { processList.forEach((process) => { - let child = new Option(process.id.toString(), process.id.toString()); + let child = new Option(process.name, process.name); if (!selectProcess.contains(child)) { selectProcess.appendChild(child); } @@ -285,11 +289,11 @@ class Services { } public async getProcessByName(name: string): Promise<Process | null> { - console.error('getProcessByName name: '+name); + console.log('getProcessByName name: '+name); const indexedDB = await IndexedDB.getInstance(); const db = indexedDB.getDb(); const process = await indexedDB.getFirstMatchWithIndex<Process>(db, indexedDB.getStoreList().AnkProcess, 'by_name', name); - console.error('getProcessByName process: '+process); + console.log('getProcessByName process: '+process); return process; } From c6ebf973396eeb1032f98f045940238c14aa9875 Mon Sep 17 00:00:00 2001 From: Yousra Assouhaji <yousra.assouhaji@atos.net> Date: Thu, 4 Apr 2024 14:05:20 +0000 Subject: [PATCH 42/90] Replace api.rs --- crates/sp_client/src/api.rs | 56 ++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 4c44949..266d4f5 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -20,7 +20,7 @@ use sp_backend::spclient::{derive_keys_from_seed, OutputList, SpClient}; use crate::user::{User, UserKeys, CONNECTED_USERS}; -use crate::process::{ItemMember, Process, Role}; +use crate::process::Process; type ApiResult<T: FromWasmAbi> = Result<T, ApiError>; @@ -167,16 +167,23 @@ pub struct get_process_return(Vec<Process>); #[wasm_bindgen] pub fn get_processes() -> ApiResult<get_process_return> { - let member1 = ItemMember::new(Role::Manager, String::from("")); - let member2 = ItemMember::new(Role::Manager, String::from("")); - let member3 = ItemMember::new(Role::Manager, String::from("")); + let number_managers: u8 = 5; + + let birthday_signet = 50000; + let mut members: Vec<String> = Vec::with_capacity((number_managers) as usize); - //instances of process + for _ in 0..number_managers{ + //add sp_client + let sp_wallet = generate_sp_wallet(None, birthday_signet, true)?; + let sp_address = sp_wallet.sp_client.get_receiving_address(); + members.push(sp_address); + } + //instances of process let process1 = Process { id: 1, name: String::from("CREATE_ID"), version: String::from("1.0"), - members: vec![member1.clone(), member2.clone()], + members: members.clone(), html: crate::process::HTML_CREATE_ID.to_owned(), style: crate::process::CSS.to_owned(), script: "".to_owned(), @@ -185,7 +192,7 @@ pub fn get_processes() -> ApiResult<get_process_return> { id: 2, name: String::from("UPDATE_ID"), version: String::from("1.0"), - members: vec![member1.clone(), member2.clone()], + members: members.clone(), html: crate::process::HTML_UPDATE_ID.to_owned(), style: crate::process::CSS.to_owned(), script: "".to_owned(), @@ -194,7 +201,7 @@ pub fn get_processes() -> ApiResult<get_process_return> { id: 3, name: String::from("RECOVER"), version: String::from("1.0"), - members: vec![member1.clone(), member2.clone()], + members: members.clone(), html: crate::process::HTML_RECOVER.to_owned(), style: crate::process::CSS.to_owned(), script: "".to_owned(), @@ -203,7 +210,7 @@ pub fn get_processes() -> ApiResult<get_process_return> { id: 4, name: String::from("REVOKE_IMAGE"), version: String::from("1.0"), - members: vec![member1.clone(), member2.clone()], + members: members.clone(), html: crate::process::HTML_REVOKE_IMAGE.to_owned(), style: crate::process::CSS.to_owned(), script: "".to_owned(), @@ -212,7 +219,7 @@ pub fn get_processes() -> ApiResult<get_process_return> { id: 5, name: String::from("REVOKE"), version: String::from("1.0"), - members: vec![member1.clone(), member2.clone()], + members: members.clone(), html: crate::process::HTML_REVOKE.to_owned(), style: crate::process::CSS.to_owned(), script: "".to_owned(), @@ -226,8 +233,37 @@ pub fn get_processes() -> ApiResult<get_process_return> { data_process.push(process4); data_process.push(process5); Ok(get_process_return(data_process)) + } +//for testing +/*#[wasm_bindgen] +pub fn get_process() -> ApiResult<get_process_return>{ + + let number_managers: u8 = 5; + let number_users:u8 = 10; + let birthday_signet = 50000; + let mut members: Vec<ItemMember> = Vec::with_capacity((number_managers + number_users) as usize); + + for _ in 0..number_managers{ + //add sp_client + let sp_wallet = generate_sp_wallet(None, birthday_signet, true)?; + let sp_address: SilentPaymentAddress = sp_wallet.sp_client.get_receiving_address().try_into()?; + members.push(ItemMember::new(Role::Manager,sp_address, String::from(""))); + } + for _ in 0..number_users{ + let sp_wallet = generate_sp_wallet(None, birthday_signet, true)?; + let sp_address: SilentPaymentAddress = sp_wallet.sp_client.get_receiving_address().try_into()?; + members.push(ItemMember::new(Role::User, sp_address, String::from(""))); + } + + let process = Process::new(members); + let mut data_process: Vec<Process> = Vec::new(); + data_process.push(process); + Ok(get_process_return(data_process)) + +}*/ + #[derive(Debug, Tsify, Serialize, Deserialize)] #[tsify(from_wasm_abi)] #[allow(non_camel_case_types)] From abf9bbf0cd89b79db9fd299f7502f4fc4089a037 Mon Sep 17 00:00:00 2001 From: Yousra Assouhaji <yousra.assouhaji@atos.net> Date: Thu, 4 Apr 2024 14:05:41 +0000 Subject: [PATCH 43/90] Replace process.rs --- crates/sp_client/src/process.rs | 45 +++++++++------------------------ 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/crates/sp_client/src/process.rs b/crates/sp_client/src/process.rs index 3338cf6..9302962 100644 --- a/crates/sp_client/src/process.rs +++ b/crates/sp_client/src/process.rs @@ -1,7 +1,11 @@ -use serde::{Deserialize, Serialize}; -use serde_json::{json, Value}; -use tsify::Tsify; +use std::fmt::DebugStruct; + use wasm_bindgen::prelude::*; +use serde::{Deserialize, Serialize}; +use tsify::Tsify; +use serde_json::{json, Value}; +use sp_backend::silentpayments::sending::SilentPaymentAddress; + pub const HTML_CREATE_ID: &str = " <div class='card'> @@ -318,41 +322,16 @@ pub const CSS: &str = " } "; -// process member (gestionnaire for now) -#[derive(Debug, Default, Serialize, Deserialize, Clone)] -pub enum Role { - Manager, - #[default] - User, -} - -#[derive(Debug, Serialize, Deserialize, Default, Tsify, Clone)] -#[tsify(into_wasm_abi)] -pub struct ItemMember { - pub role: Role, //gestionnaire - pub sp_address: String, - //pre_id - //shard - //priv_key_mainnet_spend - //priv_key_mainnet_scan - //priv_key_signet_scan -} - -impl ItemMember { - pub fn new(role: Role, sp_address: String) -> Self { - ItemMember { role, sp_address } - } -} - #[derive(Debug, Serialize, Deserialize, Default, Tsify)] #[tsify(into_wasm_abi, from_wasm_abi)] pub struct Process { pub id: u32, pub name: String, pub version: String, - pub members: Vec<ItemMember>, - pub html: String, + pub members: Vec<String>, + pub html:String, pub style: String, pub script: String, - //item_name : String, -} + // Add conditions : process, member, peer, artefact + +} \ No newline at end of file From 47c356a22f304307c70cf3cb5ed19f12cef8fd3e Mon Sep 17 00:00:00 2001 From: franck <franck.petretto@atos.net> Date: Fri, 5 Apr 2024 09:08:29 +0200 Subject: [PATCH 44/90] Fix updatanid display --- crates/sp_client/src/api.rs | 25 +++-- crates/sp_client/src/process.rs | 165 ++++++++++++++++++++++++++++++-- src/services.ts | 4 +- 3 files changed, 172 insertions(+), 22 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 266d4f5..13c09b3 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -168,22 +168,22 @@ pub struct get_process_return(Vec<Process>); #[wasm_bindgen] pub fn get_processes() -> ApiResult<get_process_return> { let number_managers: u8 = 5; - + let birthday_signet = 50000; let mut members: Vec<String> = Vec::with_capacity((number_managers) as usize); - for _ in 0..number_managers{ + for _ in 0..number_managers { //add sp_client let sp_wallet = generate_sp_wallet(None, birthday_signet, true)?; let sp_address = sp_wallet.sp_client.get_receiving_address(); members.push(sp_address); } - //instances of process + //instances of process let process1 = Process { id: 1, name: String::from("CREATE_ID"), version: String::from("1.0"), - members: members.clone(), + members: members.clone(), html: crate::process::HTML_CREATE_ID.to_owned(), style: crate::process::CSS.to_owned(), script: "".to_owned(), @@ -192,16 +192,16 @@ pub fn get_processes() -> ApiResult<get_process_return> { id: 2, name: String::from("UPDATE_ID"), version: String::from("1.0"), - members: members.clone(), + members: members.clone(), html: crate::process::HTML_UPDATE_ID.to_owned(), - style: crate::process::CSS.to_owned(), - script: "".to_owned(), + style: crate::process::CSSUPDATE.to_owned(), + script: crate::process::JSUPDATE.to_owned(), }; let process3 = Process { id: 3, name: String::from("RECOVER"), version: String::from("1.0"), - members: members.clone(), + members: members.clone(), html: crate::process::HTML_RECOVER.to_owned(), style: crate::process::CSS.to_owned(), script: "".to_owned(), @@ -210,7 +210,7 @@ pub fn get_processes() -> ApiResult<get_process_return> { id: 4, name: String::from("REVOKE_IMAGE"), version: String::from("1.0"), - members: members.clone(), + members: members.clone(), html: crate::process::HTML_REVOKE_IMAGE.to_owned(), style: crate::process::CSS.to_owned(), script: "".to_owned(), @@ -219,7 +219,7 @@ pub fn get_processes() -> ApiResult<get_process_return> { id: 5, name: String::from("REVOKE"), version: String::from("1.0"), - members: members.clone(), + members: members.clone(), html: crate::process::HTML_REVOKE.to_owned(), style: crate::process::CSS.to_owned(), script: "".to_owned(), @@ -233,13 +233,12 @@ pub fn get_processes() -> ApiResult<get_process_return> { data_process.push(process4); data_process.push(process5); Ok(get_process_return(data_process)) - } //for testing /*#[wasm_bindgen] pub fn get_process() -> ApiResult<get_process_return>{ - + let number_managers: u8 = 5; let number_users:u8 = 10; let birthday_signet = 50000; @@ -255,7 +254,7 @@ pub fn get_process() -> ApiResult<get_process_return>{ let sp_wallet = generate_sp_wallet(None, birthday_signet, true)?; let sp_address: SilentPaymentAddress = sp_wallet.sp_client.get_receiving_address().try_into()?; members.push(ItemMember::new(Role::User, sp_address, String::from(""))); - } + } let process = Process::new(members); let mut data_process: Vec<Process> = Vec::new(); diff --git a/crates/sp_client/src/process.rs b/crates/sp_client/src/process.rs index 9302962..56f95d6 100644 --- a/crates/sp_client/src/process.rs +++ b/crates/sp_client/src/process.rs @@ -1,11 +1,10 @@ use std::fmt::DebugStruct; -use wasm_bindgen::prelude::*; use serde::{Deserialize, Serialize}; -use tsify::Tsify; use serde_json::{json, Value}; use sp_backend::silentpayments::sending::SilentPaymentAddress; - +use tsify::Tsify; +use wasm_bindgen::prelude::*; pub const HTML_CREATE_ID: &str = " <div class='card'> @@ -320,7 +319,158 @@ pub const CSS: &str = " .passwordalert { color: #FF0000; } -"; + "; + +pub const CSSUPDATE: &str = " + <style> + body { + margin: 0; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + min-height: 100vh; + background-color: #f4f4f4; + font-family: 'Arial', sans-serif; + } + + .container { + max-width: 400px; + width: 100%; + padding: 20px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + background-color: #ffffff; + border-radius: 8px; + text-align: left; + overflow: hidden; + } + + form { + display: grid; + grid-template-columns: repeat(1fr, 2fr); + gap: 10px; + max-width: 400px; + margin: auto; + } + + .bg-primary { + background-color: #1a61ed; + } + + .bg-primary:hover { + background-color: #457be8; + } + + .bg-secondary { + background-color: #2b81ed; + } + + .bg-secondary:hover { + background-color: #5f9bff; + } + + label { + text-align: left; + padding-right: 10px; + line-height: 2; + } + + input { + width: 100%; + padding: 8px; + box-sizing: border-box; + } + + button { + grid-column: span 2; + display: inline-block; + color: #fff; + border: none; + padding: 12px 17px; + border-radius: 4px; + cursor: pointer; + } + + .div-text-area { + grid-column: span 2; + } + + textarea { + width: 100%; + padding: 8px; + box-sizing: border-box; + } + + .side-by-side { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + margin-bottom: 5px; + } + .circle-btn { + width: 25px; + height: 25px; + border-radius: 50%; + border: none; + color: white; + padding: 0px; + text-align: center; + } + + #fileInput { + width: 100%; + padding: 8px; + padding-left: 0px; + box-sizing: border-box; + } + </style> + "; + +pub const JSUPDATE: &str = " + var addSpAddressBtn = document.getElementById('add-sp-address-btn'); + var removeSpAddressBtn = document.querySelectorAll('.minus-sp-address-btn'); + + addSpAddressBtn.addEventListener('click', function (event) { + addDynamicField(this); + }); + + function addDynamicField(element) { + var addSpAddressBlock = document.getElementById('sp-address-block'); + var spAddress = addSpAddressBlock.querySelector('#sp-address').value; + addSpAddressBlock.querySelector('#sp-address').value = ''; + spAddress = spAddress.trim(); + if (spAddress != '') { + var sideBySideDiv = document.createElement('div'); + sideBySideDiv.className = 'side-by-side'; + + var inputElement = document.createElement('input'); + inputElement.type = 'text'; + inputElement.name = 'spAddresses[]'; + inputElement.setAttribute('form', 'no-form'); + inputElement.value = spAddress; + inputElement.disabled = true; + + var buttonElement = document.createElement('button'); + buttonElement.type = 'button'; + buttonElement.className = + 'circle-btn bg-secondary minus-sp-address-btn'; + buttonElement.innerHTML = '-'; + + buttonElement.addEventListener('click', function (event) { + removeDynamicField(this.parentElement); + }); + + sideBySideDiv.appendChild(inputElement); + sideBySideDiv.appendChild(buttonElement); + + addSpAddressBlock.appendChild(sideBySideDiv); + } + function removeDynamicField(element) { + element.remove(); + } + } + "; #[derive(Debug, Serialize, Deserialize, Default, Tsify)] #[tsify(into_wasm_abi, from_wasm_abi)] @@ -329,9 +479,8 @@ pub struct Process { pub name: String, pub version: String, pub members: Vec<String>, - pub html:String, + pub html: String, pub style: String, pub script: String, - // Add conditions : process, member, peer, artefact - -} \ No newline at end of file + // Add conditions : process, member, peer, artefact +} diff --git a/src/services.ts b/src/services.ts index 685d41d..e5fd51b 100644 --- a/src/services.ts +++ b/src/services.ts @@ -184,11 +184,13 @@ class Services { let style = ""; let script = ""; try { - const processObject = await services.getProcessByName(Services.instance.current_process!); + const processObject = await services.getProcessByName("UPDATE_ID"); if (processObject) { body = processObject.html; style = processObject.style; script = processObject.script; + console.log("JS displayUpdateAnId body : "+body); + } } catch (error) { console.error("Failed to retrieve process with Error:", error); From 6128f826b14da8224a029a49698519d00498109b Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Thu, 4 Apr 2024 15:09:14 +0200 Subject: [PATCH 45/90] Add websockets.ts --- src/services.ts | 38 +++++++++++++++++++++ src/websockets.ts | 85 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 src/websockets.ts diff --git a/src/services.ts b/src/services.ts index e5fd51b..cc8ab92 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,5 +1,6 @@ import { createUserReturn, User, Process } from '../dist/pkg/sdk_client'; import IndexedDB from './database' +import { WebSocketClient } from './websockets'; class Services { private static instance: Services; @@ -162,6 +163,18 @@ class Services { return imageBytes; } + public async parseBitcoinMessage(raw: Blob): Promise<string | null> { + try { + const buffer = await raw.arrayBuffer(); + const uint8Array = new Uint8Array(buffer); + const msg: string = this.sdkClient.parse_bitcoin_network_msg(uint8Array); + return msg; + } catch (error) { + console.error("Error processing the blob:", error); + return null; + } + } + public async displayRevoke(): Promise<void> { const services = await Services.getInstance(); services.injectHtml('REVOKE'); @@ -200,6 +213,11 @@ class Services { services.attachSubmitListener("form4nk", services.updateAnId); } + public async parse4nkMessage(raw: string): Promise<string | null> { + const msg: string = this.sdkClient.parse_4nk_msg(raw); + return msg; + } + public injectUpdateAnIdHtml(bodyToInject: string, styleToInject: string, scriptToInject: string) { console.log("JS html : "+bodyToInject); const body = document.getElementsByTagName('body')[0]; @@ -263,6 +281,16 @@ class Services { } } + public async checkTransaction(tx: string): Promise<string | null> { + const services = await Services.getInstance(); + try { + return services.sdkClient.check_network_transaction(tx); + } catch (error) { + console.error(error); + return null; + } + } + public async getAllProcessForUser(pre_id: string): Promise<Process[]> { const services = await Services.getInstance(); let user: User; @@ -401,6 +429,16 @@ class Services { } return success; } + + public obtainTokenWithFaucet(wsclient: WebSocketClient, spaddress: string): string | null { + try { + wsclient.sendMessage(spaddress); + } catch (error) { + console.error("Failed to obtain tokens with relay ", wsclient.getUrl()); + return null; + } + return null; + } } export default Services; diff --git a/src/websockets.ts b/src/websockets.ts new file mode 100644 index 0000000..72d8c80 --- /dev/null +++ b/src/websockets.ts @@ -0,0 +1,85 @@ +import Services from "./services"; +// import * as mempool from "./mempool"; + +class WebSocketClient { + private ws: WebSocket; + private messageQueue: string[] = []; + + constructor(url: string, private services: Services) { + this.ws = new WebSocket(url); + + this.ws.addEventListener('open', (event) => { + console.log('WebSocket connection established'); + // Once the connection is open, send all messages in the queue + while (this.messageQueue.length > 0) { + const message = this.messageQueue.shift(); + if (message) { + this.ws.send(message); + } + } + }); + + // Listen for messages + this.ws.addEventListener('message', (event) => { + const msgData = event.data; + console.log(msgData); + + (async () => { + if (msgData instanceof Blob) { + // bitcoin network msg is just bytes + let res = await services.parseBitcoinMessage(msgData); + if (res) { + let ours = await services.checkTransaction(res); + if (ours) { + console.log("Found our utxo in "+res); + } else { + console.log("No utxo found in tx "+res); + } + } else { + console.error("Faile to parse a bitcoin network msg"); + } + } else if (typeof(msgData) === 'string') { + // json strings are 4nk message + console.log("Received text message: "+msgData); + let res = await services.parse4nkMessage(msgData); + if (res) { + console.debug(res); + } + } else { + console.error("Received an unknown message"); + } + })(); + }); + + // Listen for possible errors + this.ws.addEventListener('error', (event) => { + console.error('WebSocket error:', event); + }); + + // Listen for when the connection is closed + this.ws.addEventListener('close', (event) => { + console.log('WebSocket is closed now.'); + }); + } + + // Method to send messages + public sendMessage(message: string): void { + if (this.ws.readyState === WebSocket.OPEN) { + this.ws.send(message); + } else { + console.error('WebSocket is not open. ReadyState:', this.ws.readyState); + this.messageQueue.push(message); + } + } + + public getUrl(): string { + return this.ws.url; + } + + // Method to close the WebSocket connection + public close(): void { + this.ws.close(); + } +} + +export { WebSocketClient }; From 741b303348de12bd1f659f4c5f6c3f213698e1fd Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Mon, 8 Apr 2024 15:56:01 +0200 Subject: [PATCH 46/90] connect on startup --- src/index.ts | 4 +++- src/services.ts | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 4327e11..bdb0bbb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,11 @@ import Services from './services'; -import IndexedDB from './database' +import { WebSocketClient } from './websockets'; +const wsurl = "ws://127.0.0.1:8090"; document.addEventListener('DOMContentLoaded', async () => { try { const services = await Services.getInstance(); + await services.addWebsocketConnection(wsurl); if ((await services.isNewUser())) { await services.displayCreateId(); diff --git a/src/services.ts b/src/services.ts index cc8ab92..920e915 100644 --- a/src/services.ts +++ b/src/services.ts @@ -6,6 +6,7 @@ class Services { private static instance: Services; private sdkClient: any; private current_process: string | null = null; + private websocketConnection: WebSocketClient[] = []; // Private constructor to prevent direct instantiation from outside private constructor() {} @@ -44,6 +45,14 @@ class Services { // } + public async addWebsocketConnection(url: string): Promise<void> { + const services = await Services.getInstance(); + const newClient = new WebSocketClient(url, services); + if (!services.websocketConnection.includes(newClient)) { + services.websocketConnection.push(newClient); + } + } + public async isNewUser(): Promise<boolean> { let isNew = false; try { From 750bf69aa5be6bdbd4edfcf594a82abe107a5cbc Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Fri, 5 Apr 2024 19:12:44 +0200 Subject: [PATCH 47/90] Refactoring --- crates/sp_client/src/api.rs | 185 ++++++++++++++++--------- crates/sp_client/src/lib.rs | 17 +++ crates/sp_client/src/network.rs | 94 +++++++++++++ crates/sp_client/src/silentpayments.rs | 76 ++++++++++ crates/sp_client/src/user.rs | 115 ++++++++++----- src/index.ts | 2 +- src/services.ts | 60 ++++++-- 7 files changed, 439 insertions(+), 110 deletions(-) create mode 100644 crates/sp_client/src/network.rs create mode 100644 crates/sp_client/src/silentpayments.rs diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 13c09b3..3afa033 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -1,12 +1,17 @@ +use std::any::Any; use std::collections::HashMap; -use std::sync::{Mutex, OnceLock}; +use std::str::FromStr; +use std::sync::{Mutex, OnceLock, PoisonError}; use rand::Rng; use anyhow::Error as AnyhowError; use serde_json::Error as SerdeJsonError; use shamir::SecretData; -use sp_backend::bitcoin::secp256k1::SecretKey; +use sp_backend::bitcoin::consensus::deserialize; +use sp_backend::bitcoin::hex::{FromHex, HexToBytesError}; +use sp_backend::bitcoin::secp256k1::{PublicKey, SecretKey}; +use sp_backend::bitcoin::{Transaction, Txid}; use sp_backend::silentpayments::Error as SpError; use serde::{Deserialize, Serialize}; @@ -15,10 +20,12 @@ use tsify::Tsify; use wasm_bindgen::convert::FromWasmAbi; use wasm_bindgen::prelude::*; -use sp_backend::spclient::SpendKey; use sp_backend::spclient::{derive_keys_from_seed, OutputList, SpClient}; +use sp_backend::spclient::{SpWallet, SpendKey}; -use crate::user::{User, UserKeys, CONNECTED_USERS}; +use crate::network::{BitcoinNetworkMsg, BitcoinTopic}; +use crate::silentpayments::check_transaction; +use crate::user::{lock_connected_users, User, UserWallets, CONNECTED_USERS}; use crate::process::Process; @@ -55,6 +62,30 @@ impl From<SerdeJsonError> for ApiError { } } +impl From<HexToBytesError> for ApiError { + fn from(value: HexToBytesError) -> Self { + ApiError { + message: value.to_string(), + } + } +} + +impl From<sp_backend::bitcoin::secp256k1::Error> for ApiError { + fn from(value: sp_backend::bitcoin::secp256k1::Error) -> Self { + ApiError { + message: value.to_string(), + } + } +} + +impl From<sp_backend::bitcoin::consensus::encode::Error> for ApiError { + fn from(value: sp_backend::bitcoin::consensus::encode::Error) -> Self { + ApiError { + message: value.to_string(), + } + } +} + impl Into<JsValue> for ApiError { fn into(self) -> JsValue { JsValue::from_str(&self.message) @@ -62,7 +93,7 @@ impl Into<JsValue> for ApiError { } #[derive(Tsify, Serialize, Deserialize)] -#[tsify(into_wasm_abi)] +#[tsify(into_wasm_abi, from_wasm_abi)] #[allow(non_camel_case_types)] pub struct createUserReturn { pub user: User, @@ -75,16 +106,11 @@ pub fn setup() { } // Should be transfered to annother module -pub struct GenerateSPWallet { - pub sp_client: SpClient, - pub sp_outputs: OutputList, -} - pub fn generate_sp_wallet( label: Option<String>, birthday: u32, is_testnet: bool, -) -> ApiResult<GenerateSPWallet> { +) -> ApiResult<SpWallet> { let mut seed = [0u8; 64]; rand::thread_rng().fill(&mut seed); let (scan_sk, spend_sk) = derive_keys_from_seed(&seed, is_testnet)?; @@ -101,20 +127,7 @@ pub fn generate_sp_wallet( our_address.to_string() ); - //let sp_client_json = serde_json::to_string(&sp_client)?; - - // Generate an empty outputs - let sp_outputs = OutputList::new( - our_address.get_scan_key(), - our_address.get_spend_key(), - birthday, - ); - //let sp_outputs_json = serde_json::to_string(&sp_outputs)?; - - let res = GenerateSPWallet { - sp_client, - sp_outputs, - }; + let res = SpWallet::new(sp_client, None)?; Ok(res) } @@ -133,28 +146,28 @@ pub fn create_user( birthday_signet: u32, process: String, ) -> ApiResult<createUserReturn> { - let mut output_list: Vec<OutputList> = Vec::new(); //recover let sp_wallet_recover = generate_sp_wallet(label.clone(), birthday_signet, true)?; - output_list.push(sp_wallet_recover.sp_outputs); //revoke let sp_wallet_revoke = generate_sp_wallet(label.clone(), birthday_signet, true)?; - output_list.push(sp_wallet_revoke.sp_outputs); //mainet let sp_wallet_main = generate_sp_wallet(label, birthday_main, false)?; - output_list.push(sp_wallet_main.sp_outputs); - let user_keys = UserKeys::new( - Some(sp_wallet_main.sp_client), - sp_wallet_recover.sp_client, - Some(sp_wallet_revoke.sp_client), + let user_wallets = UserWallets::new( + Some(sp_wallet_main), + sp_wallet_recover, + Some(sp_wallet_revoke), ); - let user = User::new(user_keys, password, process)?; + let user = User::new(user_wallets.clone(), password, process)?; + + let outputs = user_wallets.get_all_outputs(); + + lock_connected_users()?.insert(user.pre_id.clone(), user_wallets); let generate_user = createUserReturn { user, - output_list_vec: output_list, + output_list_vec: outputs, }; Ok(generate_user) @@ -175,7 +188,7 @@ pub fn get_processes() -> ApiResult<get_process_return> { for _ in 0..number_managers { //add sp_client let sp_wallet = generate_sp_wallet(None, birthday_signet, true)?; - let sp_address = sp_wallet.sp_client.get_receiving_address(); + let sp_address = sp_wallet.get_client().get_receiving_address(); members.push(sp_address); } //instances of process @@ -235,34 +248,6 @@ pub fn get_processes() -> ApiResult<get_process_return> { Ok(get_process_return(data_process)) } -//for testing -/*#[wasm_bindgen] -pub fn get_process() -> ApiResult<get_process_return>{ - - let number_managers: u8 = 5; - let number_users:u8 = 10; - let birthday_signet = 50000; - let mut members: Vec<ItemMember> = Vec::with_capacity((number_managers + number_users) as usize); - - for _ in 0..number_managers{ - //add sp_client - let sp_wallet = generate_sp_wallet(None, birthday_signet, true)?; - let sp_address: SilentPaymentAddress = sp_wallet.sp_client.get_receiving_address().try_into()?; - members.push(ItemMember::new(Role::Manager,sp_address, String::from(""))); - } - for _ in 0..number_users{ - let sp_wallet = generate_sp_wallet(None, birthday_signet, true)?; - let sp_address: SilentPaymentAddress = sp_wallet.sp_client.get_receiving_address().try_into()?; - members.push(ItemMember::new(Role::User, sp_address, String::from(""))); - } - - let process = Process::new(members); - let mut data_process: Vec<Process> = Vec::new(); - data_process.push(process); - Ok(get_process_return(data_process)) - -}*/ - #[derive(Debug, Tsify, Serialize, Deserialize)] #[tsify(from_wasm_abi)] #[allow(non_camel_case_types)] @@ -285,14 +270,84 @@ impl shamir_shares { } } +#[derive(Debug, Tsify, Serialize, Deserialize)] +#[tsify(from_wasm_abi)] +#[allow(non_camel_case_types)] +pub struct outputs_list(Vec<OutputList>); + +impl outputs_list { + fn as_inner(&self) -> &[OutputList] { + &self.0 + } +} + #[wasm_bindgen] pub fn login_user( user_password: String, pre_id: String, recover: recover_data, shares: shamir_shares, + outputs: outputs_list, ) -> ApiResult<()> { - let res = User::login(pre_id, user_password, recover.as_inner(), shares.as_inner())?; + let res = User::login( + pre_id, + user_password, + recover.as_inner(), + shares.as_inner(), + outputs.as_inner(), + )?; Ok(res) } + +#[wasm_bindgen] +pub fn check_transaction_for_silent_payments( + tx_hex: String, + tweak_data_hex: String, +) -> ApiResult<()> { + let tx = deserialize::<Transaction>(&Vec::from_hex(&tx_hex)?)?; + let tweak_data = PublicKey::from_str(&tweak_data_hex)?; + + check_transaction(tx, tweak_data); + + Ok(()) +} + +#[wasm_bindgen] +pub fn parse_bitcoin_network_msg(msg: Vec<u8>) -> ApiResult<()> { + let parsed_msg = BitcoinNetworkMsg::new(&msg)?; + + match parsed_msg.topic { + BitcoinTopic::RawTx => { + let tx = deserialize::<Transaction>(parsed_msg.data)?; + let tweak_data = PublicKey::from_slice(parsed_msg.addon)?; + check_transaction(tx, tweak_data); + } + BitcoinTopic::RawBlock => (), + } + + Ok(()) +} + +#[wasm_bindgen] +pub fn parse_4nk_msg(raw: String) -> Option<String>{ + if let Ok(msg) = AnkNetworkMsg::new(&raw) { + match msg.topic { + AnkTopic::Faucet => { + match Txid::from_str(msg.content) { + Ok(txid) => { + // return the txid for verification + Some(txid.to_string()) + }, + Err(e) => { + log::error!("Invalid txid with a \"faucet\" message: {}", e.to_string()); + None + } + } + } + } + } else { + log::debug!("Can't parse message as a valid 4nk message: {}", raw); + None + } +} diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index 9898215..73db7f5 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -1,7 +1,24 @@ #![allow(warnings)] +use anyhow::Error; +use std::fmt::Debug; +use std::sync::{Mutex, MutexGuard}; + mod Prd_list; pub mod api; mod crypto; +mod network; mod peers; mod process; +mod silentpayments; mod user; + +pub(crate) trait MutexExt<T> { + fn lock_anyhow(&self) -> Result<MutexGuard<T>, Error>; +} + +impl<T: Debug> MutexExt<T> for Mutex<T> { + fn lock_anyhow(&self) -> Result<MutexGuard<T>, Error> { + self.lock() + .map_err(|e| Error::msg(format!("Failed to lock: {}", e))) + } +} diff --git a/crates/sp_client/src/network.rs b/crates/sp_client/src/network.rs new file mode 100644 index 0000000..fdb16c6 --- /dev/null +++ b/crates/sp_client/src/network.rs @@ -0,0 +1,94 @@ +use anyhow::{Error, Result}; +use serde::{Deserialize, Serialize}; +use tsify::Tsify; + +const RAWTXTOPIC: &'static str = "rawtx"; +const RAWBLOCKTOPIC: &'static str = "rawblock"; + +#[derive(Debug, Serialize, Deserialize)] +pub enum BitcoinTopic { + RawTx, + RawBlock, +} + +impl BitcoinTopic { + pub fn as_str(&self) -> &str { + match self { + Self::RawTx => RAWTXTOPIC, + Self::RawBlock => RAWBLOCKTOPIC, + } + } +} + +#[derive(Debug, Serialize, Deserialize, Tsify)] +#[tsify(from_wasm_abi, into_wasm_abi)] +pub struct BitcoinNetworkMsg<'a> { + pub topic: BitcoinTopic, + pub data: &'a [u8], + pub sequence: &'a [u8], + pub addon: &'a [u8], +} + +impl<'a> BitcoinNetworkMsg<'a> { + pub fn new(raw_msg: &'a [u8]) -> Result<Self> { + let topic: BitcoinTopic; + let data: &[u8]; + let sequence: &[u8]; + let addon: &[u8]; + let addon_len: usize; + let raw_msg_len = raw_msg.len(); + + if raw_msg.starts_with(RAWTXTOPIC.as_bytes()) { + topic = BitcoinTopic::RawTx; + addon_len = 33; + } else if raw_msg.starts_with(RAWBLOCKTOPIC.as_bytes()) { + topic = BitcoinTopic::RawBlock; + addon_len = 0; + } else { + return Err(Error::msg("Unknown prefix")); + } + + data = &raw_msg[topic.as_str().as_bytes().len()..raw_msg_len - 4 - addon_len]; + sequence = &raw_msg[raw_msg_len - 4 - addon_len..]; + addon = &raw_msg[raw_msg_len - addon_len..]; + + Ok(Self { + topic, + data, + sequence, + addon, + }) + } +} + +#[derive(Debug)] +pub enum AnkTopic { + Faucet, +} + +impl AnkTopic { + pub fn as_str(&self) -> &str { + match self { + Self::Faucet => "faucet", + } + } +} + +#[derive(Debug)] +pub struct AnkNetworkMsg<'a> { + pub topic: AnkTopic, + pub content: &'a str, +} + +impl<'a> AnkNetworkMsg<'a> { + pub fn new(raw: &'a str) -> Result<Self> { + if raw.starts_with(AnkTopic::Faucet.as_str()) { + Ok(Self { + topic: AnkTopic::Faucet, + content: &raw[AnkTopic::Faucet.as_str().len()..], + }) + } else { + Err(Error::msg("Unknown 4nk message")) + } + } +} diff --git a/crates/sp_client/src/silentpayments.rs b/crates/sp_client/src/silentpayments.rs new file mode 100644 index 0000000..5ab45d4 --- /dev/null +++ b/crates/sp_client/src/silentpayments.rs @@ -0,0 +1,76 @@ +use std::collections::HashMap; + +use anyhow::Result; + +use sp_backend::silentpayments::utils::receiving::calculate_shared_secret; +use sp_backend::{ + bitcoin::{ + secp256k1::{PublicKey, Scalar, XOnlyPublicKey}, + Transaction, + }, + silentpayments::receiving::Label, +}; + +use crate::user::{lock_connected_users, CONNECTED_USERS}; + +type FoundOutputs = HashMap<Option<Label>, HashMap<XOnlyPublicKey, Scalar>>; + +pub fn check_transaction(tx: Transaction, tweak_data: PublicKey) -> Result<FoundOutputs> { + let connected_users = lock_connected_users()?; + + let pubkeys_to_check: HashMap<XOnlyPublicKey, u32> = (0u32..) + .zip(tx.output) + .filter_map(|(i, o)| { + if o.script_pubkey.is_p2tr() { + let xonly = XOnlyPublicKey::from_slice(&o.script_pubkey.as_bytes()[2..]) + .expect("Transaction is invalid"); + Some((xonly, i)) + } else { + None + } + }) + .collect(); + + // Check the transaction for all connected users + for (pre_id, keys) in connected_users.clone() { + let recover = keys.recover; + let shared_secret = + calculate_shared_secret(tweak_data, recover.get_client().get_scan_key())?; + let res = recover + .get_client() + .sp_receiver + .scan_transaction(&shared_secret, pubkeys_to_check.keys().cloned().collect())?; + + if res.len() > 0 { + return Ok(res); + } + + if let Some(main) = keys.main { + let shared_secret = + calculate_shared_secret(tweak_data, main.get_client().get_scan_key())?; + let res = main + .get_client() + .sp_receiver + .scan_transaction(&shared_secret, pubkeys_to_check.keys().cloned().collect())?; + + if res.len() > 0 { + return Ok(res); + } + } + + if let Some(revoke) = keys.revoke { + let shared_secret = + calculate_shared_secret(tweak_data, revoke.get_client().get_scan_key())?; + let res = revoke + .get_client() + .sp_receiver + .scan_transaction(&shared_secret, pubkeys_to_check.keys().cloned().collect())?; + + if res.len() > 0 { + return Ok(res); + } + } + } + + Ok(HashMap::new()) +} diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index 70835e2..202ed8d 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -12,6 +12,7 @@ use sp_backend::bitcoin::hashes::HashEngine; use sp_backend::bitcoin::hex::{DisplayHex, FromHex}; use sp_backend::bitcoin::secp256k1::SecretKey; use sp_backend::bitcoin::secp256k1::ThirtyTwoByteHash; +use sp_backend::spclient::SpClient; use tsify::Tsify; use wasm_bindgen::prelude::*; @@ -20,34 +21,42 @@ use std::collections::HashMap; use std::fs::File; use std::io::{Cursor, Read, Write}; use std::str::FromStr; -use std::sync::{Mutex, OnceLock}; +use std::sync::{Mutex, MutexGuard, OnceLock}; use sp_backend::bitcoin::secp256k1::constants::SECRET_KEY_SIZE; use sp_backend::silentpayments::bitcoin_hashes::sha256; use sp_backend::silentpayments::sending::SilentPaymentAddress; use sp_backend::spclient::SpendKey; -use sp_backend::spclient::{OutputList, SpClient}; +use sp_backend::spclient::{OutputList, SpWallet}; use crate::crypto::{Aes256Decryption, Aes256Encryption, HalfKey, Purpose}; use crate::peers::Peer; use crate::user; +use crate::MutexExt; type PreId = String; const MANAGERS_NUMBER: u8 = 10; const QUORUM_SHARD: f32 = 0.8; -pub static CONNECTED_USERS: OnceLock<Mutex<HashMap<PreId, UserKeys>>> = OnceLock::new(); +type UsersMap = HashMap<PreId, UserWallets>; +pub static CONNECTED_USERS: OnceLock<Mutex<UsersMap>> = OnceLock::new(); -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct UserKeys { - pub main: Option<SpClient>, - pub recover: SpClient, - pub revoke: Option<SpClient>, +pub fn lock_connected_users() -> Result<MutexGuard<'static, UsersMap>> { + CONNECTED_USERS + .get_or_init(|| Mutex::new(HashMap::new())) + .lock_anyhow() } -impl UserKeys { - pub fn new(main: Option<SpClient>, recover: SpClient, revoke: Option<SpClient>) -> Self { +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct UserWallets { + pub main: Option<SpWallet>, + pub recover: SpWallet, + pub revoke: Option<SpWallet>, +} + +impl UserWallets { + pub fn new(main: Option<SpWallet>, recover: SpWallet, revoke: Option<SpWallet>) -> Self { Self { main, recover, @@ -55,9 +64,22 @@ impl UserKeys { } } - pub fn try_get_revoke(&self) -> Option<&SpClient> { + pub fn try_get_revoke(&self) -> Option<&SpWallet> { self.revoke.as_ref() } + + pub(crate) fn get_all_outputs(&self) -> Vec<OutputList> { + let mut res = Vec::<OutputList>::new(); + if let Some(main) = &self.main { + res.push(main.get_outputs().clone()); + } + if let Some(revoke) = &self.revoke { + res.push(revoke.get_outputs().clone()); + } + res.push(self.recover.get_outputs().clone()); + + res + } } #[derive(Debug, Serialize, Deserialize, Clone, Tsify)] @@ -69,25 +91,30 @@ pub struct User { recover_data: Vec<u8>, revoke_data: Option<Vec<u8>>, shares: Vec<Vec<u8>>, + outputs: Vec<OutputList>, } impl User { - pub fn new(user_keys: UserKeys, user_password: String, process: String) -> Result<Self> { + pub fn new(user_wallets: UserWallets, user_password: String, process: String) -> Result<Self> { let mut rng = thread_rng(); // image revoke // We just take the 2 revoke keys let mut revoke_data = Vec::with_capacity(64); - if let Some(revoke) = user_keys.try_get_revoke() { - revoke_data.extend_from_slice(revoke.get_scan_key().as_ref()); - revoke_data.extend_from_slice(revoke.try_get_secret_spend_key()?.as_ref()); + if let Some(revoke) = user_wallets.try_get_revoke() { + revoke_data.extend_from_slice(revoke.get_client().get_scan_key().as_ref()); + revoke_data.extend_from_slice(revoke.get_client().try_get_secret_spend_key()?.as_ref()); } else { return Err(Error::msg("No revoke wallet available")); } // Take the 2 recover keys // split recover spend key - let recover_spend_key = user_keys.recover.try_get_secret_spend_key()?.clone(); + let recover_spend_key = user_wallets + .recover + .get_client() + .try_get_secret_spend_key()? + .clone(); let (part1_key, part2_key) = recover_spend_key.as_ref().split_at(SECRET_KEY_SIZE / 2); let mut recover_data = Vec::<u8>::with_capacity(180); // 32 * 3 + (12+16)*3 @@ -161,7 +188,12 @@ impl User { let scan_key_encryption = Aes256Encryption::import_key( Purpose::ThirtyTwoBytes, - user_keys.recover.get_scan_key().secret_bytes().to_vec(), + user_wallets + .recover + .get_client() + .get_scan_key() + .secret_bytes() + .to_vec(), hash3.to_byte_array(), Aes256Gcm::generate_nonce(&mut rng).into(), )?; @@ -171,12 +203,6 @@ impl User { recover_data.extend_from_slice(&cipher_scan_key); - //Create PRDList - //@todo - //Send messages PRDList - //@todo - //Receive List Items (PCD) - Ok(User { pre_id: pre_id.to_string(), processes: vec![process], @@ -184,6 +210,7 @@ impl User { recover_data, revoke_data: Some(revoke_data), shares, + outputs: user_wallets.get_all_outputs(), }) } @@ -192,6 +219,7 @@ impl User { user_password: String, recover_data: &[u8], shares: &[Vec<u8>], + outputs: &[OutputList], ) -> Result<()> { let mut retrieved_spend_key = [0u8; 32]; let mut retrieved_scan_key = [0u8; 32]; @@ -258,6 +286,13 @@ impl User { true, )?; + let recover_outputs = outputs + .iter() + .find(|o| o.check_fingerprint(&recover_client)) + .cloned(); + + let recover_wallet = SpWallet::new(recover_client, recover_outputs)?; + // Adding user to CONNECTED_USERS if let Some(current_users) = CONNECTED_USERS.get() { let mut lock = current_users.to_owned().lock().unwrap(); @@ -267,11 +302,11 @@ impl User { pre_id ))); } else { - lock.insert(pre_id.clone(), UserKeys::new(None, recover_client, None)); + lock.insert(pre_id.clone(), UserWallets::new(None, recover_wallet, None)); } } else { let mut user_map = HashMap::new(); - user_map.insert(pre_id, UserKeys::new(None, recover_client, None)); + user_map.insert(pre_id, UserWallets::new(None, recover_wallet, None)); let new_value = Mutex::new(user_map); if let Err(error) = CONNECTED_USERS.set(new_value) { return Err(Error::msg( @@ -396,7 +431,7 @@ mod tests { const USER_PASSWORD: &str = "correct horse battery staple"; const PROCESS: &str = "example"; - fn helper_create_user_keys() -> UserKeys { + fn helper_create_user_wallets() -> UserWallets { let label = "default".to_owned(); let sp_main = SpClient::new( label.clone(), @@ -422,16 +457,20 @@ mod tests { true, ) .unwrap(); - let user_keys = UserKeys::new(Some(sp_main), sp_recover, Some(sp_revoke)); + let user_wallets = UserWallets::new( + Some(SpWallet::new(sp_main, None).unwrap()), + SpWallet::new(sp_recover, None).unwrap(), + Some(SpWallet::new(sp_revoke, None).unwrap()), + ); - user_keys + user_wallets } // Test 1: Create User #[test] fn test_successful_creation() { - let user_keys = helper_create_user_keys(); - let result = User::new(user_keys, USER_PASSWORD.to_owned(), PROCESS.to_owned()); + let user_wallets = helper_create_user_wallets(); + let result = User::new(user_wallets, USER_PASSWORD.to_owned(), PROCESS.to_owned()); assert!(result.is_ok()); let user = result.unwrap(); @@ -439,14 +478,20 @@ mod tests { #[test] fn test_login() { - let user_keys = helper_create_user_keys(); - let user = User::new(user_keys, USER_PASSWORD.to_owned(), PROCESS.to_owned()).unwrap(); + let user_wallets = helper_create_user_wallets(); + let user = User::new( + user_wallets.clone(), + USER_PASSWORD.to_owned(), + PROCESS.to_owned(), + ) + .unwrap(); let res = User::login( user.pre_id.clone(), USER_PASSWORD.to_owned(), &user.recover_data, &user.shares, + &user_wallets.get_all_outputs(), ); assert!(res.is_ok()); @@ -458,7 +503,11 @@ mod tests { assert!( format!( "{}", - recover.try_get_secret_spend_key().unwrap().display_secret() + recover + .get_client() + .try_get_secret_spend_key() + .unwrap() + .display_secret() ) == RECOVER_SPEND ) } diff --git a/src/index.ts b/src/index.ts index bdb0bbb..f0304ea 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ import Services from './services'; import { WebSocketClient } from './websockets'; -const wsurl = "ws://127.0.0.1:8090"; +const wsurl = "ws://192.168.1.44:8090"; document.addEventListener('DOMContentLoaded', async () => { try { const services = await Services.getInstance(); diff --git a/src/services.ts b/src/services.ts index 920e915..e331a5b 100644 --- a/src/services.ts +++ b/src/services.ts @@ -93,21 +93,42 @@ class Services { // To comment if test // if (!Services.instance.isPasswordValid(password)) return; - let label = null; - let birthday_signet = 50000; - let birthday_main = 500000; - const user: createUserReturn = this.sdkClient.create_user(password, label, birthday_main, birthday_signet, this.current_process); + const label = null; + const birthday_signet = 50000; + const birthday_main = 500000; + + const services = await Services.getInstance(); + let createUserReturn: createUserReturn = services.sdkClient.create_user(password, label, birthday_main, birthday_signet, this.current_process); + + let user = createUserReturn.user; + const outputs_list = createUserReturn.output_list_vec; + + const shares = user.shares; + const revokeData = user.revoke_data; + + user.shares = []; + user.revoke_data = null; try { const indexedDb = await IndexedDB.getInstance(); const db = indexedDb.getDb(); - await indexedDb.writeObject(db, indexedDb.getStoreList().AnkUser, user.user, null); - await indexedDb.writeObject(db, indexedDb.getStoreList().SpOutputs, user.output_list_vec, null); + await indexedDb.writeObject(db, indexedDb.getStoreList().AnkUser, user, null); + await indexedDb.writeObject(db, indexedDb.getStoreList().SpOutputs, outputs_list, null); } catch (error) { console.error("Failed to write user object :", error); } - await Services.instance.displayRevokeImage(); + let sp_address = ""; + try { + sp_address = services.sdkClient.get_receiving_address(user.pre_id); + console.info('Using sp_address:', sp_address); + } catch (error) { + console.error(error); + } + + await services.obtainTokenWithFaucet(sp_address); + + await services.displayRevokeImage(new Uint8Array(revokeData)); } public async displayRecover(): Promise<void> { @@ -136,7 +157,7 @@ class Services { const process = processElement.value; console.log("JS password: " + password + " process: " + process); // To comment if test - if (!Services.instance.isPasswordValid(password)) return; + // if (!Services.instance.isPasswordValid(password)) return; // TODO alert("Recover submit to do ..."); @@ -439,11 +460,28 @@ class Services { return success; } - public obtainTokenWithFaucet(wsclient: WebSocketClient, spaddress: string): string | null { + private async pickWebsocketConnectionRandom(): Promise<WebSocketClient | null> { + const services = await Services.getInstance(); + const websockets = services.websocketConnection; + if (websockets.length === 0) { + console.error("No websocket connection available at the moment"); + return null; + } else { + const random = Math.floor(Math.random() * websockets.length); + return websockets[random]; + } + } + + public async obtainTokenWithFaucet(spaddress: string): Promise<string | null> { + const services = await Services.getInstance(); + const connection = await services.pickWebsocketConnectionRandom(); + if (!connection) { + return null; + } try { - wsclient.sendMessage(spaddress); + connection.sendMessage('faucet'+spaddress); } catch (error) { - console.error("Failed to obtain tokens with relay ", wsclient.getUrl()); + console.error("Failed to obtain tokens with relay ", connection.getUrl()); return null; } return null; From 9657be4959b9a5649db9dd1f8ea32c2c03e8fd9f Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Sun, 7 Apr 2024 23:18:16 +0200 Subject: [PATCH 48/90] add data to image --- crates/sp_client/Cargo.toml | 1 + crates/sp_client/src/api.rs | 12 +++++++++++ crates/sp_client/src/images.rs | 38 ++++++++++++++++++++++++++++++++++ crates/sp_client/src/lib.rs | 1 + src/database.ts | 22 ++++++++++---------- src/services.ts | 38 ++++++++++++++++++++++++++-------- 6 files changed, 92 insertions(+), 20 deletions(-) create mode 100644 crates/sp_client/src/images.rs diff --git a/crates/sp_client/Cargo.toml b/crates/sp_client/Cargo.toml index 3a82e7a..25f7965 100644 --- a/crates/sp_client/Cargo.toml +++ b/crates/sp_client/Cargo.toml @@ -21,6 +21,7 @@ tsify = { git = "https://github.com/Sosthene00/tsify", branch = "next" } aes-gcm = "0.10.3" aes = "0.8.3" shamir = { git = "https://github.com/Sosthene00/shamir", branch = "master" } +img-parts = "0.3.0" [dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 3afa033..130c40f 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -23,6 +23,7 @@ use wasm_bindgen::prelude::*; use sp_backend::spclient::{derive_keys_from_seed, OutputList, SpClient}; use sp_backend::spclient::{SpWallet, SpendKey}; +use crate::images; use crate::network::{BitcoinNetworkMsg, BitcoinTopic}; use crate::silentpayments::check_transaction; use crate::user::{lock_connected_users, User, UserWallets, CONNECTED_USERS}; @@ -173,6 +174,17 @@ pub fn create_user( Ok(generate_user) } +#[wasm_bindgen] +pub fn add_data_to_image(image: Vec<u8>, data: Vec<u8>, is_revoke: bool) -> ApiResult<Vec<u8>> { + let mut new_image: Vec<u8>; + if is_revoke { + new_image = images::BackUpImage::new_revoke(image, &data)?.to_inner(); + } else { + new_image = images::BackUpImage::new_recover(image, &data)?.to_inner(); + } + Ok(new_image) +} + #[derive(Tsify, Serialize, Deserialize)] #[tsify(into_wasm_abi)] #[allow(non_camel_case_types)] diff --git a/crates/sp_client/src/images.rs b/crates/sp_client/src/images.rs new file mode 100644 index 0000000..f0e11ee --- /dev/null +++ b/crates/sp_client/src/images.rs @@ -0,0 +1,38 @@ +use anyhow::{Error, Result}; +use img_parts::{jpeg::Jpeg, Bytes, ImageEXIF}; +use serde::{Deserialize, Serialize}; +use sp_backend::bitcoin::secp256k1::SecretKey; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BackUpImage(Vec<u8>); + +impl BackUpImage { + pub fn new_recover(image: Vec<u8>, data: &[u8]) -> Result<Self> { + // TODO: sanity check on data + let img = write_exif(image, data)?; + Ok(Self(img)) + } + + pub fn new_revoke(image: Vec<u8>, data: &[u8]) -> Result<Self> { + // TODO: sanity check on data + let img = write_exif(image, data)?; + Ok(Self(img)) + } + + pub fn to_inner(&self) -> Vec<u8> { + self.0.clone() + } + + pub fn as_inner(&self) -> &[u8] { + &self.0 + } +} + +fn write_exif(image: Vec<u8>, data: &[u8]) -> Result<Vec<u8>> { + let mut jpeg = Jpeg::from_bytes(Bytes::from(image))?; + let data_bytes = Bytes::from(data.to_owned()); + jpeg.set_exif(Some(data_bytes)); + let output_image_bytes = jpeg.encoder().bytes(); + let output_image = output_image_bytes.to_vec(); + Ok(output_image) +} diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index 73db7f5..95968cb 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -6,6 +6,7 @@ use std::sync::{Mutex, MutexGuard}; mod Prd_list; pub mod api; mod crypto; +mod images; mod network; mod peers; mod process; diff --git a/src/database.ts b/src/database.ts index 7413e88..d8d8041 100644 --- a/src/database.ts +++ b/src/database.ts @@ -9,17 +9,17 @@ class Database { // options: {}, // indices: [] // }, - SpOutputs: { - name: "sp_outputs", - options: {'autoIncrement': true}, - indices: [{ - name: 'by_wallet_fingerprint', - keyPath: 'wallet_fingerprint', - options: { - 'unique': false - } - }] - }, + // SpOutputs: { + // name: "sp_outputs", + // options: {'autoIncrement': true}, + // indices: [{ + // name: 'by_wallet_fingerprint', + // keyPath: 'wallet_fingerprint', + // options: { + // 'unique': false + // } + // }] + // }, AnkUser: { name: "user", options: {'keyPath': 'pre_id'}, diff --git a/src/services.ts b/src/services.ts index e331a5b..7160fbc 100644 --- a/src/services.ts +++ b/src/services.ts @@ -89,7 +89,7 @@ class Services { const password = passwordElement.value; this.current_process = processElement.value; - console.log("JS password: " + password + " process: " + this.current_process); + // console.log("JS password: " + password + " process: " + this.current_process); // To comment if test // if (!Services.instance.isPasswordValid(password)) return; @@ -101,10 +101,14 @@ class Services { let createUserReturn: createUserReturn = services.sdkClient.create_user(password, label, birthday_main, birthday_signet, this.current_process); let user = createUserReturn.user; - const outputs_list = createUserReturn.output_list_vec; const shares = user.shares; + // send the shares on the network const revokeData = user.revoke_data; + if (!revokeData) { + console.error('Failed to get revoke data from wasm'); + return; + } user.shares = []; user.revoke_data = null; @@ -113,7 +117,6 @@ class Services { const indexedDb = await IndexedDB.getInstance(); const db = indexedDb.getDb(); await indexedDb.writeObject(db, indexedDb.getStoreList().AnkUser, user, null); - await indexedDb.writeObject(db, indexedDb.getStoreList().SpOutputs, outputs_list, null); } catch (error) { console.error("Failed to write user object :", error); } @@ -163,17 +166,16 @@ class Services { alert("Recover submit to do ..."); } - public async displayRevokeImage(): Promise<void> { + public async displayRevokeImage(revokeData: Uint8Array): Promise<void> { const services = await Services.getInstance(); await services.injectHtml('REVOKE_IMAGE'); services.attachClickListener("displayupdateanid", services.displayUpdateAnId); let imageBytes = await services.getRecoverImage('assets/4nk_revoke.jpg'); if (imageBytes != null) { - let blob = new Blob([imageBytes], {type: 'image/png'}); var elem = document.getElementById("revoke") as HTMLAnchorElement; if (elem != null) { - elem.href = URL.createObjectURL(blob); + let imageWithData = services.sdkClient.add_data_to_image(imageBytes, revokeData, true); } } } @@ -299,6 +301,16 @@ class Services { } } + public async addProcess(process: Process): Promise<void> { + try { + const indexedDB = await IndexedDB.getInstance(); + const db = indexedDB.getDb(); + await indexedDB.writeObject(db, indexedDB.getStoreList().AnkProcess, process, null); + } catch (error) { + console.log('addProcess failed: ',error); + } + } + public async getAllProcess(): Promise<Process[]> { try { const indexedDB = await IndexedDB.getInstance(); @@ -369,7 +381,7 @@ class Services { try { const processStore = await indexedDB.getObject<Process>(db, indexedDB.getStoreList().AnkProcess, process.id); if (!processStore) { - console.error('Add process.id : '+process.id); + console.error('Adding process.id : '+process.id); await indexedDB.writeObject(db, indexedDB.getStoreList().AnkProcess, process, null); } } catch (error) { @@ -391,7 +403,6 @@ class Services { } public async injectHtml(processName: string) { - // console.log("JS html : "+html); const container = document.getElementById('containerId'); if (!container) { @@ -401,8 +412,17 @@ class Services { const services = await Services.getInstance(); - await services.loadProcesses(); + // do we have all processes in db? + const knownProcesses = await services.getAllProcess(); + const processesFromNetwork: Process[] = services.sdkClient.get_processes(); + const processToAdd = processesFromNetwork.filter(processFromNetwork => !knownProcesses.some(knownProcess => knownProcess.id === processFromNetwork.id)); + + processToAdd.forEach(async p => { + await services.addProcess(p); + }) + + // get the process we need const process = await services.getProcessByName(processName); if (process) { container.innerHTML = process.html; From 9f0bde4710e416f8a0679f2f53a136021b2fbd82 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Mon, 8 Apr 2024 18:33:08 +0200 Subject: [PATCH 49/90] refactor get_receiving_address --- crates/sp_client/src/api.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 130c40f..ea6bd9e 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -24,7 +24,7 @@ use sp_backend::spclient::{derive_keys_from_seed, OutputList, SpClient}; use sp_backend::spclient::{SpWallet, SpendKey}; use crate::images; -use crate::network::{BitcoinNetworkMsg, BitcoinTopic}; +use crate::network::{BitcoinNetworkMsg, BitcoinTopic, AnkNetworkMsg, AnkTopic}; use crate::silentpayments::check_transaction; use crate::user::{lock_connected_users, User, UserWallets, CONNECTED_USERS}; @@ -134,9 +134,14 @@ pub fn generate_sp_wallet( } #[wasm_bindgen] -pub fn get_receiving_address(sp_client: String) -> String { - let sp_client: SpClient = serde_json::from_str(&sp_client).unwrap(); - sp_client.get_receiving_address() +pub fn get_receiving_address(pre_id: String) -> ApiResult<String> { + if let Some(my_wallets) = lock_connected_users()?.get(&pre_id) { + Ok(my_wallets.recover.get_client().get_receiving_address()) + } else { + Err(ApiError { + message: "Unknown user pre_id".to_owned(), + }) + } } #[wasm_bindgen] From 7d22c033bbb6e7ace03a2bd05a97bd0535c81147 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 17 Apr 2024 08:31:55 +0200 Subject: [PATCH 50/90] mv crypto and network to common --- crates/sp_client/Cargo.toml | 3 +- crates/sp_client/src/crypto.rs | 447 -------------------------------- crates/sp_client/src/lib.rs | 2 - crates/sp_client/src/network.rs | 94 ------- crates/sp_client/src/user.rs | 9 +- 5 files changed, 4 insertions(+), 551 deletions(-) delete mode 100644 crates/sp_client/src/crypto.rs delete mode 100644 crates/sp_client/src/network.rs diff --git a/crates/sp_client/Cargo.toml b/crates/sp_client/Cargo.toml index 25f7965..1a725bc 100644 --- a/crates/sp_client/Cargo.toml +++ b/crates/sp_client/Cargo.toml @@ -18,8 +18,7 @@ wasm-logger = "0.2.0" rand = "0.8.5" log = "0.4.6" tsify = { git = "https://github.com/Sosthene00/tsify", branch = "next" } -aes-gcm = "0.10.3" -aes = "0.8.3" +sdk_common = { git = "https://git.4nkweb.com/4nk/sdk_common.git", branch = "demo" } shamir = { git = "https://github.com/Sosthene00/shamir", branch = "master" } img-parts = "0.3.0" diff --git a/crates/sp_client/src/crypto.rs b/crates/sp_client/src/crypto.rs deleted file mode 100644 index 59ab295..0000000 --- a/crates/sp_client/src/crypto.rs +++ /dev/null @@ -1,447 +0,0 @@ -use std::collections::HashMap; - -use anyhow::{Error, Result}; -use sp_backend::{ - bitcoin::{ - consensus::serde::hex, - hex::DisplayHex, - key::constants::SECRET_KEY_SIZE, - secp256k1::{ecdh::SharedSecret, SecretKey}, - Txid, - }, - silentpayments::sending::SilentPaymentAddress, -}; -use wasm_bindgen::JsValue; - -use serde::{Deserialize, Serialize}; -use serde_json::{json, Value}; - -use aes::cipher::generic_array::GenericArray; -use aes::{ - cipher::consts::{U32, U8}, - Aes256, -}; -use aes_gcm::{ - aead::{Aead, AeadInPlace, KeyInit, Nonce}, - AeadCore, Aes256Gcm, AesGcm, Key, TagSize, -}; -use rand::{thread_rng, RngCore}; - -const HALFKEYSIZE: usize = SECRET_KEY_SIZE / 2; - -const THIRTYTWO: usize = 32; - -pub struct HalfKey([u8; HALFKEYSIZE]); - -impl TryFrom<Vec<u8>> for HalfKey { - type Error = anyhow::Error; - fn try_from(value: Vec<u8>) -> std::prelude::v1::Result<Self, Error> { - if value.len() == HALFKEYSIZE { - let mut buf = [0u8; HALFKEYSIZE]; - buf.copy_from_slice(&value); - Ok(HalfKey(buf)) - } else { - Err(Error::msg("Invalid length for HalfKey")) - } - } -} - -impl HalfKey { - pub fn as_slice(&self) -> &[u8] { - &self.0 - } - - pub fn to_inner(&self) -> Vec<u8> { - self.0.to_vec() - } -} - -pub enum Purpose { - Login, - ThirtyTwoBytes, -} - -pub type CipherText = Vec<u8>; - -pub type EncryptedKey = Vec<u8>; - -pub struct Aes256Decryption { - pub purpose: Purpose, - cipher_text: CipherText, - aes_key: [u8; 32], - nonce: [u8; 12], -} - -impl Aes256Decryption { - pub fn new( - purpose: Purpose, - cipher_text: CipherText, - encrypted_aes_key: Vec<u8>, // If shared_secret is none this is actually the aes_key - shared_secret: Option<SharedSecret>, // We don't need that for certain purpose, like Login - ) -> Result<Self> { - let mut aes_key = [0u8; 32]; - if let Some(shared_secret) = shared_secret { - if encrypted_aes_key.len() <= 12 { - return Err(Error::msg("encrypted_aes_key is shorter than nonce length")); - } // Actually we could probably test that if the remnant is not a multiple of 32, something's wrong - // take the first 12 bytes form encrypted_aes_key as nonce - let (decrypt_key_nonce, encrypted_key) = encrypted_aes_key.split_at(12); - // decrypt key with shared_secret obtained from transaction - let decrypt_key_cipher = Aes256Gcm::new_from_slice(shared_secret.as_ref()) - .map_err(|e| Error::msg(format!("{}", e)))?; - let aes_key_plain = decrypt_key_cipher - .decrypt(decrypt_key_nonce.into(), encrypted_key) - .map_err(|e| Error::msg(format!("{}", e)))?; - if aes_key_plain.len() != 32 { - return Err(Error::msg("Invalid length for decrypted key")); - } - aes_key.copy_from_slice(&aes_key_plain); - } else { - if encrypted_aes_key.len() != 32 { - return Err(Error::msg("Invalid length for decrypted key")); - } - aes_key.copy_from_slice(&encrypted_aes_key); - } - if cipher_text.len() <= 12 { - return Err(Error::msg("cipher_text is shorter than nonce length")); - } - let (message_nonce, message_cipher) = cipher_text.split_at(12); - let mut nonce = [0u8; 12]; - nonce.copy_from_slice(message_nonce); - Ok(Self { - purpose, - cipher_text: message_cipher.to_vec(), - aes_key, - nonce, - }) - } - - pub fn decrypt_with_key(&self) -> Result<Vec<u8>> { - match self.purpose { - Purpose::Login => { - let half_key = self.decrypt_login()?; - Ok(half_key.to_inner()) - } - Purpose::ThirtyTwoBytes => { - let thirty_two_buf = self.decrypt_thirty_two()?; - Ok(thirty_two_buf.to_vec()) - } - } - } - - fn decrypt_login(&self) -> Result<HalfKey> { - let cipher = Aes256Gcm::new(&self.aes_key.into()); - let plain = cipher - .decrypt(&self.nonce.into(), &*self.cipher_text) - .map_err(|e| Error::msg(format!("{}", e)))?; - if plain.len() != SECRET_KEY_SIZE / 2 { - return Err(Error::msg("Plain text of invalid lenght for a login")); - } - let mut key_half = [0u8; SECRET_KEY_SIZE / 2]; - key_half.copy_from_slice(&plain); - Ok(HalfKey(key_half)) - } - - fn decrypt_thirty_two(&self) -> Result<[u8; THIRTYTWO]> { - let cipher = Aes256Gcm::new(&self.aes_key.into()); - let plain = cipher - .decrypt(&self.nonce.into(), &*self.cipher_text) - .map_err(|e| Error::msg(format!("{}", e)))?; - if plain.len() != THIRTYTWO { - return Err(Error::msg("Plain text of invalid length, should be 32")); - } - let mut thirty_two = [0u8; THIRTYTWO]; - thirty_two.copy_from_slice(&plain); - Ok(thirty_two) - } -} - -pub struct Aes256Encryption { - pub purpose: Purpose, - plaintext: Vec<u8>, - aes_key: [u8; 32], - nonce: [u8; 12], - shared_secrets: HashMap<Txid, HashMap<SilentPaymentAddress, SharedSecret>>, -} - -impl Aes256Encryption { - pub fn new(purpose: Purpose, plaintext: Vec<u8>) -> Result<Self> { - let mut rng = thread_rng(); - let aes_key: [u8; 32] = Aes256Gcm::generate_key(&mut rng).into(); - let nonce: [u8; 12] = Aes256Gcm::generate_nonce(&mut rng).into(); - Self::import_key(purpose, plaintext, aes_key, nonce) - } - - pub fn set_shared_secret( - &mut self, - shared_secrets: HashMap<Txid, HashMap<SilentPaymentAddress, SharedSecret>>, - ) { - self.shared_secrets = shared_secrets; - } - - pub fn encrypt_keys_with_shared_secrets( - &self, - ) -> Result<HashMap<SilentPaymentAddress, EncryptedKey>> { - let mut res = HashMap::new(); - let mut rng = thread_rng(); - - for (_, sp_address2shared_secret) in self.shared_secrets.iter() { - for (sp_address, shared_secret) in sp_address2shared_secret { - let cipher = Aes256Gcm::new_from_slice(shared_secret.as_ref()) - .map_err(|e| Error::msg(format!("{}", e)))?; - let nonce = Aes256Gcm::generate_nonce(&mut rng); - let encrypted_key = cipher - .encrypt(&nonce, self.aes_key.as_slice()) - .map_err(|e| Error::msg(format!("{}", e)))?; - - let mut ciphertext = Vec::<u8>::with_capacity(nonce.len() + encrypted_key.len()); - ciphertext.extend(nonce); - ciphertext.extend(encrypted_key); - - res.insert(sp_address.to_owned(), ciphertext); - } - } - Ok(res) - } - - pub fn import_key( - purpose: Purpose, - plaintext: Vec<u8>, - aes_key: [u8; 32], - nonce: [u8; 12], - ) -> Result<Self> { - if plaintext.len() == 0 { - return Err(Error::msg("Can't create encryption for an empty message")); - } - Ok(Self { - purpose, - plaintext, - aes_key, - nonce, - shared_secrets: HashMap::new(), - }) - } - - pub fn encrypt_with_aes_key(&self) -> Result<CipherText> { - match self.purpose { - Purpose::Login => self.encrypt_login(), - Purpose::ThirtyTwoBytes => self.encrypt_thirty_two(), - } - } - - fn encrypt_login(&self) -> Result<CipherText> { - let half_key: HalfKey = self.plaintext.clone().try_into()?; - let cipher = Aes256Gcm::new(&self.aes_key.into()); - let cipher_text = cipher - .encrypt(&self.nonce.into(), half_key.as_slice()) - .map_err(|e| Error::msg(format!("{}", e)))?; - let mut res = Vec::with_capacity(self.nonce.len() + cipher_text.len()); - res.extend_from_slice(&self.nonce); - res.extend_from_slice(&cipher_text); - Ok(res) - } - - fn encrypt_thirty_two(&self) -> Result<CipherText> { - if self.plaintext.len() != 32 { - return Err(Error::msg("Invalid length, should be 32")); - } - let mut thirty_two = [0u8; 32]; - thirty_two.copy_from_slice(&self.plaintext); - let cipher = Aes256Gcm::new(&self.aes_key.into()); - let cipher_text = cipher - .encrypt(&self.nonce.into(), thirty_two.as_slice()) - .map_err(|e| Error::msg(format!("{}", e)))?; - let mut res = Vec::with_capacity(self.nonce.len() + cipher_text.len()); - log::info!("{}", cipher_text.len()); - res.extend_from_slice(&self.nonce); - res.extend_from_slice(&cipher_text); - Ok(res) - } -} - -#[cfg(test)] -mod tests { - use std::str::FromStr; - - use super::*; - - const ALICE_SP_ADDRESS: &str = "tsp1qqw3lqr6xravz9nf8ntazgwwl0fqv47kfjdxsnxs6eutavqfwyv5q6qk97mmyf6dtkdyzqlu2zv6h9j2ggclk7vn705q5u2phglpq7yw3dg5rwpdz"; - const BOB_SP_ADDRESS: &str = "tsp1qq2hlsgrj0gz8kcfkf9flqw5llz0u2vr04telqndku9mcqm6dl4fhvq60t8r78srrf56w9yr7w9e9dusc2wjqc30up6fjwnh9mw3e3veqegdmtf08"; - const TRANSACTION: &str = "4e6d03dec558e1b6624f813bf2da7cd8d8fb1c2296684c08cf38724dcfd8d10b"; - const ALICE_SHARED_SECRET: &str = - "ccf02d364c2641ca129a3fdf49de57b705896e233f7ba6d738991993ea7e2106"; - const BOB_SHARED_SECRET: &str = - "15ef3e377fb842e81de52dbaaea8ba30aeb051a81043ee19264afd27353da521"; - - #[test] - fn new_aes_empty_plaintext() { - let plaintext = Vec::new(); - let aes_enc = Aes256Encryption::new(Purpose::Login, plaintext); - - assert!(aes_enc.is_err()); - } - - #[test] - fn aes_encrypt_login_invalid_length() { - let plaintext = "example"; - let aes_enc_short = Aes256Encryption::new(Purpose::Login, plaintext.as_bytes().to_vec()); - - assert!(aes_enc_short.is_ok()); - - let cipher = aes_enc_short.unwrap().encrypt_with_aes_key(); - - assert!(cipher.is_err()); - - let plaintext = [1u8; 64]; - let aes_enc_long = Aes256Encryption::new(Purpose::Login, plaintext.to_vec()); - - assert!(aes_enc_long.is_ok()); - - let cipher = aes_enc_long.unwrap().encrypt_with_aes_key(); - - assert!(cipher.is_err()); - } - - #[test] - fn aes_encrypt_login() { - let plaintext = [1u8; HALFKEYSIZE]; - let aes_key = Aes256Gcm::generate_key(&mut thread_rng()); - let nonce = Aes256Gcm::generate_nonce(&mut thread_rng()); - let aes_enc = Aes256Encryption::import_key( - Purpose::Login, - plaintext.to_vec(), - aes_key.into(), - nonce.into(), - ); - - assert!(aes_enc.is_ok()); - - let cipher = aes_enc.unwrap().encrypt_with_aes_key(); - - assert!(cipher.is_ok()); - - let mut plain_key = [0u8; 32]; - plain_key.copy_from_slice(&aes_key.to_vec()); - - let aes_dec = - Aes256Decryption::new(Purpose::Login, cipher.unwrap(), plain_key.to_vec(), None); - - assert!(aes_dec.is_ok()); - } - - #[test] - fn aes_encrypt_key() { - let plaintext = [1u8; HALFKEYSIZE]; - let mut aes_enc = Aes256Encryption::new(Purpose::Login, plaintext.to_vec()).unwrap(); - - let mut shared_secrets: HashMap<Txid, _> = HashMap::new(); - let mut sp_address2shared_secrets: HashMap<SilentPaymentAddress, SharedSecret> = - HashMap::new(); - sp_address2shared_secrets.insert( - ALICE_SP_ADDRESS.try_into().unwrap(), - SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap(), - ); - shared_secrets.insert( - Txid::from_str(TRANSACTION).unwrap(), - sp_address2shared_secrets, - ); - - aes_enc.set_shared_secret(shared_secrets); - - let sp_address2encrypted_keys = aes_enc.encrypt_keys_with_shared_secrets(); - - assert!(sp_address2encrypted_keys.is_ok()); - - let encrypted_key = sp_address2encrypted_keys - .unwrap() - .get(&ALICE_SP_ADDRESS.try_into().unwrap()) - .cloned(); - - let ciphertext = aes_enc.encrypt_with_aes_key(); - - assert!(ciphertext.is_ok()); - - let aes_dec = Aes256Decryption::new( - Purpose::Login, - ciphertext.unwrap(), - encrypted_key.unwrap(), - Some(SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap()), - ); - - assert!(aes_dec.is_ok()); - - let retrieved_plain = aes_dec.unwrap().decrypt_with_key(); - - assert!(retrieved_plain.is_ok()); - - assert!(retrieved_plain.unwrap() == plaintext); - } - - #[test] - fn aes_encrypt_key_many() { - let plaintext = [1u8; THIRTYTWO]; - let mut aes_enc = - Aes256Encryption::new(Purpose::ThirtyTwoBytes, plaintext.to_vec()).unwrap(); - - let mut shared_secrets: HashMap<Txid, _> = HashMap::new(); - let mut sp_address2shared_secrets: HashMap<SilentPaymentAddress, SharedSecret> = - HashMap::new(); - sp_address2shared_secrets.insert( - ALICE_SP_ADDRESS.try_into().unwrap(), - SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap(), - ); - sp_address2shared_secrets.insert( - BOB_SP_ADDRESS.try_into().unwrap(), - SharedSecret::from_str(BOB_SHARED_SECRET).unwrap(), - ); - shared_secrets.insert( - Txid::from_str(TRANSACTION).unwrap(), - sp_address2shared_secrets, - ); - - aes_enc.set_shared_secret(shared_secrets); - - let mut sp_address2encrypted_keys = aes_enc.encrypt_keys_with_shared_secrets(); - - assert!(sp_address2encrypted_keys.is_ok()); - - // Alice - let encrypted_key = sp_address2encrypted_keys - .as_mut() - .unwrap() - .get(&ALICE_SP_ADDRESS.try_into().unwrap()) - .cloned(); - - let ciphertext = aes_enc.encrypt_with_aes_key(); - - let aes_dec = Aes256Decryption::new( - Purpose::ThirtyTwoBytes, - ciphertext.unwrap(), - encrypted_key.unwrap(), - Some(SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap()), - ); - - let retrieved_plain = aes_dec.unwrap().decrypt_with_key(); - - assert!(retrieved_plain.unwrap() == plaintext); - - // Bob - let encrypted_key = sp_address2encrypted_keys - .unwrap() - .get(&BOB_SP_ADDRESS.try_into().unwrap()) - .cloned(); - - let ciphertext = aes_enc.encrypt_with_aes_key(); - - let aes_dec = Aes256Decryption::new( - Purpose::ThirtyTwoBytes, - ciphertext.unwrap(), - encrypted_key.unwrap(), - Some(SharedSecret::from_str(BOB_SHARED_SECRET).unwrap()), - ); - - let retrieved_plain = aes_dec.unwrap().decrypt_with_key(); - - assert!(retrieved_plain.unwrap() == plaintext); - } -} diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index 95968cb..c0056a6 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -5,9 +5,7 @@ use std::sync::{Mutex, MutexGuard}; mod Prd_list; pub mod api; -mod crypto; mod images; -mod network; mod peers; mod process; mod silentpayments; diff --git a/crates/sp_client/src/network.rs b/crates/sp_client/src/network.rs deleted file mode 100644 index fdb16c6..0000000 --- a/crates/sp_client/src/network.rs +++ /dev/null @@ -1,94 +0,0 @@ -use anyhow::{Error, Result}; -use serde::{Deserialize, Serialize}; -use tsify::Tsify; - -const RAWTXTOPIC: &'static str = "rawtx"; -const RAWBLOCKTOPIC: &'static str = "rawblock"; - -#[derive(Debug, Serialize, Deserialize)] -pub enum BitcoinTopic { - RawTx, - RawBlock, -} - -impl BitcoinTopic { - pub fn as_str(&self) -> &str { - match self { - Self::RawTx => RAWTXTOPIC, - Self::RawBlock => RAWBLOCKTOPIC, - } - } -} - -#[derive(Debug, Serialize, Deserialize, Tsify)] -#[tsify(from_wasm_abi, into_wasm_abi)] -pub struct BitcoinNetworkMsg<'a> { - pub topic: BitcoinTopic, - pub data: &'a [u8], - pub sequence: &'a [u8], - pub addon: &'a [u8], -} - -impl<'a> BitcoinNetworkMsg<'a> { - pub fn new(raw_msg: &'a [u8]) -> Result<Self> { - let topic: BitcoinTopic; - let data: &[u8]; - let sequence: &[u8]; - let addon: &[u8]; - let addon_len: usize; - let raw_msg_len = raw_msg.len(); - - if raw_msg.starts_with(RAWTXTOPIC.as_bytes()) { - topic = BitcoinTopic::RawTx; - addon_len = 33; - } else if raw_msg.starts_with(RAWBLOCKTOPIC.as_bytes()) { - topic = BitcoinTopic::RawBlock; - addon_len = 0; - } else { - return Err(Error::msg("Unknown prefix")); - } - - data = &raw_msg[topic.as_str().as_bytes().len()..raw_msg_len - 4 - addon_len]; - sequence = &raw_msg[raw_msg_len - 4 - addon_len..]; - addon = &raw_msg[raw_msg_len - addon_len..]; - - Ok(Self { - topic, - data, - sequence, - addon, - }) - } -} - -#[derive(Debug)] -pub enum AnkTopic { - Faucet, -} - -impl AnkTopic { - pub fn as_str(&self) -> &str { - match self { - Self::Faucet => "faucet", - } - } -} - -#[derive(Debug)] -pub struct AnkNetworkMsg<'a> { - pub topic: AnkTopic, - pub content: &'a str, -} - -impl<'a> AnkNetworkMsg<'a> { - pub fn new(raw: &'a str) -> Result<Self> { - if raw.starts_with(AnkTopic::Faucet.as_str()) { - Ok(Self { - topic: AnkTopic::Faucet, - content: &raw[AnkTopic::Faucet.as_str().len()..], - }) - } else { - Err(Error::msg("Unknown 4nk message")) - } - } -} diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index 202ed8d..d1720c1 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -1,8 +1,3 @@ -use aes::cipher::generic_array::GenericArray; -use aes_gcm::aead::Aead; -use aes_gcm::AeadCore; -use aes_gcm::KeyInit; -use aes_gcm::{aead::Buffer, Aes256Gcm, Key}; use anyhow::{Error, Result}; use rand::{self, thread_rng, Rng, RngCore}; use serde::{Deserialize, Serialize}; @@ -29,10 +24,12 @@ use sp_backend::silentpayments::sending::SilentPaymentAddress; use sp_backend::spclient::SpendKey; use sp_backend::spclient::{OutputList, SpWallet}; -use crate::crypto::{Aes256Decryption, Aes256Encryption, HalfKey, Purpose}; use crate::peers::Peer; use crate::user; use crate::MutexExt; +use sdk_common::crypto::{ + AeadCore, Aes256Decryption, Aes256Encryption, Aes256Gcm, HalfKey, KeyInit, Purpose, +}; type PreId = String; From 0d42c289cb4cb9ef9a2a2750d1b0729b421e6096 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 17 Apr 2024 08:41:38 +0200 Subject: [PATCH 51/90] mv html to ts, update process acquisition --- crates/sp_client/src/api.rs | 66 +++------ crates/sp_client/src/process.rs | 177 +++++++---------------- src/services.ts | 240 ++++++++++++++++++++++++++------ 3 files changed, 263 insertions(+), 220 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index ea6bd9e..2788999 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -197,60 +197,38 @@ pub struct get_process_return(Vec<Process>); #[wasm_bindgen] pub fn get_processes() -> ApiResult<get_process_return> { - let number_managers: u8 = 5; - - let birthday_signet = 50000; - let mut members: Vec<String> = Vec::with_capacity((number_managers) as usize); - - for _ in 0..number_managers { - //add sp_client - let sp_wallet = generate_sp_wallet(None, birthday_signet, true)?; - let sp_address = sp_wallet.get_client().get_receiving_address(); - members.push(sp_address); - } + let MEMBERS: [String;5] = [ + "tsp1qqdvmxycf3c3tf2qhpev0npx25rj05270d6j2pcsrfk2qn5gdy0rpwq6hd9u9sztl3fwmrzzqafzl3ymkq86aqfz5jl5egdkz72tqmhcnrswdz3pk".to_owned(), + "tsp1qqwafwn7dcr9d6ta0w8fjtd9s53u72x9qmmtgd8adqr7454xl90a5jq3vw23l2x8ypt55nrg7trl9lwz5xr5j357ucu4sf9rfmvc0zujcpqcps6rm".to_owned(), + "tsp1qqw02t5hmg5rxpjdkmjdnnmhvuc76wt6vlqdmn2zafnh6axxjd6e2gqcz04gzvnkzf572mur8spyx2a2s8sqzll2ymdpyz59cpl96j4zuvcdvrzxz".to_owned(), + "tsp1qqgpay2r5jswm7vcv24xd94shdf90w30vxtql9svw7qnlnrzd6xt02q7s7z57uw0sssh6c0xddcrryq4mxup93jsh3gfau3autrawl8umkgsyupkm".to_owned(), + "tsp1qqtsqmtgnxp0lsmnxyxcq52zpgxwugwlq8urlprs5pr5lwyqc789gjqhx5qra6g4rszsq43pms6nguee2l9trx905rk5sgntek05hnf7say4ru69y".to_owned(), + ]; //instances of process let process1 = Process { - id: 1, - name: String::from("CREATE_ID"), + id: 6, + name: String::from("Messaging"), version: String::from("1.0"), - members: members.clone(), - html: crate::process::HTML_CREATE_ID.to_owned(), + members: MEMBERS.to_vec(), + html: crate::process::HTML_MESSAGING.to_owned(), style: crate::process::CSS.to_owned(), script: "".to_owned(), }; let process2 = Process { - id: 2, - name: String::from("UPDATE_ID"), + id: 7, + name: String::from("Kotpart"), version: String::from("1.0"), - members: members.clone(), - html: crate::process::HTML_UPDATE_ID.to_owned(), - style: crate::process::CSSUPDATE.to_owned(), - script: crate::process::JSUPDATE.to_owned(), + members: MEMBERS.to_vec(), + html: crate::process::HTML_MESSAGING.to_owned(), + style: crate::process::CSS.to_owned(), + script: "".to_owned(), }; let process3 = Process { - id: 3, - name: String::from("RECOVER"), + id: 8, + name: String::from("Storage"), version: String::from("1.0"), - members: members.clone(), - html: crate::process::HTML_RECOVER.to_owned(), - style: crate::process::CSS.to_owned(), - script: "".to_owned(), - }; - let process4 = Process { - id: 4, - name: String::from("REVOKE_IMAGE"), - version: String::from("1.0"), - members: members.clone(), - html: crate::process::HTML_REVOKE_IMAGE.to_owned(), - style: crate::process::CSS.to_owned(), - script: "".to_owned(), - }; - let process5 = Process { - id: 5, - name: String::from("REVOKE"), - version: String::from("1.0"), - members: members.clone(), - html: crate::process::HTML_REVOKE.to_owned(), + members: MEMBERS.to_vec(), + html: crate::process::HTML_MESSAGING.to_owned(), style: crate::process::CSS.to_owned(), script: "".to_owned(), }; @@ -260,8 +238,6 @@ pub fn get_processes() -> ApiResult<get_process_return> { data_process.push(process1); data_process.push(process2); data_process.push(process3); - data_process.push(process4); - data_process.push(process5); Ok(get_process_return(data_process)) } diff --git a/crates/sp_client/src/process.rs b/crates/sp_client/src/process.rs index 56f95d6..2e6af74 100644 --- a/crates/sp_client/src/process.rs +++ b/crates/sp_client/src/process.rs @@ -6,144 +6,63 @@ use sp_backend::silentpayments::sending::SilentPaymentAddress; use tsify::Tsify; use wasm_bindgen::prelude::*; -pub const HTML_CREATE_ID: &str = " +pub const HTML_KOTPART: &str = " <div class='card'> <div class='side-by-side'> - <h3>Create an Id</h3> - <div><a href='#'>Processes</a></div> - </div> - <form id='form4nk' action='#'> - <label for='password'>Password :</label> - <input type='password' id='password' /><hr/> - <input type='hidden' id='currentpage' value='creatid' /> - <select id='selectProcess' class='custom-select'></select><hr/> - <div class='side-by-side'> - <button type='submit' id='submitButton' class='bg-primary'>Create</button> - <div> - <a href='#' id='displayrecover'>Recover</a> - </div> - </div> - </form><br/> - <div id='passwordalert' class='passwordalert'></div> - </div> - "; - -pub const HTML_UPDATE_ID: &str = " - <body> - <div class='container'> - <div> - <h3>Update an Id</h3> - </div> - <hr /> - <form id='form4nk' action='#'> - <label for='firstName'>First Name:</label> - <input type='text' id='firstName' name='firstName' required /> - - <label for='lastName'>Last Name:</label> - <input type='text' id='lastName' name='lastName' required /> - - <label for='Birthday'>Birthday:</label> - <input type='date' id='Birthday' name='birthday' /> - - <label for='file'>File:</label> - <input type='file' id='fileInput' name='file' /> - - <label>Third parties:</label> - <div id='sp-address-block'> - <div class='side-by-side'> - <input - type='text' - name='sp-address' - id='sp-address' - placeholder='sp address' - form='no-form' - /> - <button - type='button' - class='circle-btn bg-secondary' - id='add-sp-address-btn' - > - + - </button> - </div> - </div> - <div class='div-text-area'> - <textarea - name='bio' - id='' - cols='30' - rows='10' - placeholder='Bio' - ></textarea> - </div> - <button type='submit' class='bg-primary'>Update</button> - </form> - </div> - </body> - "; - -pub const HTML_RECOVER: &str = " - <div class='card'> - <div class='side-by-side'> - <h3>Recover my Id</h3> - <div><a href='#'>Processes</a></div> - </div> - <form id='form4nk' action='#'> - <label for='password'>Password :</label> - <input type='password' id='password' /> - <input type='hidden' id='currentpage' value='recover' /> - <select id='selectProcess' class='custom-select'></select><hr/> - <div class='side-by-side'> - <button type='submit' id='submitButton' class='recover bg-primary'>Recover</button> + <h3>Send encrypted messages</h3> <div> - <a href='#' id='displaycreateid'>Create an Id</a> - </div> - </div><hr/> - <a href='#' id='displayrevoke' class='btn'>Revoke</a> - </form><br/> - <div id='passwordalert' class='passwordalert'></div> - </div> - "; - -pub const HTML_REVOKE_IMAGE: &str = " - <div class='card'> - <div class='side-by-side'> - <h3>Revoke image</h3> - <div><a href='#' id='displayupdateanid'>Update an Id</a></div> - </div> - </div> - <div class='card-revoke'> - <a href='#' download='revoke_4NK.jpg' id='revoke'> - <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'> - <path - d='M246.6 9.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 109.3V320c0 17.7 14.3 32 32 32s32-14.3 32-32V109.3l73.4 73.4c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-128-128zM64 352c0-17.7-14.3-32-32-32s-32 14.3-32 32v64c0 53 43 96 96 96H352c53 0 96-43 96-96V352c0-17.7-14.3-32-32-32s-32 14.3-32 32v64c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V352z' - /> - </svg> - </a> - <div class='image-container'> - <img src='assets/4nk_revoke.jpg' alt='' /> - </div> - </div> - "; - -pub const HTML_REVOKE: &str = " - <div class='card'> - <div class='side-by-side'> - <h3>Revoke an Id</h3> - <div> - <a href='#' id='displayrecover'>Recover</a> + <a href='#' id='send messages'>Send Messages</a> </div> </div> <form id='form4nk' action='#'> - <label for='password'>Password :</label> - <input type='password' id='password' /> + <label for='sp_address'>Send to:</label> + <input type='text' id='sp_address' /> <hr/> - <div class='image-container'> - <label class='image-label'>Revoke image</label> - <img src='assets/revoke.jpeg' alt='' /> + <label for='message'>Message:</label> + <input type='message' id='message' /> + <hr/> + <button type='submit' id='submitButton' class='recover bg-primary'>Send</button> + </form> + </div> + "; + +pub const HTML_STORAGE: &str = " + <div class='card'> + <div class='side-by-side'> + <h3>Send encrypted messages</h3> + <div> + <a href='#' id='send messages'>Send Messages</a> </div> + </div> + <form id='form4nk' action='#'> + <label for='sp_address'>Send to:</label> + <input type='text' id='sp_address' /> <hr/> - <button type='submit' id='submitButton' class='recover bg-primary'>Revoke</button> + <label for='message'>Message:</label> + <input type='message' id='message' /> + <hr/> + <button type='submit' id='submitButton' class='recover bg-primary'>Send</button> + </form> + </div> + "; + +pub const HTML_MESSAGING: &str = " + <div class='card'> + <div class='side-by-side'> + <h3>Send encrypted messages</h3> + <div> + <a href='#' id='send messages'>Send Messages</a> + </div> + </div> + <form id='form4nk' action='#'> + <div id='our_address' class='our_address'></div> + <label for='sp_address'>Send to:</label> + <input type='text' id='sp_address' /> + <hr/> + <label for='message'>Message:</label> + <input type='message' id='message' /> + <hr/> + <button type='submit' id='submitButton' class='recover bg-primary'>Send</button> </form> </div> "; diff --git a/src/services.ts b/src/services.ts index 7160fbc..e7de153 100644 --- a/src/services.ts +++ b/src/services.ts @@ -24,27 +24,9 @@ class Services { private async init(): Promise<void> { this.sdkClient = await import("../dist/pkg/sdk_client"); this.sdkClient.setup(); + await this.updateProcesses(); } - // public async getSpAddressDefaultClient(): Promise<string | null> { - // try { - // const indexedDB = await IndexedDB.getInstance(); - // const db = indexedDB.getDb(); - // const spClient = await indexedDB.getObject<string>(db, indexedDB.getStoreList().SpClient, "default"); - - // if (spClient) { - // return this.sdkClient.get_receiving_address(spClient); - // } else { - // console.error("SP client not found"); - // return null; - // } - // } catch (error) { - // console.error("Failed to retrieve object or get sp address:", error); - // return null; - // } - - // } - public async addWebsocketConnection(url: string): Promise<void> { const services = await Services.getInstance(); const newClient = new WebSocketClient(url, services); @@ -70,7 +52,7 @@ class Services { public async displayCreateId(): Promise<void> { const services = await Services.getInstance(); - await services.injectHtml('CREATE_ID'); + await services.createIdInjectHtml(); services.attachSubmitListener("form4nk", (event) => services.createId(event)); services.attachClickListener("displayrecover", services.displayRecover); await services.displayProcess(); @@ -136,8 +118,8 @@ class Services { public async displayRecover(): Promise<void> { const services = await Services.getInstance(); - await services.injectHtml('RECOVER'); - services.attachSubmitListener("form4nk", services.recover); + await services.recoverInjectHtml(); + services.attachSubmitListener("form4nk", (event) => services.recover(event)); services.attachClickListener("displaycreateid", services.displayCreateId); services.attachClickListener("displayrevoke", services.displayRevoke); services.attachClickListener("submitButtonRevoke", services.revoke); @@ -168,7 +150,7 @@ class Services { public async displayRevokeImage(revokeData: Uint8Array): Promise<void> { const services = await Services.getInstance(); - await services.injectHtml('REVOKE_IMAGE'); + await services.revokeImageInjectHtml(); services.attachClickListener("displayupdateanid", services.displayUpdateAnId); let imageBytes = await services.getRecoverImage('assets/4nk_revoke.jpg'); @@ -209,7 +191,7 @@ class Services { public async displayRevoke(): Promise<void> { const services = await Services.getInstance(); - services.injectHtml('REVOKE'); + await services.revokeInjectHtml(); services.attachClickListener("displayrecover", Services.instance.displayRecover); services.attachSubmitListener("form4nk", Services.instance.revoke); } @@ -224,24 +206,8 @@ class Services { public async displayUpdateAnId() { const services = await Services.getInstance(); - console.log("JS displayUpdateAnId process : "+services.current_process); - let body = ""; - let style = ""; - let script = ""; - try { - const processObject = await services.getProcessByName("UPDATE_ID"); - if (processObject) { - body = processObject.html; - style = processObject.style; - script = processObject.script; - console.log("JS displayUpdateAnId body : "+body); + await services.updateIdInjectHtml(); - } - } catch (error) { - console.error("Failed to retrieve process with Error:", error); - } - - services.injectUpdateAnIdHtml(body, style, script); services.attachSubmitListener("form4nk", services.updateAnId); } @@ -370,22 +336,20 @@ class Services { return process; } - public async loadProcesses(): Promise<void> { + public async updateProcesses(): Promise<void> { const services = await Services.getInstance(); const processList: Process[] = services.sdkClient.get_processes(); - console.error('processList size: '+processList.length); processList.forEach(async (process: Process) => { const indexedDB = await IndexedDB.getInstance(); - const db = indexedDB.getDb(); + const db = await indexedDB.getDb(); try { const processStore = await indexedDB.getObject<Process>(db, indexedDB.getStoreList().AnkProcess, process.id); if (!processStore) { - console.error('Adding process.id : '+process.id); await indexedDB.writeObject(db, indexedDB.getStoreList().AnkProcess, process, null); } } catch (error) { - console.warn('Error while writing process', process.name, 'to indexedDB:', error); + console.error('Error while writing process', process.name, 'to indexedDB:', error); } }) } @@ -401,6 +365,190 @@ class Services { element?.removeEventListener("submit", callback); element?.addEventListener("submit", callback); } + public async revokeInjectHtml() { + const container = document.getElementById('containerId'); + + if (!container) { + console.error("No html container"); + return; + } + + container.innerHTML = + ` <div class='card'> + <div class='side-by-side'> + <h3>Revoke an Id</h3> + <div> + <a href='#' id='displayrecover'>Recover</a> + </div> + </div> + <form id='form4nk' action='#'> + <label for='password'>Password :</label> + <input type='password' id='password' /> + <hr/> + <div class='image-container'> + <label class='image-label'>Revoke image</label> + <img src='assets/revoke.jpeg' alt='' /> + </div> + <hr/> + <button type='submit' id='submitButton' class='recover bg-primary'>Revoke</button> + </form> + </div> + `; + } + public async revokeImageInjectHtml() { + const container = document.getElementById('containerId'); + + if (!container) { + console.error("No html container"); + return; + } + + container.innerHTML = + `<div class='card'> + <div class='side-by-side'> + <h3>Revoke image</h3> + <div><a href='#' id='displayupdateanid'>Update an Id</a></div> + </div> + </div> + <div class='card-revoke'> + <a href='#' download='revoke_4NK.jpg' id='revoke'> + <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'> + <path + d='M246.6 9.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 109.3V320c0 17.7 14.3 32 32 32s32-14.3 32-32V109.3l73.4 73.4c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-128-128zM64 352c0-17.7-14.3-32-32-32s-32 14.3-32 32v64c0 53 43 96 96 96H352c53 0 96-43 96-96V352c0-17.7-14.3-32-32-32s-32 14.3-32 32v64c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V352z' + /> + </svg> + </a> + <div class='image-container'> + <img src='assets/4nk_revoke.jpg' alt='' /> + </div> + </div>`; + } + + public async recoverInjectHtml() { + const container = document.getElementById('containerId'); + + if (!container) { + console.error("No html container"); + return; + } + + const services = await Services.getInstance(); + await services.updateProcesses(); + + container.innerHTML = + `<div class='card'> + <div class='side-by-side'> + <h3>Recover my Id</h3> + <div><a href='#'>Processes</a></div> + </div> + <form id='form4nk' action='#'> + <label for='password'>Password :</label> + <input type='password' id='password' /> + <input type='hidden' id='currentpage' value='recover' /> + <select id='selectProcess' class='custom-select'></select><hr/> + <div class='side-by-side'> + <button type='submit' id='submitButton' class='recover bg-primary'>Recover</button> + <div> + <a href='#' id='displaycreateid'>Create an Id</a> + </div> + </div><hr/> + <a href='#' id='displayrevoke' class='btn'>Revoke</a> + </form><br/> + <div id='passwordalert' class='passwordalert'></div> + </div>`; + } + + public async createIdInjectHtml() { + const container = document.getElementById('containerId'); + + if (!container) { + console.error("No html container"); + return; + } + + container.innerHTML = + `<div class='card'> + <div class='side-by-side'> + <h3>Create an Id</h3> + <div><a href='#'>Processes</a></div> + </div> + <form id='form4nk' action='#'> + <label for='password'>Password :</label> + <input type='password' id='password' /><hr/> + <input type='hidden' id='currentpage' value='creatid' /> + <select id='selectProcess' class='custom-select'></select><hr/> + <div class='side-by-side'> + <button type='submit' id='submitButton' class='bg-primary'>Create</button> + <div> + <a href='#' id='displayrecover'>Recover</a> + </div> + </div> + </form><br/> + <div id='passwordalert' class='passwordalert'></div> + </div>`; + } + + public async updateIdInjectHtml() { + const container = document.getElementById('containerId'); + + if (!container) { + console.error("No html container"); + return; + } + + container.innerHTML = + `<body> + <div class='container'> + <div> + <h3>Update an Id</h3> + </div> + <hr /> + <form id='form4nk' action='#'> + <label for='firstName'>First Name:</label> + <input type='text' id='firstName' name='firstName' required /> + + <label for='lastName'>Last Name:</label> + <input type='text' id='lastName' name='lastName' required /> + + <label for='Birthday'>Birthday:</label> + <input type='date' id='Birthday' name='birthday' /> + + <label for='file'>File:</label> + <input type='file' id='fileInput' name='file' /> + + <label>Third parties:</label> + <div id='sp-address-block'> + <div class='side-by-side'> + <input + type='text' + name='sp-address' + id='sp-address' + placeholder='sp address' + form='no-form' + /> + <button + type='button' + class='circle-btn bg-secondary' + id='add-sp-address-btn' + > + + + </button> + </div> + </div> + <div class='div-text-area'> + <textarea + name='bio' + id='' + cols='30' + rows='10' + placeholder='Bio' + ></textarea> + </div> + <button type='submit' class='bg-primary'>Update</button> + </form> + </div> + </body>`; + } public async injectHtml(processName: string) { const container = document.getElementById('containerId'); From 8fb517c1072498f6b946d6353539a6b5c9bafd9f Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 17 Apr 2024 08:58:28 +0200 Subject: [PATCH 52/90] Update faucet --- crates/sp_client/src/api.rs | 74 ++++++++++++++++++-------- crates/sp_client/src/silentpayments.rs | 60 ++++++--------------- src/services.ts | 55 ++++++------------- src/websockets.ts | 37 ++++++------- 4 files changed, 103 insertions(+), 123 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 2788999..c9b80b6 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -3,15 +3,18 @@ use std::collections::HashMap; use std::str::FromStr; use std::sync::{Mutex, OnceLock, PoisonError}; +use log::debug; use rand::Rng; use anyhow::Error as AnyhowError; +use sdk_common::crypto::AnkSharedSecret; use serde_json::Error as SerdeJsonError; use shamir::SecretData; -use sp_backend::bitcoin::consensus::deserialize; -use sp_backend::bitcoin::hex::{FromHex, HexToBytesError}; +use sp_backend::bitcoin::consensus::{deserialize, serialize}; +use sp_backend::bitcoin::hex::{parse, DisplayHex, FromHex, HexToBytesError}; +use sp_backend::bitcoin::secp256k1::ecdh::SharedSecret; use sp_backend::bitcoin::secp256k1::{PublicKey, SecretKey}; -use sp_backend::bitcoin::{Transaction, Txid}; +use sp_backend::bitcoin::{OutPoint, Transaction, Txid}; use sp_backend::silentpayments::Error as SpError; use serde::{Deserialize, Serialize}; @@ -20,12 +23,13 @@ use tsify::Tsify; use wasm_bindgen::convert::FromWasmAbi; use wasm_bindgen::prelude::*; -use sp_backend::spclient::{derive_keys_from_seed, OutputList, SpClient}; +use sdk_common::network::{AnkFlag, AnkNetworkMsg, NewTxMessage}; + +use sp_backend::spclient::{derive_keys_from_seed, OutputList, OwnedOutput, SpClient}; use sp_backend::spclient::{SpWallet, SpendKey}; use crate::images; -use crate::network::{BitcoinNetworkMsg, BitcoinTopic, AnkNetworkMsg, AnkTopic}; -use crate::silentpayments::check_transaction; +use crate::silentpayments::{check_transaction, create_transaction_for_address}; use crate::user::{lock_connected_users, User, UserWallets, CONNECTED_USERS}; use crate::process::Process; @@ -264,7 +268,7 @@ impl shamir_shares { } #[derive(Debug, Tsify, Serialize, Deserialize)] -#[tsify(from_wasm_abi)] +#[tsify(from_wasm_abi, into_wasm_abi)] #[allow(non_camel_case_types)] pub struct outputs_list(Vec<OutputList>); @@ -296,30 +300,58 @@ pub fn login_user( #[wasm_bindgen] pub fn check_transaction_for_silent_payments( tx_hex: String, + blockheight: u32, tweak_data_hex: String, -) -> ApiResult<()> { +) -> ApiResult<String> { let tx = deserialize::<Transaction>(&Vec::from_hex(&tx_hex)?)?; let tweak_data = PublicKey::from_str(&tweak_data_hex)?; - check_transaction(tx, tweak_data); + let updated_user = check_transaction(&tx, blockheight, tweak_data)?; - Ok(()) + Ok(updated_user) +} + +#[derive(Tsify, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[allow(non_camel_case_types)] +pub struct parseNetworkMsgReturn { + topic: String, + message: String, } #[wasm_bindgen] -pub fn parse_bitcoin_network_msg(msg: Vec<u8>) -> ApiResult<()> { - let parsed_msg = BitcoinNetworkMsg::new(&msg)?; - - match parsed_msg.topic { - BitcoinTopic::RawTx => { - let tx = deserialize::<Transaction>(parsed_msg.data)?; - let tweak_data = PublicKey::from_slice(parsed_msg.addon)?; - check_transaction(tx, tweak_data); +pub fn parse_network_msg(raw: String) -> ApiResult<parseNetworkMsgReturn> { + if let Ok(ank_msg) = serde_json::from_str::<AnkNetworkMsg>(&raw) { + match ank_msg.flag { + AnkFlag::NewTx => { + let tx_message = serde_json::from_str::<NewTxMessage>(&ank_msg.content)?; + let tx = deserialize::<Transaction>(&Vec::from_hex(&tx_message.transaction)?)?; + if tx_message.tweak_data.is_none() { + return Err(ApiError { + message: "Missing tweak_data".to_owned(), + }); + } + let partial_tweak = PublicKey::from_str(&tx_message.tweak_data.unwrap())?; + let txid = check_transaction(&tx, 0, partial_tweak)?; + return Ok(parseNetworkMsgReturn { + topic: AnkFlag::NewTx.as_str().to_owned(), + message: txid, + }); + } + AnkFlag::Faucet => unimplemented!(), + AnkFlag::Error => { + return Ok(parseNetworkMsgReturn { + topic: AnkFlag::Error.as_str().to_owned(), + message: ank_msg.content.to_owned(), + }) + } + _ => unimplemented!(), } - BitcoinTopic::RawBlock => (), + } else { + Err(ApiError { + message: format!("Can't parse message as a valid 4nk message: {}", raw), + }) } - - Ok(()) } #[wasm_bindgen] diff --git a/crates/sp_client/src/silentpayments.rs b/crates/sp_client/src/silentpayments.rs index 5ab45d4..14964f6 100644 --- a/crates/sp_client/src/silentpayments.rs +++ b/crates/sp_client/src/silentpayments.rs @@ -18,59 +18,33 @@ type FoundOutputs = HashMap<Option<Label>, HashMap<XOnlyPublicKey, Scalar>>; pub fn check_transaction(tx: Transaction, tweak_data: PublicKey) -> Result<FoundOutputs> { let connected_users = lock_connected_users()?; - let pubkeys_to_check: HashMap<XOnlyPublicKey, u32> = (0u32..) - .zip(tx.output) - .filter_map(|(i, o)| { - if o.script_pubkey.is_p2tr() { - let xonly = XOnlyPublicKey::from_slice(&o.script_pubkey.as_bytes()[2..]) - .expect("Transaction is invalid"); - Some((xonly, i)) - } else { - None - } - }) - .collect(); +pub fn check_transaction( + tx: &Transaction, + blockheight: u32, + tweak_data: PublicKey, +) -> Result<String> { + let connected_users = lock_connected_users()?; + let txid = tx.txid().to_string(); // Check the transaction for all connected users for (pre_id, keys) in connected_users.clone() { - let recover = keys.recover; - let shared_secret = - calculate_shared_secret(tweak_data, recover.get_client().get_scan_key())?; - let res = recover - .get_client() - .sp_receiver - .scan_transaction(&shared_secret, pubkeys_to_check.keys().cloned().collect())?; - - if res.len() > 0 { - return Ok(res); + let mut recover = keys.recover; + if recover.update_wallet_with_transaction(tx, blockheight, tweak_data)? > 0 { + return Ok(txid); } - if let Some(main) = keys.main { - let shared_secret = - calculate_shared_secret(tweak_data, main.get_client().get_scan_key())?; - let res = main - .get_client() - .sp_receiver - .scan_transaction(&shared_secret, pubkeys_to_check.keys().cloned().collect())?; - - if res.len() > 0 { - return Ok(res); + if let Some(mut main) = keys.main { + if main.update_wallet_with_transaction(tx, blockheight, tweak_data)? > 0 { + return Ok(txid); } } - if let Some(revoke) = keys.revoke { - let shared_secret = - calculate_shared_secret(tweak_data, revoke.get_client().get_scan_key())?; - let res = revoke - .get_client() - .sp_receiver - .scan_transaction(&shared_secret, pubkeys_to_check.keys().cloned().collect())?; - - if res.len() > 0 { - return Ok(res); + if let Some(mut revoke) = keys.revoke { + if revoke.update_wallet_with_transaction(tx, blockheight, tweak_data)? > 0 { + return Ok(txid); } } } - Ok(HashMap::new()) + return Err(Error::msg("No new outputs found")); } diff --git a/src/services.ts b/src/services.ts index e7de153..b7952d4 100644 --- a/src/services.ts +++ b/src/services.ts @@ -177,18 +177,6 @@ class Services { return imageBytes; } - public async parseBitcoinMessage(raw: Blob): Promise<string | null> { - try { - const buffer = await raw.arrayBuffer(); - const uint8Array = new Uint8Array(buffer); - const msg: string = this.sdkClient.parse_bitcoin_network_msg(uint8Array); - return msg; - } catch (error) { - console.error("Error processing the blob:", error); - return null; - } - } - public async displayRevoke(): Promise<void> { const services = await Services.getInstance(); await services.revokeInjectHtml(); @@ -211,30 +199,15 @@ class Services { services.attachSubmitListener("form4nk", services.updateAnId); } - public async parse4nkMessage(raw: string): Promise<string | null> { - const msg: string = this.sdkClient.parse_4nk_msg(raw); + public async parseNetworkMessage(raw: string): Promise<parseNetworkMsgReturn | null> { + const services = await Services.getInstance(); + try { + const msg: parseNetworkMsgReturn = services.sdkClient.parse_network_msg(raw); return msg; - } - - public injectUpdateAnIdHtml(bodyToInject: string, styleToInject: string, scriptToInject: string) { - console.log("JS html : "+bodyToInject); - const body = document.getElementsByTagName('body')[0]; - - if (!body) { - console.error("No body tag"); - return; + } catch (error) { + console.error(error); + return null; } - body.innerHTML = styleToInject + bodyToInject; - - const script = document.createElement("script"); - script.innerHTML = scriptToInject; - document.body.appendChild(script); - script.onload = () => { - console.log('Script loaded successfuly'); - }; - script.onerror = () => { - console.log('Error loading script'); - }; } public async updateAnId(event: Event): Promise<void> { @@ -288,11 +261,13 @@ class Services { return []; } } - - public async checkTransaction(tx: string): Promise<string | null> { + public async checkTransaction(tx: string, tweak_data: string, blkheight: number): Promise<string | null> { const services = await Services.getInstance(); + try { - return services.sdkClient.check_network_transaction(tx); + const updated_user: string = services.sdkClient.check_transaction_for_silent_payments(tx, blkheight, tweak_data); + await services.updateOwnedOutputsForUser(updated_user); + return updated_user; } catch (error) { console.error(error); return null; @@ -647,7 +622,11 @@ class Services { return null; } try { - connection.sendMessage('faucet'+spaddress); + const flag: AnkFlag = "Faucet"; + const faucetMsg: FaucetMessage = { + 'sp_address': spaddress + } + connection.sendMessage(flag, JSON.stringify(faucetMsg)); } catch (error) { console.error("Failed to obtain tokens with relay ", connection.getUrl()); return null; diff --git a/src/websockets.ts b/src/websockets.ts index 72d8c80..c73e7dd 100644 --- a/src/websockets.ts +++ b/src/websockets.ts @@ -1,5 +1,5 @@ import Services from "./services"; -// import * as mempool from "./mempool"; +import { AnkFlag, AnkNetworkMsg, parseNetworkMsgReturn } from "../dist/pkg/sdk_client"; class WebSocketClient { private ws: WebSocket; @@ -25,28 +25,18 @@ class WebSocketClient { console.log(msgData); (async () => { - if (msgData instanceof Blob) { - // bitcoin network msg is just bytes - let res = await services.parseBitcoinMessage(msgData); - if (res) { - let ours = await services.checkTransaction(res); - if (ours) { - console.log("Found our utxo in "+res); - } else { - console.log("No utxo found in tx "+res); - } - } else { - console.error("Faile to parse a bitcoin network msg"); - } - } else if (typeof(msgData) === 'string') { - // json strings are 4nk message + if (typeof(msgData) === 'string') { console.log("Received text message: "+msgData); - let res = await services.parse4nkMessage(msgData); + let res = await services.parseNetworkMessage(msgData); if (res) { - console.debug(res); + if (res.topic === 'new_tx') { + // we received a tx + window.alert(`New tx\n${res.message}`); + await services.updateOwnedOutputsForUser(res.message); + } } } else { - console.error("Received an unknown message"); + console.error("Received an invalid message"); } })(); }); @@ -63,9 +53,14 @@ class WebSocketClient { } // Method to send messages - public sendMessage(message: string): void { + public sendMessage(flag: AnkFlag, message: string): void { if (this.ws.readyState === WebSocket.OPEN) { - this.ws.send(message); + const networkMessage: AnkNetworkMsg = { + 'flag': flag, + 'content': message + } + // console.debug("Sending message:", JSON.stringify(networkMessage)); + this.ws.send(JSON.stringify(networkMessage)); } else { console.error('WebSocket is not open. ReadyState:', this.ws.readyState); this.messageQueue.push(message); From d6a473f6e917fb120aa7c261eb85c34dc3207356 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 17 Apr 2024 09:12:12 +0200 Subject: [PATCH 53/90] fix indexeddb --- src/database.ts | 30 ++++-------------------------- src/services.ts | 12 ++++++------ 2 files changed, 10 insertions(+), 32 deletions(-) diff --git a/src/database.ts b/src/database.ts index d8d8041..3c2fc30 100644 --- a/src/database.ts +++ b/src/database.ts @@ -4,32 +4,10 @@ class Database { private dbName: string = '4nk'; private dbVersion: number = 1; private storeDefinitions = { - // SpClient: { - // name: "sp_client", - // options: {}, - // indices: [] - // }, - // SpOutputs: { - // name: "sp_outputs", - // options: {'autoIncrement': true}, - // indices: [{ - // name: 'by_wallet_fingerprint', - // keyPath: 'wallet_fingerprint', - // options: { - // 'unique': false - // } - // }] - // }, AnkUser: { name: "user", options: {'keyPath': 'pre_id'}, - indices: [{ - name: 'by_process', - keyPath: 'process', - options: { - 'unique': false - } - }] + indices: [] }, AnkSession: { name: "session", @@ -92,11 +70,11 @@ class Database { }); } - public getDb(): IDBDatabase { + public async getDb(): Promise<IDBDatabase> { if (!this.db) { - throw new Error("Database not initialized"); + await this.init(); } - return this.db; + return this.db!; } public getStoreList(): {[key: string]: string} { diff --git a/src/services.ts b/src/services.ts index b7952d4..f159552 100644 --- a/src/services.ts +++ b/src/services.ts @@ -39,7 +39,7 @@ class Services { let isNew = false; try { const indexedDB = await IndexedDB.getInstance(); - const db = indexedDB.getDb(); + const db = await indexedDB.getDb(); let userListObject = await indexedDB.getAll<User>(db, indexedDB.getStoreList().AnkUser); if (userListObject.length == 0) { isNew = true; @@ -97,7 +97,7 @@ class Services { try { const indexedDb = await IndexedDB.getInstance(); - const db = indexedDb.getDb(); + const db = await indexedDb.getDb(); await indexedDb.writeObject(db, indexedDb.getStoreList().AnkUser, user, null); } catch (error) { console.error("Failed to write user object :", error); @@ -243,7 +243,7 @@ class Services { public async addProcess(process: Process): Promise<void> { try { const indexedDB = await IndexedDB.getInstance(); - const db = indexedDB.getDb(); + const db = await indexedDB.getDb(); await indexedDB.writeObject(db, indexedDB.getStoreList().AnkProcess, process, null); } catch (error) { console.log('addProcess failed: ',error); @@ -253,7 +253,7 @@ class Services { public async getAllProcess(): Promise<Process[]> { try { const indexedDB = await IndexedDB.getInstance(); - const db = indexedDB.getDb(); + const db = await indexedDB.getDb(); let processListObject = await indexedDB.getAll<Process>(db, indexedDB.getStoreList().AnkProcess); return processListObject; } catch (error) { @@ -280,7 +280,7 @@ class Services { let userProcessList: Process[] = []; try { const indexedDB = await IndexedDB.getInstance(); - const db = indexedDB.getDb(); + const db = await indexedDB.getDb(); user = await indexedDB.getObject<User>(db, indexedDB.getStoreList().AnkUser, pre_id); } catch (error) { console.error('getAllUserProcess failed: ',error); @@ -304,7 +304,7 @@ class Services { public async getProcessByName(name: string): Promise<Process | null> { console.log('getProcessByName name: '+name); const indexedDB = await IndexedDB.getInstance(); - const db = indexedDB.getDb(); + const db = await indexedDB.getDb(); const process = await indexedDB.getFirstMatchWithIndex<Process>(db, indexedDB.getStoreList().AnkProcess, 'by_name', name); console.log('getProcessByName process: '+process); From 18f159696b32cd4d8062a084601a83da6c2475a7 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 17 Apr 2024 09:13:19 +0200 Subject: [PATCH 54/90] fix image download --- src/services.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/services.ts b/src/services.ts index f159552..6e7a86c 100644 --- a/src/services.ts +++ b/src/services.ts @@ -158,6 +158,12 @@ class Services { var elem = document.getElementById("revoke") as HTMLAnchorElement; if (elem != null) { let imageWithData = services.sdkClient.add_data_to_image(imageBytes, revokeData, true); + const blob = new Blob([imageWithData], { type: 'image/jpeg' }); + const url = URL.createObjectURL(blob); + + // Set the href attribute for download + elem.href = url; + elem.download = 'revoke_4NK.jpg'; } } } From 8e60ec6ef0c2b4204c66d8fa9065d0d1d56a5c5b Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 17 Apr 2024 09:14:00 +0200 Subject: [PATCH 55/90] recover --- src/services.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/services.ts b/src/services.ts index 6e7a86c..ee5176a 100644 --- a/src/services.ts +++ b/src/services.ts @@ -128,7 +128,6 @@ class Services { public async recover(event: Event) { event.preventDefault(); - console.log("JS recover submit "); const passwordElement = document.getElementById("password") as HTMLInputElement; const processElement = document.getElementById("selectProcess") as HTMLSelectElement; @@ -140,12 +139,25 @@ class Services { const password = passwordElement.value; const process = processElement.value; - console.log("JS password: " + password + " process: " + process); + // console.log("JS password: " + password + " process: " + process); // To comment if test // if (!Services.instance.isPasswordValid(password)) return; - // TODO - alert("Recover submit to do ..."); + // Get user in db + const services = await Services.getInstance(); + try { + const user = await services.getUserInfo(); + if (user) { + services.sdkClient.login_user(password, user.pre_id, user.recover_data, user.shares, user.outputs); + this.sp_address = services.sdkClient.get_receiving_address(user?.pre_id); + } + } catch (error) { + console.error(error); + } + + // TODO: check blocks since last_scan and update outputs + + await services.displaySendMessage(); } public async displayRevokeImage(revokeData: Uint8Array): Promise<void> { From 51465902bd4c60580e717aca1684c42d91bb53d3 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 17 Apr 2024 09:14:36 +0200 Subject: [PATCH 56/90] update create id --- src/services.ts | 50 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/src/services.ts b/src/services.ts index ee5176a..f703aa6 100644 --- a/src/services.ts +++ b/src/services.ts @@ -61,6 +61,19 @@ class Services { public async createId(event: Event): Promise<void> { event.preventDefault(); + // verify we don't already have an user + const services = await Services.getInstance(); + try { + let user = await services.getUserInfo(); + if (user) { + console.error("User already exists, please recover"); + return; + } + } catch (error) { + console.error(error); + return; + } + const passwordElement = document.getElementById("password") as HTMLInputElement; const processElement = document.getElementById("selectProcess") as HTMLSelectElement; @@ -79,12 +92,11 @@ class Services { const birthday_signet = 50000; const birthday_main = 500000; - const services = await Services.getInstance(); let createUserReturn: createUserReturn = services.sdkClient.create_user(password, label, birthday_main, birthday_signet, this.current_process); let user = createUserReturn.user; - const shares = user.shares; + // const shares = user.shares; // send the shares on the network const revokeData = user.revoke_data; if (!revokeData) { @@ -92,7 +104,7 @@ class Services { return; } - user.shares = []; + // user.shares = []; user.revoke_data = null; try { @@ -103,16 +115,16 @@ class Services { console.error("Failed to write user object :", error); } - let sp_address = ""; try { - sp_address = services.sdkClient.get_receiving_address(user.pre_id); - console.info('Using sp_address:', sp_address); + this.sp_address = services.sdkClient.get_receiving_address(user.pre_id); + if (this.sp_address) { + console.info('Using sp_address:', this.sp_address); + await services.obtainTokenWithFaucet(this.sp_address); + } } catch (error) { console.error(error); } - await services.obtainTokenWithFaucet(sp_address); - await services.displayRevokeImage(new Uint8Array(revokeData)); } @@ -651,6 +663,28 @@ class Services { } return null; } + + public async getUserInfo(): Promise<User | null> { + try { + const indexedDB = await IndexedDB.getInstance(); + const db = await indexedDB.getDb(); + let user = await indexedDB.getAll<User>(db, indexedDB.getStoreList().AnkUser); + // This should never happen + if (user.length > 1) { + throw "Multiple users in db"; + } else { + let res = user.pop(); + if (res === undefined) { + return null; + } else { + return res; + } + } + } catch (error) { + console.error("Can't get user from db"); + return null; + } + } } export default Services; From 3330baefc17b947961bd0f4823fd71c2fdab4869 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 17 Apr 2024 09:15:15 +0200 Subject: [PATCH 57/90] Add send message screen --- src/services.ts | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/services.ts b/src/services.ts index f703aa6..6005be8 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,4 +1,4 @@ -import { createUserReturn, User, Process } from '../dist/pkg/sdk_client'; +import { createUserReturn, User, Process, createNotificationTransactionReturn, parse_network_msg, outputs_list, parseNetworkMsgReturn, FaucetMessage, AnkFlag } from '../dist/pkg/sdk_client'; import IndexedDB from './database' import { WebSocketClient } from './websockets'; @@ -7,6 +7,7 @@ class Services { private sdkClient: any; private current_process: string | null = null; private websocketConnection: WebSocketClient[] = []; + private sp_address: string | null = null; // Private constructor to prevent direct instantiation from outside private constructor() {} @@ -58,6 +59,37 @@ class Services { await services.displayProcess(); } + public async displaySendMessage(): Promise<void> { + const services = await Services.getInstance(); + await services.injectHtml('Messaging'); + services.attachSubmitListener("form4nk", (event) => services.sendMessage(event)); + const ourAddress = document.getElementById('our_address'); + if (ourAddress) { + ourAddress.innerHTML = `<strong>Our Address:</strong> ${this.sp_address}` + } + // services.attachClickListener("displaysendmessage", services.displaySendMessage); + // await services.displayProcess(); + } + + public async sendMessage(event: Event): Promise<void> { + event.preventDefault(); + + const spAddressElement = document.getElementById("sp_address") as HTMLInputElement; + const messageElement = document.getElementById("message") as HTMLInputElement; + + if (!spAddressElement || !messageElement) { + console.error("One or more elements not found"); + return; + } + + const recipientSpAddress = spAddressElement.value; + const message = messageElement.value; + const services = await Services.getInstance(); + + let notificationInfo = services.notify_address_for_message(recipientSpAddress, message); + console.log(notificationInfo); + } + public async createId(event: Event): Promise<void> { event.preventDefault(); From a6f4a5122cd4d44155f38636d8ffe96329b644a4 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 17 Apr 2024 09:15:30 +0200 Subject: [PATCH 58/90] update user outputs --- src/services.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/services.ts b/src/services.ts index 6005be8..593557b 100644 --- a/src/services.ts +++ b/src/services.ts @@ -323,6 +323,29 @@ class Services { return []; } } + + public async updateOwnedOutputsForUser(preId: string): Promise<void> { + const services = await Services.getInstance(); + let latest_outputs: outputs_list; + try { + latest_outputs = services.sdkClient.get_outpoints_for_user(preId); + } catch (error) { + console.error(error); + return; + } + + try { + const indexedDB = await IndexedDB.getInstance(); + const db = await indexedDB.getDb(); + const storeName = indexedDB.getStoreList().AnkUser; + let user = await indexedDB.getObject<User>(db, storeName, preId); + user.outputs = latest_outputs; + await indexedDB.setObject(db, storeName, user, null); + } catch (error) { + console.error(error); + } + } + public async checkTransaction(tx: string, tweak_data: string, blkheight: number): Promise<string | null> { const services = await Services.getInstance(); From 8f6918748dcad0897facb361d0d9c6b434f2109c Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 17 Apr 2024 09:15:44 +0200 Subject: [PATCH 59/90] add notify address for message --- crates/sp_client/src/api.rs | 81 ++++++++++++++++++++------ crates/sp_client/src/silentpayments.rs | 80 ++++++++++++++++++++++++- src/services.ts | 24 ++++++++ 3 files changed, 165 insertions(+), 20 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index c9b80b6..3182318 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -355,24 +355,69 @@ pub fn parse_network_msg(raw: String) -> ApiResult<parseNetworkMsgReturn> { } #[wasm_bindgen] -pub fn parse_4nk_msg(raw: String) -> Option<String>{ - if let Ok(msg) = AnkNetworkMsg::new(&raw) { - match msg.topic { - AnkTopic::Faucet => { - match Txid::from_str(msg.content) { - Ok(txid) => { - // return the txid for verification - Some(txid.to_string()) - }, - Err(e) => { - log::error!("Invalid txid with a \"faucet\" message: {}", e.to_string()); - None - } - } - } - } +pub fn get_outpoints_for_user(pre_id: String) -> ApiResult<outputs_list> { + let connected_users = lock_connected_users()?; + let user = connected_users.get(&pre_id).ok_or(ApiError { + message: "Can't find user".to_owned(), + })?; + Ok(outputs_list(user.get_all_outputs())) +} + +#[wasm_bindgen] +pub fn is_tx_owned_by_user(pre_id: String, tx: String) -> ApiResult<bool> { + let transaction = deserialize::<Transaction>(&Vec::from_hex(&tx)?)?; + let txid = transaction.txid(); + let connected_users = lock_connected_users()?; + let user = connected_users.get(&pre_id).ok_or(ApiError { + message: "Can't find user".to_owned(), + })?; + + if let Some(_) = user + .recover + .get_outputs() + .to_outpoints_list() + .iter() + .find(|(outpoint, output)| outpoint.txid == txid) + { + Ok(true) } else { - log::debug!("Can't parse message as a valid 4nk message: {}", raw); - None + Ok(false) } } + +#[derive(Tsify, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[allow(non_camel_case_types)] +pub struct createNotificationTransactionReturn { + pub transaction: String, + pub spaddress2secret: HashMap<String, String>, +} + +#[wasm_bindgen] +pub fn create_notification_transaction( + user_pre_id: String, + recipient: String, + message: String, +) -> ApiResult<createNotificationTransactionReturn> { + let sp_address: SilentPaymentAddress = recipient.try_into()?; + + let (transaction, notification_information) = + create_transaction_for_address(user_pre_id, sp_address, message)?; + + // The secret is an ecc point and *must* be hashed to produce a proper ecdh secret + // For now we propose to implement a tagged hash for it + // It could be interesting to add some piece of data to allow for the derivation of multiple secrets + + let spaddress2secret = notification_information + .into_iter() + .map(|(address, shared_pubkey)| { + let shared_secret = AnkSharedSecret::new_from_public_key(shared_pubkey); + (address.into(), shared_secret.to_string()) + }) + .collect(); + + Ok(createNotificationTransactionReturn { + transaction: serialize(&transaction).to_lower_hex_string(), + spaddress2secret, + }) +} diff --git a/crates/sp_client/src/silentpayments.rs b/crates/sp_client/src/silentpayments.rs index 14964f6..cee9658 100644 --- a/crates/sp_client/src/silentpayments.rs +++ b/crates/sp_client/src/silentpayments.rs @@ -1,8 +1,14 @@ use std::collections::HashMap; -use anyhow::Result; +use anyhow::{Error, Result}; +use rand::Rng; +use sp_backend::bitcoin::policy::DUST_RELAY_TX_FEE; +use sp_backend::bitcoin::secp256k1::ecdh::SharedSecret; +use sp_backend::bitcoin::{block, Amount, OutPoint}; +use sp_backend::silentpayments::sending::SilentPaymentAddress; use sp_backend::silentpayments::utils::receiving::calculate_shared_secret; +use sp_backend::spclient::{OutputList, OwnedOutput, Recipient, SpClient}; use sp_backend::{ bitcoin::{ secp256k1::{PublicKey, Scalar, XOnlyPublicKey}, @@ -15,9 +21,79 @@ use crate::user::{lock_connected_users, CONNECTED_USERS}; type FoundOutputs = HashMap<Option<Label>, HashMap<XOnlyPublicKey, Scalar>>; -pub fn check_transaction(tx: Transaction, tweak_data: PublicKey) -> Result<FoundOutputs> { +type NotificationInformation = (Transaction, Vec<(SilentPaymentAddress, PublicKey)>); + +pub fn create_transaction_for_address( + send_as: String, + sp_address: SilentPaymentAddress, + message: String, +) -> Result<NotificationInformation> { let connected_users = lock_connected_users()?; + let sender = connected_users + .get(&send_as) + .ok_or(Error::msg("Unknown sender"))?; + + let sp_wallet = if sp_address.is_testnet() { + &sender.recover + } else { + if let Some(main) = &sender.main { + main + } else { + return Err(Error::msg("Can't spend on mainnet")); + } + }; + + let available_outpoints = sender.recover.get_outputs().to_spendable_list(); + + // Here we need to add more heuristics about which outpoint we spend + // For now let's keep it simple + + let mut inputs: HashMap<OutPoint, OwnedOutput> = HashMap::new(); + + let total_available = + available_outpoints + .into_iter() + .try_fold(Amount::from_sat(0), |acc, (outpoint, output)| { + let new_total = acc + output.amount; + inputs.insert(outpoint, output); + if new_total > Amount::from_sat(1000) { + Err(new_total) + } else { + Ok(new_total) + } + }); + + match total_available { + Err(total) => log::debug!("Spending {} outputs totaling {} sats", inputs.len(), total), + Ok(_) => return Err(Error::msg("Not enought fund available")), + } + + let recipient = Recipient { + address: sp_address.into(), + amount: Amount::from_sat(1000), + nb_outputs: 1, + }; + + let mut new_psbt = sp_wallet + .get_client() + .create_new_psbt(inputs, vec![recipient], None)?; + log::debug!("Created psbt: {}", new_psbt); + SpClient::set_fees(&mut new_psbt, Amount::from_sat(1000), sp_address.into())?; + let shared_secrets: Vec<(SilentPaymentAddress, PublicKey)> = + sp_wallet.get_client().fill_sp_outputs(&mut new_psbt)?; + log::debug!("Definitive psbt: {}", new_psbt); + let mut aux_rand = [0u8; 32]; + rand::thread_rng().fill(&mut aux_rand); + let mut signed = sp_wallet.get_client().sign_psbt(new_psbt, &aux_rand)?; + log::debug!("signed psbt: {}", signed); + SpClient::finalize_psbt(&mut signed)?; + + let final_tx = signed.extract_tx()?; + + Ok((final_tx, shared_secrets)) +} + pub fn check_transaction( tx: &Transaction, blockheight: u32, diff --git a/src/services.ts b/src/services.ts index 593557b..1643b09 100644 --- a/src/services.ts +++ b/src/services.ts @@ -740,6 +740,30 @@ class Services { return null; } } + + public async notify_address_for_message(sp_address: string, message: string): Promise<createNotificationTransactionReturn | null> { + const services = await Services.getInstance(); + let user: User; + try { + let possibleUser = await services.getUserInfo(); + if (!possibleUser) { + console.error("No user loaded, please first create a new user or login"); + return null; + } else { + user = possibleUser; + } + } catch (error) { + throw error; + } + + try { + let notificationInfo: createNotificationTransactionReturn = services.sdkClient.create_notification_transaction(user, sp_address, message); + return notificationInfo; + } catch { + console.error("Failed to create notification transaction for user", user); + return null + } + } } export default Services; From 1ac419edb7bab4faa75100c55d7577a5d730d74d Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 17 Apr 2024 21:53:29 +0200 Subject: [PATCH 60/90] Update sp_backend to sp_client --- crates/sp_client/Cargo.toml | 2 +- crates/sp_client/src/Prd_list.rs | 4 ++-- crates/sp_client/src/api.rs | 26 +++++++++++++------------- crates/sp_client/src/images.rs | 2 +- crates/sp_client/src/process.rs | 2 +- crates/sp_client/src/silentpayments.rs | 14 +++++++------- crates/sp_client/src/user.rs | 22 +++++++++++----------- 7 files changed, 36 insertions(+), 36 deletions(-) diff --git a/crates/sp_client/Cargo.toml b/crates/sp_client/Cargo.toml index 1a725bc..2155567 100644 --- a/crates/sp_client/Cargo.toml +++ b/crates/sp_client/Cargo.toml @@ -8,7 +8,7 @@ name = "sdk_client" crate-type = ["cdylib"] [dependencies] -sp_backend = { git = "https://github.com/Sosthene00/sp-backend", branch = "sp_client" } +sp_client= { git = "https://github.com/Sosthene00/sp-client", branch = "sp_client" } anyhow = "1.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0" diff --git a/crates/sp_client/src/Prd_list.rs b/crates/sp_client/src/Prd_list.rs index e8e8185..9ed63d0 100644 --- a/crates/sp_client/src/Prd_list.rs +++ b/crates/sp_client/src/Prd_list.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; -use sp_backend::bitcoin::PublicKey; -//use sp_backend::silentpayments::sending::SilentPaymentAddress; +use sp_client::bitcoin::PublicKey; +//use sp_client::silentpayments::sending::SilentPaymentAddress; use std::marker::Copy; use tsify::Tsify; use wasm_bindgen::prelude::*; diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 3182318..213a6b0 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -10,23 +10,23 @@ use anyhow::Error as AnyhowError; use sdk_common::crypto::AnkSharedSecret; use serde_json::Error as SerdeJsonError; use shamir::SecretData; -use sp_backend::bitcoin::consensus::{deserialize, serialize}; -use sp_backend::bitcoin::hex::{parse, DisplayHex, FromHex, HexToBytesError}; -use sp_backend::bitcoin::secp256k1::ecdh::SharedSecret; -use sp_backend::bitcoin::secp256k1::{PublicKey, SecretKey}; -use sp_backend::bitcoin::{OutPoint, Transaction, Txid}; -use sp_backend::silentpayments::Error as SpError; +use sp_client::bitcoin::consensus::{deserialize, serialize}; +use sp_client::bitcoin::hex::{parse, DisplayHex, FromHex, HexToBytesError}; +use sp_client::bitcoin::secp256k1::ecdh::SharedSecret; +use sp_client::bitcoin::secp256k1::{PublicKey, SecretKey}; +use sp_client::bitcoin::{OutPoint, Transaction, Txid}; +use sp_client::silentpayments::Error as SpError; use serde::{Deserialize, Serialize}; -use sp_backend::silentpayments::sending::SilentPaymentAddress; +use sp_client::silentpayments::sending::SilentPaymentAddress; use tsify::Tsify; use wasm_bindgen::convert::FromWasmAbi; use wasm_bindgen::prelude::*; use sdk_common::network::{AnkFlag, AnkNetworkMsg, NewTxMessage}; -use sp_backend::spclient::{derive_keys_from_seed, OutputList, OwnedOutput, SpClient}; -use sp_backend::spclient::{SpWallet, SpendKey}; +use sp_client::spclient::{derive_keys_from_seed, OutputList, OwnedOutput, SpClient}; +use sp_client::spclient::{SpWallet, SpendKey}; use crate::images; use crate::silentpayments::{check_transaction, create_transaction_for_address}; @@ -75,16 +75,16 @@ impl From<HexToBytesError> for ApiError { } } -impl From<sp_backend::bitcoin::secp256k1::Error> for ApiError { - fn from(value: sp_backend::bitcoin::secp256k1::Error) -> Self { +impl From<sp_client::bitcoin::secp256k1::Error> for ApiError { + fn from(value: sp_client::bitcoin::secp256k1::Error) -> Self { ApiError { message: value.to_string(), } } } -impl From<sp_backend::bitcoin::consensus::encode::Error> for ApiError { - fn from(value: sp_backend::bitcoin::consensus::encode::Error) -> Self { +impl From<sp_client::bitcoin::consensus::encode::Error> for ApiError { + fn from(value: sp_client::bitcoin::consensus::encode::Error) -> Self { ApiError { message: value.to_string(), } diff --git a/crates/sp_client/src/images.rs b/crates/sp_client/src/images.rs index f0e11ee..f0e0698 100644 --- a/crates/sp_client/src/images.rs +++ b/crates/sp_client/src/images.rs @@ -1,7 +1,7 @@ use anyhow::{Error, Result}; use img_parts::{jpeg::Jpeg, Bytes, ImageEXIF}; use serde::{Deserialize, Serialize}; -use sp_backend::bitcoin::secp256k1::SecretKey; +use sp_client::bitcoin::secp256k1::SecretKey; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct BackUpImage(Vec<u8>); diff --git a/crates/sp_client/src/process.rs b/crates/sp_client/src/process.rs index 2e6af74..36e1c47 100644 --- a/crates/sp_client/src/process.rs +++ b/crates/sp_client/src/process.rs @@ -2,7 +2,7 @@ use std::fmt::DebugStruct; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; -use sp_backend::silentpayments::sending::SilentPaymentAddress; +use sp_client::silentpayments::sending::SilentPaymentAddress; use tsify::Tsify; use wasm_bindgen::prelude::*; diff --git a/crates/sp_client/src/silentpayments.rs b/crates/sp_client/src/silentpayments.rs index cee9658..a82f99e 100644 --- a/crates/sp_client/src/silentpayments.rs +++ b/crates/sp_client/src/silentpayments.rs @@ -3,13 +3,13 @@ use std::collections::HashMap; use anyhow::{Error, Result}; use rand::Rng; -use sp_backend::bitcoin::policy::DUST_RELAY_TX_FEE; -use sp_backend::bitcoin::secp256k1::ecdh::SharedSecret; -use sp_backend::bitcoin::{block, Amount, OutPoint}; -use sp_backend::silentpayments::sending::SilentPaymentAddress; -use sp_backend::silentpayments::utils::receiving::calculate_shared_secret; -use sp_backend::spclient::{OutputList, OwnedOutput, Recipient, SpClient}; -use sp_backend::{ +use sp_client::bitcoin::policy::DUST_RELAY_TX_FEE; +use sp_client::bitcoin::secp256k1::ecdh::SharedSecret; +use sp_client::bitcoin::{block, Amount, OutPoint}; +use sp_client::silentpayments::sending::SilentPaymentAddress; +use sp_client::silentpayments::utils::receiving::calculate_shared_secret; +use sp_client::spclient::{OutputList, OwnedOutput, Recipient, SpClient}; +use sp_client::{ bitcoin::{ secp256k1::{PublicKey, Scalar, XOnlyPublicKey}, Transaction, diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index d1720c1..30a0119 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -2,12 +2,12 @@ use anyhow::{Error, Result}; use rand::{self, thread_rng, Rng, RngCore}; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; -use sp_backend::bitcoin::hashes::Hash; -use sp_backend::bitcoin::hashes::HashEngine; -use sp_backend::bitcoin::hex::{DisplayHex, FromHex}; -use sp_backend::bitcoin::secp256k1::SecretKey; -use sp_backend::bitcoin::secp256k1::ThirtyTwoByteHash; -use sp_backend::spclient::SpClient; +use sp_client::bitcoin::hashes::Hash; +use sp_client::bitcoin::hashes::HashEngine; +use sp_client::bitcoin::hex::{DisplayHex, FromHex}; +use sp_client::bitcoin::secp256k1::SecretKey; +use sp_client::bitcoin::secp256k1::ThirtyTwoByteHash; +use sp_client::spclient::SpClient; use tsify::Tsify; use wasm_bindgen::prelude::*; @@ -18,11 +18,11 @@ use std::io::{Cursor, Read, Write}; use std::str::FromStr; use std::sync::{Mutex, MutexGuard, OnceLock}; -use sp_backend::bitcoin::secp256k1::constants::SECRET_KEY_SIZE; -use sp_backend::silentpayments::bitcoin_hashes::sha256; -use sp_backend::silentpayments::sending::SilentPaymentAddress; -use sp_backend::spclient::SpendKey; -use sp_backend::spclient::{OutputList, SpWallet}; +use sp_client::bitcoin::secp256k1::constants::SECRET_KEY_SIZE; +use sp_client::silentpayments::bitcoin_hashes::sha256; +use sp_client::silentpayments::sending::SilentPaymentAddress; +use sp_client::spclient::SpendKey; +use sp_client::spclient::{OutputList, SpWallet}; use crate::peers::Peer; use crate::user; From c986324c6899f260e3bce66cad4e2690922eb0f0 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Wed, 17 Apr 2024 21:56:48 +0200 Subject: [PATCH 61/90] check_transaction_for_silent_payments returns txid --- crates/sp_client/src/api.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 213a6b0..0eb9bf7 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -306,9 +306,9 @@ pub fn check_transaction_for_silent_payments( let tx = deserialize::<Transaction>(&Vec::from_hex(&tx_hex)?)?; let tweak_data = PublicKey::from_str(&tweak_data_hex)?; - let updated_user = check_transaction(&tx, blockheight, tweak_data)?; + let txid = check_transaction(&tx, blockheight, tweak_data)?; - Ok(updated_user) + Ok(txid) } #[derive(Tsify, Serialize, Deserialize)] From 0f185c693fc277d8ecef7b65f225e803b557fb94 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Thu, 18 Apr 2024 00:35:16 +0200 Subject: [PATCH 62/90] fix update outputs for user --- src/services.ts | 34 +++++++++++++++++++++------------- src/websockets.ts | 2 +- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/services.ts b/src/services.ts index 1643b09..77a23ca 100644 --- a/src/services.ts +++ b/src/services.ts @@ -324,23 +324,22 @@ class Services { } } - public async updateOwnedOutputsForUser(preId: string): Promise<void> { + public async updateOwnedOutputsForUser(): Promise<void> { const services = await Services.getInstance(); let latest_outputs: outputs_list; try { - latest_outputs = services.sdkClient.get_outpoints_for_user(preId); + latest_outputs = services.sdkClient.get_outpoints_for_user(); } catch (error) { console.error(error); return; } try { - const indexedDB = await IndexedDB.getInstance(); - const db = await indexedDB.getDb(); - const storeName = indexedDB.getStoreList().AnkUser; - let user = await indexedDB.getObject<User>(db, storeName, preId); - user.outputs = latest_outputs; - await indexedDB.setObject(db, storeName, user, null); + let user = await services.getUserInfo(); + if (user) { + user.outputs = latest_outputs; + await services.updateUser(user); + } } catch (error) { console.error(error); } @@ -350,9 +349,9 @@ class Services { const services = await Services.getInstance(); try { - const updated_user: string = services.sdkClient.check_transaction_for_silent_payments(tx, blkheight, tweak_data); - await services.updateOwnedOutputsForUser(updated_user); - return updated_user; + const txid = services.sdkClient.check_transaction_for_silent_payments(tx, blkheight, tweak_data); + await services.updateOwnedOutputsForUser(); + return txid; } catch (error) { console.error(error); return null; @@ -719,6 +718,16 @@ class Services { return null; } + public async updateUser(user: User): Promise<void> { + try { + const indexedDB = await IndexedDB.getInstance(); + const db = await indexedDB.getDb(); + await indexedDB.setObject(db, indexedDB.getStoreList().AnkUser, user, null); + } catch (error) { + throw error; + } + } + public async getUserInfo(): Promise<User | null> { try { const indexedDB = await IndexedDB.getInstance(); @@ -736,8 +745,7 @@ class Services { } } } catch (error) { - console.error("Can't get user from db"); - return null; + throw error; } } diff --git a/src/websockets.ts b/src/websockets.ts index c73e7dd..c94b4af 100644 --- a/src/websockets.ts +++ b/src/websockets.ts @@ -32,7 +32,7 @@ class WebSocketClient { if (res.topic === 'new_tx') { // we received a tx window.alert(`New tx\n${res.message}`); - await services.updateOwnedOutputsForUser(res.message); + await services.updateOwnedOutputsForUser(); } } } else { From b5f3c821927b25781ca01a0b0a884ca8a19f19b8 Mon Sep 17 00:00:00 2001 From: Sosthene00 <674694@protonmail.ch> Date: Thu, 18 Apr 2024 00:36:38 +0200 Subject: [PATCH 63/90] Get the shared secret from a transaction --- crates/sp_client/src/api.rs | 28 +++++++++++------------ crates/sp_client/src/silentpayments.rs | 31 ++++++++++++++------------ 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 0eb9bf7..6046111 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -1,5 +1,6 @@ use std::any::Any; use std::collections::HashMap; +use std::io::Write; use std::str::FromStr; use std::sync::{Mutex, OnceLock, PoisonError}; @@ -11,6 +12,7 @@ use sdk_common::crypto::AnkSharedSecret; use serde_json::Error as SerdeJsonError; use shamir::SecretData; use sp_client::bitcoin::consensus::{deserialize, serialize}; +use sp_client::silentpayments::bitcoin_hashes::{HashEngine, sha256, Hash}; use sp_client::bitcoin::hex::{parse, DisplayHex, FromHex, HexToBytesError}; use sp_client::bitcoin::secp256k1::ecdh::SharedSecret; use sp_client::bitcoin::secp256k1::{PublicKey, SecretKey}; @@ -355,9 +357,9 @@ pub fn parse_network_msg(raw: String) -> ApiResult<parseNetworkMsgReturn> { } #[wasm_bindgen] -pub fn get_outpoints_for_user(pre_id: String) -> ApiResult<outputs_list> { +pub fn get_outpoints_for_user() -> ApiResult<outputs_list> { let connected_users = lock_connected_users()?; - let user = connected_users.get(&pre_id).ok_or(ApiError { + let (_, user) = connected_users.iter().last().ok_or(ApiError { message: "Can't find user".to_owned(), })?; Ok(outputs_list(user.get_all_outputs())) @@ -395,26 +397,24 @@ pub struct createNotificationTransactionReturn { #[wasm_bindgen] pub fn create_notification_transaction( - user_pre_id: String, recipient: String, message: String, ) -> ApiResult<createNotificationTransactionReturn> { let sp_address: SilentPaymentAddress = recipient.try_into()?; - let (transaction, notification_information) = - create_transaction_for_address(user_pre_id, sp_address, message)?; + let (transaction, shared_point) = + create_transaction_for_address_with_shared_secret(sp_address, message)?; - // The secret is an ecc point and *must* be hashed to produce a proper ecdh secret + // The shared_point *must* be hashed to produce a proper ecdh secret // For now we propose to implement a tagged hash for it - // It could be interesting to add some piece of data to allow for the derivation of multiple secrets + // It could be interesting to add some piece of data to allow for the derivation of multiple secrets + let mut eng = sha256::HashEngine::default(); + eng.write_all(&shared_point); + let shared_secret = sha256::Hash::from_engine(eng); - let spaddress2secret = notification_information - .into_iter() - .map(|(address, shared_pubkey)| { - let shared_secret = AnkSharedSecret::new_from_public_key(shared_pubkey); - (address.into(), shared_secret.to_string()) - }) - .collect(); + let mut spaddress2secret: HashMap<String, String> = HashMap::new(); + + spaddress2secret.insert(sp_address.into(), shared_secret.as_byte_array().to_lower_hex_string()); Ok(createNotificationTransactionReturn { transaction: serialize(&transaction).to_lower_hex_string(), diff --git a/crates/sp_client/src/silentpayments.rs b/crates/sp_client/src/silentpayments.rs index a82f99e..ac2a223 100644 --- a/crates/sp_client/src/silentpayments.rs +++ b/crates/sp_client/src/silentpayments.rs @@ -4,11 +4,11 @@ use anyhow::{Error, Result}; use rand::Rng; use sp_client::bitcoin::policy::DUST_RELAY_TX_FEE; -use sp_client::bitcoin::secp256k1::ecdh::SharedSecret; +use sp_client::bitcoin::secp256k1::ecdh::shared_secret_point; use sp_client::bitcoin::{block, Amount, OutPoint}; use sp_client::silentpayments::sending::SilentPaymentAddress; use sp_client::silentpayments::utils::receiving::calculate_shared_secret; -use sp_client::spclient::{OutputList, OwnedOutput, Recipient, SpClient}; +use sp_client::spclient::{OutputList, OwnedOutput, Recipient, SpClient, SpWallet}; use sp_client::{ bitcoin::{ secp256k1::{PublicKey, Scalar, XOnlyPublicKey}, @@ -21,30 +21,30 @@ use crate::user::{lock_connected_users, CONNECTED_USERS}; type FoundOutputs = HashMap<Option<Label>, HashMap<XOnlyPublicKey, Scalar>>; -type NotificationInformation = (Transaction, Vec<(SilentPaymentAddress, PublicKey)>); +type SharedPoint = [u8;64]; -pub fn create_transaction_for_address( - send_as: String, +pub fn create_transaction_for_address_with_shared_secret( sp_address: SilentPaymentAddress, message: String, -) -> Result<NotificationInformation> { +) -> Result<(Transaction, SharedPoint)> { let connected_users = lock_connected_users()?; - let sender = connected_users - .get(&send_as) + let (_, wallets) = connected_users + .iter() + .last() .ok_or(Error::msg("Unknown sender"))?; let sp_wallet = if sp_address.is_testnet() { - &sender.recover + &wallets.recover } else { - if let Some(main) = &sender.main { + if let Some(main) = &wallets.main { main } else { return Err(Error::msg("Can't spend on mainnet")); } }; - let available_outpoints = sender.recover.get_outputs().to_spendable_list(); + let available_outpoints = wallets.recover.get_outputs().to_spendable_list(); // Here we need to add more heuristics about which outpoint we spend // For now let's keep it simple @@ -80,8 +80,8 @@ pub fn create_transaction_for_address( .create_new_psbt(inputs, vec![recipient], None)?; log::debug!("Created psbt: {}", new_psbt); SpClient::set_fees(&mut new_psbt, Amount::from_sat(1000), sp_address.into())?; - let shared_secrets: Vec<(SilentPaymentAddress, PublicKey)> = - sp_wallet.get_client().fill_sp_outputs(&mut new_psbt)?; + let partial_secret = sp_wallet.get_client().get_partial_secret_from_psbt(&new_psbt)?; + sp_wallet.get_client().fill_sp_outputs(&mut new_psbt, partial_secret)?; log::debug!("Definitive psbt: {}", new_psbt); let mut aux_rand = [0u8; 32]; rand::thread_rng().fill(&mut aux_rand); @@ -91,7 +91,10 @@ pub fn create_transaction_for_address( let final_tx = signed.extract_tx()?; - Ok((final_tx, shared_secrets)) + // This should not be directly used without hashing + let shared_point = shared_secret_point(&sp_address.get_scan_key(), &partial_secret); + + Ok((final_tx, shared_point)) } pub fn check_transaction( From c57330d389883f4254ca521d86487ad48fc711da Mon Sep 17 00:00:00 2001 From: Sosthene00 <contact@sosthene.net> Date: Fri, 19 Apr 2024 00:20:34 +0200 Subject: [PATCH 64/90] Hide our_address --- src/services.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/services.ts b/src/services.ts index 77a23ca..56d26a2 100644 --- a/src/services.ts +++ b/src/services.ts @@ -63,10 +63,10 @@ class Services { const services = await Services.getInstance(); await services.injectHtml('Messaging'); services.attachSubmitListener("form4nk", (event) => services.sendMessage(event)); - const ourAddress = document.getElementById('our_address'); - if (ourAddress) { - ourAddress.innerHTML = `<strong>Our Address:</strong> ${this.sp_address}` - } + // const ourAddress = document.getElementById('our_address'); + // if (ourAddress) { + // ourAddress.innerHTML = `<strong>Our Address:</strong> ${this.sp_address}` + // } // services.attachClickListener("displaysendmessage", services.displaySendMessage); // await services.displayProcess(); } From 5cddf0566a8911a9378e7d86564fba5ee5fb1e83 Mon Sep 17 00:00:00 2001 From: Sosthene00 <contact@sosthene.net> Date: Fri, 19 Apr 2024 00:23:09 +0200 Subject: [PATCH 65/90] WIP --- crates/sp_client/src/api.rs | 22 ++--- crates/sp_client/src/silentpayments.rs | 125 ++++++++++++++++++++++--- src/services.ts | 21 ++++- 3 files changed, 140 insertions(+), 28 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 6046111..14c43cc 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -12,7 +12,6 @@ use sdk_common::crypto::AnkSharedSecret; use serde_json::Error as SerdeJsonError; use shamir::SecretData; use sp_client::bitcoin::consensus::{deserialize, serialize}; -use sp_client::silentpayments::bitcoin_hashes::{HashEngine, sha256, Hash}; use sp_client::bitcoin::hex::{parse, DisplayHex, FromHex, HexToBytesError}; use sp_client::bitcoin::secp256k1::ecdh::SharedSecret; use sp_client::bitcoin::secp256k1::{PublicKey, SecretKey}; @@ -31,7 +30,9 @@ use sp_client::spclient::{derive_keys_from_seed, OutputList, OwnedOutput, SpClie use sp_client::spclient::{SpWallet, SpendKey}; use crate::images; -use crate::silentpayments::{check_transaction, create_transaction_for_address}; +use crate::silentpayments::{ + check_transaction, create_transaction_for_address_with_shared_secret, ScannedTransaction, +}; use crate::user::{lock_connected_users, User, UserWallets, CONNECTED_USERS}; use crate::process::Process; @@ -392,7 +393,7 @@ pub fn is_tx_owned_by_user(pre_id: String, tx: String) -> ApiResult<bool> { #[allow(non_camel_case_types)] pub struct createNotificationTransactionReturn { pub transaction: String, - pub spaddress2secret: HashMap<String, String>, + pub transaction2secret: ScannedTransaction, } #[wasm_bindgen] @@ -402,22 +403,17 @@ pub fn create_notification_transaction( ) -> ApiResult<createNotificationTransactionReturn> { let sp_address: SilentPaymentAddress = recipient.try_into()?; - let (transaction, shared_point) = + let (transaction, shared_secret) = create_transaction_for_address_with_shared_secret(sp_address, message)?; - // The shared_point *must* be hashed to produce a proper ecdh secret - // For now we propose to implement a tagged hash for it - // It could be interesting to add some piece of data to allow for the derivation of multiple secrets - let mut eng = sha256::HashEngine::default(); - eng.write_all(&shared_point); - let shared_secret = sha256::Hash::from_engine(eng); - let mut spaddress2secret: HashMap<String, String> = HashMap::new(); + // update our cache - spaddress2secret.insert(sp_address.into(), shared_secret.as_byte_array().to_lower_hex_string()); + let mut transaction2secret = ScannedTransaction::new(); + transaction2secret.get_mut().insert(transaction.txid(), vec![shared_secret]); Ok(createNotificationTransactionReturn { transaction: serialize(&transaction).to_lower_hex_string(), - spaddress2secret, + transaction2secret, }) } diff --git a/crates/sp_client/src/silentpayments.rs b/crates/sp_client/src/silentpayments.rs index ac2a223..1b5d35e 100644 --- a/crates/sp_client/src/silentpayments.rs +++ b/crates/sp_client/src/silentpayments.rs @@ -1,14 +1,23 @@ -use std::collections::HashMap; +// This file should move to common + +use std::collections::{HashMap, HashSet}; +use std::io::Write; +use std::iter::Once; +use std::sync::{Mutex, MutexGuard, OnceLock}; use anyhow::{Error, Result}; +use log::debug; use rand::Rng; +use sdk_common::crypto::{Aes256Encryption, Aes256Gcm, AeadCore, Purpose}; +use serde::{Deserialize, Serialize}; use sp_client::bitcoin::policy::DUST_RELAY_TX_FEE; use sp_client::bitcoin::secp256k1::ecdh::shared_secret_point; -use sp_client::bitcoin::{block, Amount, OutPoint}; +use sp_client::bitcoin::{block, Amount, OutPoint, Txid}; use sp_client::silentpayments::sending::SilentPaymentAddress; use sp_client::silentpayments::utils::receiving::calculate_shared_secret; use sp_client::spclient::{OutputList, OwnedOutput, Recipient, SpClient, SpWallet}; +use sp_client::silentpayments::bitcoin_hashes::{sha256, Hash, HashEngine}; use sp_client::{ bitcoin::{ secp256k1::{PublicKey, Scalar, XOnlyPublicKey}, @@ -16,17 +25,75 @@ use sp_client::{ }, silentpayments::receiving::Label, }; +use tsify::Tsify; use crate::user::{lock_connected_users, CONNECTED_USERS}; +use crate::MutexExt; + +#[derive(Debug, Serialize, Deserialize, Tsify)] +#[tsify(into_wasm_abi, from_wasm_abi)] +pub struct ScannedTransaction(HashMap<Txid, Vec<SharedSecret>>); + +impl ScannedTransaction { + pub fn new() -> Self { + Self(HashMap::new()) + } + + pub fn get_mut(&mut self) -> &mut HashMap<Txid, Vec<SharedSecret>> { + &mut self.0 + } +} + +pub static TRANSACTIONCACHE: OnceLock<Mutex<ScannedTransaction>> = OnceLock::new(); + +pub fn lock_scanned_transactions() -> Result<MutexGuard<'static, ScannedTransaction>> { + TRANSACTIONCACHE + .get_or_init(|| Mutex::new(ScannedTransaction::new())) + .lock_anyhow() +} type FoundOutputs = HashMap<Option<Label>, HashMap<XOnlyPublicKey, Scalar>>; -type SharedPoint = [u8;64]; +#[derive(Debug)] +pub struct SharedPoint([u8; 64]); + +impl SharedPoint { + pub fn as_inner(&self) -> &[u8; 64] { + &self.0 + } +} + +#[derive(Debug, Serialize, Deserialize, Tsify)] +#[tsify(from_wasm_abi, into_wasm_abi)] +pub struct SharedSecret { + secret: [u8; 32], + shared_with: Option<String>, // SilentPaymentAddress +} + +impl SharedSecret { + pub fn new(secret: [u8;32], shared_with: Option<String>) -> Result<Self> { + if let Some(ref shared) = shared_with { + if let Ok(_) = SilentPaymentAddress::try_from(shared.as_str()) { + Ok(Self { + secret, + shared_with + }) + } else { + Err(Error::msg("Invalid silent payment address")) + } + } else { + Ok(Self { + secret, + shared_with: None + }) + } + } +} pub fn create_transaction_for_address_with_shared_secret( sp_address: SilentPaymentAddress, message: String, -) -> Result<(Transaction, SharedPoint)> { +) -> Result<(Transaction, SharedSecret)> { let connected_users = lock_connected_users()?; let (_, wallets) = connected_users @@ -34,6 +101,8 @@ pub fn create_transaction_for_address_with_shared_secret( .last() .ok_or(Error::msg("Unknown sender"))?; + debug!("Got user wallets"); + let sp_wallet = if sp_address.is_testnet() { &wallets.recover } else { @@ -77,11 +146,38 @@ pub fn create_transaction_for_address_with_shared_secret( let mut new_psbt = sp_wallet .get_client() - .create_new_psbt(inputs, vec![recipient], None)?; + .create_new_psbt(inputs, vec![recipient], Some(message.as_bytes()))?; log::debug!("Created psbt: {}", new_psbt); SpClient::set_fees(&mut new_psbt, Amount::from_sat(1000), sp_address.into())?; - let partial_secret = sp_wallet.get_client().get_partial_secret_from_psbt(&new_psbt)?; - sp_wallet.get_client().fill_sp_outputs(&mut new_psbt, partial_secret)?; + + let partial_secret = sp_wallet + .get_client() + .get_partial_secret_from_psbt(&new_psbt)?; + + // This wouldn't work with many recipients in the same transaction + // each address (or more precisely each scan public key) would have its own point + let shared_point = shared_secret_point(&sp_address.get_scan_key(), &partial_secret); + + // The shared_point *must* be hashed to produce a proper ecdh secret + let mut eng = sha256::HashEngine::default(); + eng.write_all(&shared_point); + let shared_secret = sha256::Hash::from_engine(eng); + + // encrypt the message with the new shared_secret + let message_encryption = Aes256Encryption::import_key( + Purpose::Arbitrary, + message.into_bytes(), + shared_secret.to_byte_array(), + Aes256Gcm::generate_nonce(&mut rand::thread_rng()).into(), + )?; + + let cipher = message_encryption.encrypt_with_aes_key()?; + + sp_client::spclient::SpClient::replace_op_return_with(&mut new_psbt, &cipher)?; + + sp_wallet + .get_client() + .fill_sp_outputs(&mut new_psbt, partial_secret)?; log::debug!("Definitive psbt: {}", new_psbt); let mut aux_rand = [0u8; 32]; rand::thread_rng().fill(&mut aux_rand); @@ -91,17 +187,24 @@ pub fn create_transaction_for_address_with_shared_secret( let final_tx = signed.extract_tx()?; - // This should not be directly used without hashing - let shared_point = shared_secret_point(&sp_address.get_scan_key(), &partial_secret); - - Ok((final_tx, shared_point)) + Ok((final_tx, SharedSecret { + secret: shared_secret.to_byte_array(), + shared_with: Some(sp_address.into()) + })) } +// This need to go pub fn check_transaction( tx: &Transaction, blockheight: u32, tweak_data: PublicKey, ) -> Result<String> { + // first check that we haven't scanned this transaction yet + if let Some((txid, _)) = lock_scanned_transactions()?.0.get_key_value(&tx.txid()) { + let err_msg = format!("Already scanned tx {}", txid); + return Err(Error::msg(err_msg)); + } + let connected_users = lock_connected_users()?; let txid = tx.txid().to_string(); diff --git a/src/services.ts b/src/services.ts index 56d26a2..5a3344e 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,4 +1,4 @@ -import { createUserReturn, User, Process, createNotificationTransactionReturn, parse_network_msg, outputs_list, parseNetworkMsgReturn, FaucetMessage, AnkFlag } from '../dist/pkg/sdk_client'; +import { createUserReturn, User, Process, createNotificationTransactionReturn, parse_network_msg, outputs_list, parseNetworkMsgReturn, FaucetMessage, AnkFlag, NewTxMessage } from '../dist/pkg/sdk_client'; import IndexedDB from './database' import { WebSocketClient } from './websockets'; @@ -86,7 +86,10 @@ class Services { const message = messageElement.value; const services = await Services.getInstance(); - let notificationInfo = services.notify_address_for_message(recipientSpAddress, message); + let notificationInfo = await services.notify_address_for_message(recipientSpAddress, message); + if (notificationInfo) { + notificationInfo.transaction + } console.log(notificationInfo); } @@ -751,6 +754,10 @@ class Services { public async notify_address_for_message(sp_address: string, message: string): Promise<createNotificationTransactionReturn | null> { const services = await Services.getInstance(); + const connection = await services.pickWebsocketConnectionRandom(); + if (!connection) { + return null; + } let user: User; try { let possibleUser = await services.getUserInfo(); @@ -766,9 +773,15 @@ class Services { try { let notificationInfo: createNotificationTransactionReturn = services.sdkClient.create_notification_transaction(user, sp_address, message); + const flag: AnkFlag = "NewTx"; + const newTxMsg: NewTxMessage = { + 'transaction': notificationInfo.transaction, + 'tweak_data': null + } + connection.sendMessage(flag, JSON.stringify(newTxMsg)); return notificationInfo; - } catch { - console.error("Failed to create notification transaction for user", user); + } catch (error) { + console.error("Failed to create notification transaction:", error); return null } } From 26bf0c08652a2f92b91a618370e498fd13838361 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Mon, 22 Apr 2024 11:52:57 +0200 Subject: [PATCH 66/90] ws mono user --- crates/sp_client/src/api.rs | 45 ++++--- crates/sp_client/src/silentpayments.rs | 43 +++---- crates/sp_client/src/user.rs | 165 ++++++++++++++++--------- 3 files changed, 146 insertions(+), 107 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 14c43cc..9d0d59c 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -33,7 +33,7 @@ use crate::images; use crate::silentpayments::{ check_transaction, create_transaction_for_address_with_shared_secret, ScannedTransaction, }; -use crate::user::{lock_connected_users, User, UserWallets, CONNECTED_USERS}; +use crate::user::{lock_connected_user, User, UserWallets, CONNECTED_USER}; use crate::process::Process; @@ -141,9 +141,20 @@ pub fn generate_sp_wallet( } #[wasm_bindgen] -pub fn get_receiving_address(pre_id: String) -> ApiResult<String> { - if let Some(my_wallets) = lock_connected_users()?.get(&pre_id) { - Ok(my_wallets.recover.get_client().get_receiving_address()) +pub fn get_recover_address() -> ApiResult<String> { + if let Ok(my_wallets) = lock_connected_user() { + Ok(my_wallets.try_get_recover()?.get_client().get_receiving_address()) + } else { + Err(ApiError { + message: "Unknown user pre_id".to_owned(), + }) + } +} + +#[wasm_bindgen] +pub fn get_main_address() -> ApiResult<String> { + if let Ok(my_wallets) = lock_connected_user() { + Ok(my_wallets.try_get_main()?.get_client().get_receiving_address()) } else { Err(ApiError { message: "Unknown user pre_id".to_owned(), @@ -168,7 +179,7 @@ pub fn create_user( let user_wallets = UserWallets::new( Some(sp_wallet_main), - sp_wallet_recover, + Some(sp_wallet_recover), Some(sp_wallet_revoke), ); @@ -176,7 +187,9 @@ pub fn create_user( let outputs = user_wallets.get_all_outputs(); - lock_connected_users()?.insert(user.pre_id.clone(), user_wallets); + // Setting CONNECTED_USER to user + let mut connected_user = lock_connected_user()?; + *connected_user = user_wallets; let generate_user = createUserReturn { user, @@ -359,24 +372,22 @@ pub fn parse_network_msg(raw: String) -> ApiResult<parseNetworkMsgReturn> { #[wasm_bindgen] pub fn get_outpoints_for_user() -> ApiResult<outputs_list> { - let connected_users = lock_connected_users()?; - let (_, user) = connected_users.iter().last().ok_or(ApiError { - message: "Can't find user".to_owned(), - })?; - Ok(outputs_list(user.get_all_outputs())) + let connected_user = lock_connected_user()?; + if connected_user.is_not_empty() { + Ok(outputs_list(connected_user.get_all_outputs())) + } else { + Err(ApiError { message: "No user logged in".to_owned() }) + } } #[wasm_bindgen] pub fn is_tx_owned_by_user(pre_id: String, tx: String) -> ApiResult<bool> { let transaction = deserialize::<Transaction>(&Vec::from_hex(&tx)?)?; let txid = transaction.txid(); - let connected_users = lock_connected_users()?; - let user = connected_users.get(&pre_id).ok_or(ApiError { - message: "Can't find user".to_owned(), - })?; + let connected_user = lock_connected_user()?; - if let Some(_) = user - .recover + if let Some(_) = connected_user + .try_get_recover()? .get_outputs() .to_outpoints_list() .iter() diff --git a/crates/sp_client/src/silentpayments.rs b/crates/sp_client/src/silentpayments.rs index 1b5d35e..aee9616 100644 --- a/crates/sp_client/src/silentpayments.rs +++ b/crates/sp_client/src/silentpayments.rs @@ -27,7 +27,7 @@ use sp_client::{ }; use tsify::Tsify; -use crate::user::{lock_connected_users, CONNECTED_USERS}; +use crate::user::{lock_connected_user, CONNECTED_USER}; use crate::MutexExt; #[derive(Debug, Serialize, Deserialize, Tsify)] @@ -94,26 +94,19 @@ pub fn create_transaction_for_address_with_shared_secret( sp_address: SilentPaymentAddress, message: String, ) -> Result<(Transaction, SharedSecret)> { - let connected_users = lock_connected_users()?; - - let (_, wallets) = connected_users - .iter() - .last() - .ok_or(Error::msg("Unknown sender"))?; - - debug!("Got user wallets"); + let connected_user = lock_connected_user()?; let sp_wallet = if sp_address.is_testnet() { - &wallets.recover + connected_user.try_get_recover()? } else { - if let Some(main) = &wallets.main { + if let Ok(main) = connected_user.try_get_main() { main } else { return Err(Error::msg("Can't spend on mainnet")); } }; - let available_outpoints = wallets.recover.get_outputs().to_spendable_list(); + let available_outpoints = sp_wallet.get_outputs().to_spendable_list(); // Here we need to add more heuristics about which outpoint we spend // For now let's keep it simple @@ -205,27 +198,19 @@ pub fn check_transaction( return Err(Error::msg(err_msg)); } - let connected_users = lock_connected_users()?; + let mut connected_user = lock_connected_user()?; let txid = tx.txid().to_string(); - // Check the transaction for all connected users - for (pre_id, keys) in connected_users.clone() { - let mut recover = keys.recover; - if recover.update_wallet_with_transaction(tx, blockheight, tweak_data)? > 0 { - return Ok(txid); - } + if connected_user.try_get_mut_recover()?.update_wallet_with_transaction(tx, blockheight, tweak_data)? > 0 { + return Ok(txid); + } - if let Some(mut main) = keys.main { - if main.update_wallet_with_transaction(tx, blockheight, tweak_data)? > 0 { - return Ok(txid); - } - } + if connected_user.try_get_mut_main()?.update_wallet_with_transaction(tx, blockheight, tweak_data)? > 0 { + return Ok(txid); + } - if let Some(mut revoke) = keys.revoke { - if revoke.update_wallet_with_transaction(tx, blockheight, tweak_data)? > 0 { - return Ok(txid); - } - } + if connected_user.try_get_mut_revoke()?.update_wallet_with_transaction(tx, blockheight, tweak_data)? > 0 { + return Ok(txid); } return Err(Error::msg("No new outputs found")); diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index 30a0119..37de212 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -36,24 +36,23 @@ type PreId = String; const MANAGERS_NUMBER: u8 = 10; const QUORUM_SHARD: f32 = 0.8; -type UsersMap = HashMap<PreId, UserWallets>; -pub static CONNECTED_USERS: OnceLock<Mutex<UsersMap>> = OnceLock::new(); +pub static CONNECTED_USER: OnceLock<Mutex<UserWallets>> = OnceLock::new(); -pub fn lock_connected_users() -> Result<MutexGuard<'static, UsersMap>> { - CONNECTED_USERS - .get_or_init(|| Mutex::new(HashMap::new())) +pub fn lock_connected_user() -> Result<MutexGuard<'static, UserWallets>> { + CONNECTED_USER + .get_or_init(|| Mutex::new(UserWallets::default())) .lock_anyhow() } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct UserWallets { - pub main: Option<SpWallet>, - pub recover: SpWallet, - pub revoke: Option<SpWallet>, + main: Option<SpWallet>, + recover: Option<SpWallet>, + revoke: Option<SpWallet>, } impl UserWallets { - pub fn new(main: Option<SpWallet>, recover: SpWallet, revoke: Option<SpWallet>) -> Self { + pub fn new(main: Option<SpWallet>, recover: Option<SpWallet>, revoke: Option<SpWallet>) -> Self { Self { main, recover, @@ -61,8 +60,56 @@ impl UserWallets { } } - pub fn try_get_revoke(&self) -> Option<&SpWallet> { - self.revoke.as_ref() + pub fn try_get_revoke(&self) -> Result<&SpWallet> { + if let Some(revoke) = &self.revoke { + Ok(revoke) + } else { + Err(Error::msg("No revoke wallet available")) + } + } + + pub fn try_get_recover(&self) -> Result<&SpWallet> { + if let Some(recover) = &self.recover { + Ok(recover) + } else { + Err(Error::msg("No recover wallet available")) + } + } + + pub fn try_get_main(&self) -> Result<&SpWallet> { + if let Some(main) = &self.main { + Ok(main) + } else { + Err(Error::msg("No main wallet available")) + } + } + + pub fn try_get_mut_revoke(&mut self) -> Result<&mut SpWallet> { + if let Some(revoke) = &mut self.revoke { + Ok(revoke) + } else { + Err(Error::msg("No revoke wallet available")) + } + } + + pub fn try_get_mut_recover(&mut self) -> Result<&mut SpWallet> { + if let Some(recover) = &mut self.recover { + Ok(recover) + } else { + Err(Error::msg("No recover wallet available")) + } + } + + pub fn try_get_mut_main(&mut self) -> Result<&mut SpWallet> { + if let Some(main) = &mut self.main { + Ok(main) + } else { + Err(Error::msg("No main wallet available")) + } + } + + pub(crate) fn is_not_empty(&self) -> bool { + self.get_all_outputs().len() > 0 } pub(crate) fn get_all_outputs(&self) -> Vec<OutputList> { @@ -73,7 +120,9 @@ impl UserWallets { if let Some(revoke) = &self.revoke { res.push(revoke.get_outputs().clone()); } - res.push(self.recover.get_outputs().clone()); + if let Some(recover) = &self.recover { + res.push(recover.get_outputs().clone()); + } res } @@ -93,22 +142,24 @@ pub struct User { impl User { pub fn new(user_wallets: UserWallets, user_password: String, process: String) -> Result<Self> { + // if we are already logged in, abort + if lock_connected_user()?.is_not_empty() { + return Err(Error::msg("User already logged in")); + } + let mut rng = thread_rng(); // image revoke // We just take the 2 revoke keys let mut revoke_data = Vec::with_capacity(64); - if let Some(revoke) = user_wallets.try_get_revoke() { - revoke_data.extend_from_slice(revoke.get_client().get_scan_key().as_ref()); - revoke_data.extend_from_slice(revoke.get_client().try_get_secret_spend_key()?.as_ref()); - } else { - return Err(Error::msg("No revoke wallet available")); - } + let revoke = user_wallets.try_get_revoke()?; + revoke_data.extend_from_slice(revoke.get_client().get_scan_key().as_ref()); + revoke_data.extend_from_slice(revoke.get_client().try_get_secret_spend_key()?.as_ref()); // Take the 2 recover keys // split recover spend key let recover_spend_key = user_wallets - .recover + .try_get_recover()? .get_client() .try_get_secret_spend_key()? .clone(); @@ -186,7 +237,7 @@ impl User { let scan_key_encryption = Aes256Encryption::import_key( Purpose::ThirtyTwoBytes, user_wallets - .recover + .try_get_recover()? .get_client() .get_scan_key() .secret_bytes() @@ -200,6 +251,8 @@ impl User { recover_data.extend_from_slice(&cipher_scan_key); + let all_outputs = user_wallets.get_all_outputs(); + Ok(User { pre_id: pre_id.to_string(), processes: vec![process], @@ -207,10 +260,19 @@ impl User { recover_data, revoke_data: Some(revoke_data), shares, - outputs: user_wallets.get_all_outputs(), + outputs: all_outputs, }) } + pub fn logout() -> Result<()> { + if let Ok(mut user) = lock_connected_user() { + *user = UserWallets::default(); + Ok(()) + } else { + Err(Error::msg("Failed to lock CONNECTED_USER")) + } + } + pub fn login( pre_id: PreId, user_password: String, @@ -218,6 +280,11 @@ impl User { shares: &[Vec<u8>], outputs: &[OutputList], ) -> Result<()> { + // if we are already logged in, abort + if lock_connected_user()?.is_not_empty() { + return Err(Error::msg("User already logged in")); + } + let mut retrieved_spend_key = [0u8; 32]; let mut retrieved_scan_key = [0u8; 32]; let mut entropy1 = [0u8; 32]; @@ -241,21 +308,6 @@ impl User { return Err(Error::msg("pre_id and recover_data don't match")); } - // If we already have loaded a user with this pre_id, abort - if let Some(current_users) = CONNECTED_USERS.get() { - if current_users - .to_owned() - .lock() - .unwrap() - .contains_key(&pre_id) - { - return Err(Error::msg(format!( - "User with pre_id {} already logged in", - pre_id - ))); - } - } - retrieved_spend_key[..16].copy_from_slice(&Self::recover_part1( &user_password, &entropy1, @@ -290,26 +342,12 @@ impl User { let recover_wallet = SpWallet::new(recover_client, recover_outputs)?; - // Adding user to CONNECTED_USERS - if let Some(current_users) = CONNECTED_USERS.get() { - let mut lock = current_users.to_owned().lock().unwrap(); - if lock.contains_key(&pre_id) { - return Err(Error::msg(format!( - "User with pre_id {} already exists", - pre_id - ))); - } else { - lock.insert(pre_id.clone(), UserWallets::new(None, recover_wallet, None)); - } + let user_wallets = UserWallets::new(None, Some(recover_wallet), None); + + if let Ok(mut user) = lock_connected_user() { + *user = user_wallets; } else { - let mut user_map = HashMap::new(); - user_map.insert(pre_id, UserWallets::new(None, recover_wallet, None)); - let new_value = Mutex::new(user_map); - if let Err(error) = CONNECTED_USERS.set(new_value) { - return Err(Error::msg( - "Failed to set the CONNECTED_USERS static variable", - )); - } + return Err(Error::msg("Failed to lock CONNECTED_USER")); } Ok(()) @@ -456,21 +494,26 @@ mod tests { .unwrap(); let user_wallets = UserWallets::new( Some(SpWallet::new(sp_main, None).unwrap()), - SpWallet::new(sp_recover, None).unwrap(), + Some(SpWallet::new(sp_recover, None).unwrap()), Some(SpWallet::new(sp_revoke, None).unwrap()), ); user_wallets } - // Test 1: Create User #[test] fn test_successful_creation() { let user_wallets = helper_create_user_wallets(); let result = User::new(user_wallets, USER_PASSWORD.to_owned(), PROCESS.to_owned()); assert!(result.is_ok()); - let user = result.unwrap(); + } + + #[test] + fn test_logout() { + let res = User::logout(); + + assert!(res.is_ok()); } #[test] @@ -493,9 +536,9 @@ mod tests { assert!(res.is_ok()); - let connected = CONNECTED_USERS.get().unwrap().lock().unwrap(); + let connected = lock_connected_user().unwrap(); - let recover = &connected.get(&user.pre_id).unwrap().recover; + let recover = connected.try_get_recover().unwrap(); assert!( format!( From fcdfeeaecca6c71bf1ff6afa58b702148a64f6e2 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Mon, 22 Apr 2024 17:17:12 +0200 Subject: [PATCH 67/90] WIP --- crates/sp_client/Cargo.toml | 4 +- crates/sp_client/src/api.rs | 192 +++++++++++++++++++--- crates/sp_client/src/lib.rs | 19 ++- crates/sp_client/src/silentpayments.rs | 217 ------------------------- crates/sp_client/src/user.rs | 6 +- src/index.ts | 2 +- src/services.ts | 74 ++++++++- src/websockets.ts | 1 - 8 files changed, 263 insertions(+), 252 deletions(-) delete mode 100644 crates/sp_client/src/silentpayments.rs diff --git a/crates/sp_client/Cargo.toml b/crates/sp_client/Cargo.toml index 2155567..f64543a 100644 --- a/crates/sp_client/Cargo.toml +++ b/crates/sp_client/Cargo.toml @@ -8,6 +8,7 @@ name = "sdk_client" crate-type = ["cdylib"] [dependencies] +# sp_client= { path = "../../../sp-client" } sp_client= { git = "https://github.com/Sosthene00/sp-client", branch = "sp_client" } anyhow = "1.0" serde = { version = "1.0.188", features = ["derive"] } @@ -18,7 +19,8 @@ wasm-logger = "0.2.0" rand = "0.8.5" log = "0.4.6" tsify = { git = "https://github.com/Sosthene00/tsify", branch = "next" } -sdk_common = { git = "https://git.4nkweb.com/4nk/sdk_common.git", branch = "demo" } +sdk_common = { path = "../../../sdk_common" } +#sdk_common = { git = "https://git.4nkweb.com/4nk/sdk_common.git", branch = "demo" } shamir = { git = "https://github.com/Sosthene00/shamir", branch = "master" } img-parts = "0.3.0" diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 9d0d59c..73bedb8 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -2,20 +2,22 @@ use std::any::Any; use std::collections::HashMap; use std::io::Write; use std::str::FromStr; +use std::string::FromUtf8Error; use std::sync::{Mutex, OnceLock, PoisonError}; use log::debug; -use rand::Rng; +use rand::{Fill, Rng}; use anyhow::Error as AnyhowError; -use sdk_common::crypto::AnkSharedSecret; +use sdk_common::crypto::{ + AeadCore, Aes256Decryption, Aes256Encryption, Aes256Gcm, AnkSharedSecret, KeyInit, Purpose, +}; use serde_json::Error as SerdeJsonError; use shamir::SecretData; use sp_client::bitcoin::consensus::{deserialize, serialize}; use sp_client::bitcoin::hex::{parse, DisplayHex, FromHex, HexToBytesError}; -use sp_client::bitcoin::secp256k1::ecdh::SharedSecret; use sp_client::bitcoin::secp256k1::{PublicKey, SecretKey}; -use sp_client::bitcoin::{OutPoint, Transaction, Txid}; +use sp_client::bitcoin::{Amount, OutPoint, Transaction, Txid}; use sp_client::silentpayments::Error as SpError; use serde::{Deserialize, Serialize}; @@ -25,15 +27,15 @@ use wasm_bindgen::convert::FromWasmAbi; use wasm_bindgen::prelude::*; use sdk_common::network::{AnkFlag, AnkNetworkMsg, NewTxMessage}; +use sdk_common::silentpayments::{ + check_transaction, create_transaction_for_address_with_shared_secret, +}; use sp_client::spclient::{derive_keys_from_seed, OutputList, OwnedOutput, SpClient}; use sp_client::spclient::{SpWallet, SpendKey}; -use crate::images; -use crate::silentpayments::{ - check_transaction, create_transaction_for_address_with_shared_secret, ScannedTransaction, -}; use crate::user::{lock_connected_user, User, UserWallets, CONNECTED_USER}; +use crate::{images, lock_scanned_transactions, Txid2Secrets}; use crate::process::Process; @@ -94,6 +96,14 @@ impl From<sp_client::bitcoin::consensus::encode::Error> for ApiError { } } +impl From<FromUtf8Error> for ApiError { + fn from(value: FromUtf8Error) -> Self { + ApiError { + message: value.to_string(), + } + } +} + impl Into<JsValue> for ApiError { fn into(self) -> JsValue { JsValue::from_str(&self.message) @@ -143,7 +153,10 @@ pub fn generate_sp_wallet( #[wasm_bindgen] pub fn get_recover_address() -> ApiResult<String> { if let Ok(my_wallets) = lock_connected_user() { - Ok(my_wallets.try_get_recover()?.get_client().get_receiving_address()) + Ok(my_wallets + .try_get_recover()? + .get_client() + .get_receiving_address()) } else { Err(ApiError { message: "Unknown user pre_id".to_owned(), @@ -154,7 +167,10 @@ pub fn get_recover_address() -> ApiResult<String> { #[wasm_bindgen] pub fn get_main_address() -> ApiResult<String> { if let Ok(my_wallets) = lock_connected_user() { - Ok(my_wallets.try_get_main()?.get_client().get_receiving_address()) + Ok(my_wallets + .try_get_main()? + .get_client() + .get_receiving_address()) } else { Err(ApiError { message: "Unknown user pre_id".to_owned(), @@ -322,9 +338,28 @@ pub fn check_transaction_for_silent_payments( let tx = deserialize::<Transaction>(&Vec::from_hex(&tx_hex)?)?; let tweak_data = PublicKey::from_str(&tweak_data_hex)?; - let txid = check_transaction(&tx, blockheight, tweak_data)?; + let mut connected_user = lock_connected_user()?; + if let Ok(recover) = connected_user.try_get_mut_recover() { + if let Ok(txid) = check_transaction(&tx, recover, blockheight, tweak_data) { + return Ok(txid); + } + } - Ok(txid) + if let Ok(main) = connected_user.try_get_mut_main() { + if let Ok(txid) = check_transaction(&tx, main, blockheight, tweak_data) { + return Ok(txid); + } + } + + if let Ok(revoke) = connected_user.try_get_mut_revoke() { + if let Ok(txid) = check_transaction(&tx, revoke, blockheight, tweak_data) { + return Ok(txid); + } + } + + Err(ApiError { + message: "No output found".to_owned(), + }) } #[derive(Tsify, Serialize, Deserialize)] @@ -341,14 +376,16 @@ pub fn parse_network_msg(raw: String) -> ApiResult<parseNetworkMsgReturn> { match ank_msg.flag { AnkFlag::NewTx => { let tx_message = serde_json::from_str::<NewTxMessage>(&ank_msg.content)?; - let tx = deserialize::<Transaction>(&Vec::from_hex(&tx_message.transaction)?)?; if tx_message.tweak_data.is_none() { return Err(ApiError { message: "Missing tweak_data".to_owned(), }); } - let partial_tweak = PublicKey::from_str(&tx_message.tweak_data.unwrap())?; - let txid = check_transaction(&tx, 0, partial_tweak)?; + let txid = check_transaction_for_silent_payments( + tx_message.transaction, + 0, + tx_message.tweak_data.unwrap(), + )?; return Ok(parseNetworkMsgReturn { topic: AnkFlag::NewTx.as_str().to_owned(), message: txid, @@ -376,7 +413,27 @@ pub fn get_outpoints_for_user() -> ApiResult<outputs_list> { if connected_user.is_not_empty() { Ok(outputs_list(connected_user.get_all_outputs())) } else { - Err(ApiError { message: "No user logged in".to_owned() }) + Err(ApiError { + message: "No user logged in".to_owned(), + }) + } +} + +#[wasm_bindgen] +pub fn get_available_amount_for_user(recover: bool) -> ApiResult<u64> { + let connected_user = lock_connected_user()?; + if recover { + if let Ok(recover_wallet) = connected_user.try_get_recover() { + Ok(recover_wallet.get_outputs().get_balance().to_sat()) + } else { + Err(ApiError { + message: "User doesn't have recover wallet available".to_owned(), + }) + } + } else { + Err(ApiError { + message: "No user logged in".to_owned(), + }) } } @@ -403,28 +460,117 @@ pub fn is_tx_owned_by_user(pre_id: String, tx: String) -> ApiResult<bool> { #[tsify(into_wasm_abi, from_wasm_abi)] #[allow(non_camel_case_types)] pub struct createNotificationTransactionReturn { + pub txid: String, pub transaction: String, - pub transaction2secret: ScannedTransaction, + pub address2secret: HashMap<String, AnkSharedSecret>, } #[wasm_bindgen] pub fn create_notification_transaction( recipient: String, message: String, + fee_rate: u32, ) -> ApiResult<createNotificationTransactionReturn> { let sp_address: SilentPaymentAddress = recipient.try_into()?; - let (transaction, shared_secret) = - create_transaction_for_address_with_shared_secret(sp_address, message)?; + let connected_user = lock_connected_user()?; + let sp_wallet: &SpWallet; + if sp_address.is_testnet() { + sp_wallet = connected_user.try_get_recover()?; + } else { + sp_wallet = connected_user.try_get_main()?; + } + + let (transaction, shared_secret) = create_transaction_for_address_with_shared_secret( + sp_address, + sp_wallet, + message, + Amount::from_sat(fee_rate.into()), + )?; + + let mut address2secret: Vec<(String, AnkSharedSecret)> = vec![]; + address2secret.push((sp_address.into(), shared_secret)); // update our cache - - let mut transaction2secret = ScannedTransaction::new(); - transaction2secret.get_mut().insert(transaction.txid(), vec![shared_secret]); + lock_scanned_transactions()? + .insert(transaction.txid(), address2secret.clone()); Ok(createNotificationTransactionReturn { + txid: transaction.txid().to_string(), transaction: serialize(&transaction).to_lower_hex_string(), - transaction2secret, + address2secret: address2secret.into_iter().collect() }) } + +#[derive(Tsify, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[allow(non_camel_case_types)] +pub struct encryptWithNewKeyResult { + pub cipher: String, + pub key: String, +} + +#[wasm_bindgen] +pub fn encrypt_with_key(plaintext: String, key: String) -> ApiResult<String> { + let nonce = Aes256Gcm::generate_nonce(&mut rand::thread_rng()); + + let mut aes_key = [0u8;32]; + aes_key.copy_from_slice(&Vec::from_hex(&key)?); + + // encrypt + let aes_enc = Aes256Encryption::import_key( + Purpose::Arbitrary, + plaintext.into_bytes(), + aes_key, + nonce.into(), + )?; + + let cipher = aes_enc.encrypt_with_aes_key()?; + Ok(String::from_utf8(cipher)?) +} + +#[wasm_bindgen] +pub fn encrypt_with_new_key(plaintext: String) -> ApiResult<encryptWithNewKeyResult> { + let mut rng = rand::thread_rng(); + + // generate new key + let aes_key = Aes256Gcm::generate_key(&mut rng); + let nonce = Aes256Gcm::generate_nonce(&mut rng); + + // encrypt + let aes_enc = Aes256Encryption::import_key( + Purpose::Arbitrary, + plaintext.into_bytes(), + aes_key.into(), + nonce.into(), + )?; + + let cipher = aes_enc.encrypt_with_aes_key()?; + + Ok(encryptWithNewKeyResult { + cipher: cipher.to_lower_hex_string(), + key: aes_key.to_lower_hex_string(), + }) +} + +#[wasm_bindgen] +pub fn try_decrypt_with_key( + cipher: String, + key: String, +) -> ApiResult<String> { + let key_bin = Vec::from_hex(&key)?; + if key_bin.len() != 32 { + return Err(ApiError { message: "key of invalid lenght".to_owned() }); + } + let mut aes_key = [0u8;32]; + aes_key.copy_from_slice(&Vec::from_hex(&key)?); + let aes_dec = Aes256Decryption::new( + Purpose::Arbitrary, + Vec::from_hex(&cipher)?, + aes_key + )?; + + let plain = String::from_utf8(aes_dec.decrypt_with_key()?)?; + Ok(plain) +} diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index c0056a6..8d7155c 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -1,16 +1,31 @@ #![allow(warnings)] use anyhow::Error; +use sdk_common::crypto::AnkSharedSecret; +use serde::{Deserialize, Serialize}; +use sp_client::bitcoin::Txid; +use sp_client::silentpayments::sending::SilentPaymentAddress; +use std::collections::HashMap; use std::fmt::Debug; -use std::sync::{Mutex, MutexGuard}; +use std::sync::{Mutex, MutexGuard, OnceLock}; +use tsify::Tsify; mod Prd_list; pub mod api; mod images; mod peers; mod process; -mod silentpayments; mod user; +pub type Txid2Secrets = HashMap<Txid, Vec<(String, AnkSharedSecret)>>; + +pub static TRANSACTIONCACHE: OnceLock<Mutex<Txid2Secrets>> = OnceLock::new(); + +pub fn lock_scanned_transactions() -> Result<MutexGuard<'static, Txid2Secrets>, Error> { + TRANSACTIONCACHE + .get_or_init(|| Mutex::new(Txid2Secrets::new())) + .lock_anyhow() +} + pub(crate) trait MutexExt<T> { fn lock_anyhow(&self) -> Result<MutexGuard<T>, Error>; } diff --git a/crates/sp_client/src/silentpayments.rs b/crates/sp_client/src/silentpayments.rs deleted file mode 100644 index aee9616..0000000 --- a/crates/sp_client/src/silentpayments.rs +++ /dev/null @@ -1,217 +0,0 @@ -// This file should move to common - -use std::collections::{HashMap, HashSet}; -use std::io::Write; -use std::iter::Once; -use std::sync::{Mutex, MutexGuard, OnceLock}; - -use anyhow::{Error, Result}; - -use log::debug; -use rand::Rng; -use sdk_common::crypto::{Aes256Encryption, Aes256Gcm, AeadCore, Purpose}; -use serde::{Deserialize, Serialize}; -use sp_client::bitcoin::policy::DUST_RELAY_TX_FEE; -use sp_client::bitcoin::secp256k1::ecdh::shared_secret_point; -use sp_client::bitcoin::{block, Amount, OutPoint, Txid}; -use sp_client::silentpayments::sending::SilentPaymentAddress; -use sp_client::silentpayments::utils::receiving::calculate_shared_secret; -use sp_client::spclient::{OutputList, OwnedOutput, Recipient, SpClient, SpWallet}; -use sp_client::silentpayments::bitcoin_hashes::{sha256, Hash, HashEngine}; -use sp_client::{ - bitcoin::{ - secp256k1::{PublicKey, Scalar, XOnlyPublicKey}, - Transaction, - }, - silentpayments::receiving::Label, -}; -use tsify::Tsify; - -use crate::user::{lock_connected_user, CONNECTED_USER}; -use crate::MutexExt; - -#[derive(Debug, Serialize, Deserialize, Tsify)] -#[tsify(into_wasm_abi, from_wasm_abi)] -pub struct ScannedTransaction(HashMap<Txid, Vec<SharedSecret>>); - -impl ScannedTransaction { - pub fn new() -> Self { - Self(HashMap::new()) - } - - pub fn get_mut(&mut self) -> &mut HashMap<Txid, Vec<SharedSecret>> { - &mut self.0 - } -} - -pub static TRANSACTIONCACHE: OnceLock<Mutex<ScannedTransaction>> = OnceLock::new(); - -pub fn lock_scanned_transactions() -> Result<MutexGuard<'static, ScannedTransaction>> { - TRANSACTIONCACHE - .get_or_init(|| Mutex::new(ScannedTransaction::new())) - .lock_anyhow() -} - -type FoundOutputs = HashMap<Option<Label>, HashMap<XOnlyPublicKey, Scalar>>; - -#[derive(Debug)] -pub struct SharedPoint([u8; 64]); - -impl SharedPoint { - pub fn as_inner(&self) -> &[u8; 64] { - &self.0 - } -} - -#[derive(Debug, Serialize, Deserialize, Tsify)] -#[tsify(from_wasm_abi, into_wasm_abi)] -pub struct SharedSecret { - secret: [u8; 32], - shared_with: Option<String>, // SilentPaymentAddress -} - -impl SharedSecret { - pub fn new(secret: [u8;32], shared_with: Option<String>) -> Result<Self> { - if let Some(ref shared) = shared_with { - if let Ok(_) = SilentPaymentAddress::try_from(shared.as_str()) { - Ok(Self { - secret, - shared_with - }) - } else { - Err(Error::msg("Invalid silent payment address")) - } - } else { - Ok(Self { - secret, - shared_with: None - }) - } - } -} - -pub fn create_transaction_for_address_with_shared_secret( - sp_address: SilentPaymentAddress, - message: String, -) -> Result<(Transaction, SharedSecret)> { - let connected_user = lock_connected_user()?; - - let sp_wallet = if sp_address.is_testnet() { - connected_user.try_get_recover()? - } else { - if let Ok(main) = connected_user.try_get_main() { - main - } else { - return Err(Error::msg("Can't spend on mainnet")); - } - }; - - let available_outpoints = sp_wallet.get_outputs().to_spendable_list(); - - // Here we need to add more heuristics about which outpoint we spend - // For now let's keep it simple - - let mut inputs: HashMap<OutPoint, OwnedOutput> = HashMap::new(); - - let total_available = - available_outpoints - .into_iter() - .try_fold(Amount::from_sat(0), |acc, (outpoint, output)| { - let new_total = acc + output.amount; - inputs.insert(outpoint, output); - if new_total > Amount::from_sat(1000) { - Err(new_total) - } else { - Ok(new_total) - } - }); - - match total_available { - Err(total) => log::debug!("Spending {} outputs totaling {} sats", inputs.len(), total), - Ok(_) => return Err(Error::msg("Not enought fund available")), - } - - let recipient = Recipient { - address: sp_address.into(), - amount: Amount::from_sat(1000), - nb_outputs: 1, - }; - - let mut new_psbt = sp_wallet - .get_client() - .create_new_psbt(inputs, vec![recipient], Some(message.as_bytes()))?; - log::debug!("Created psbt: {}", new_psbt); - SpClient::set_fees(&mut new_psbt, Amount::from_sat(1000), sp_address.into())?; - - let partial_secret = sp_wallet - .get_client() - .get_partial_secret_from_psbt(&new_psbt)?; - - // This wouldn't work with many recipients in the same transaction - // each address (or more precisely each scan public key) would have its own point - let shared_point = shared_secret_point(&sp_address.get_scan_key(), &partial_secret); - - // The shared_point *must* be hashed to produce a proper ecdh secret - let mut eng = sha256::HashEngine::default(); - eng.write_all(&shared_point); - let shared_secret = sha256::Hash::from_engine(eng); - - // encrypt the message with the new shared_secret - let message_encryption = Aes256Encryption::import_key( - Purpose::Arbitrary, - message.into_bytes(), - shared_secret.to_byte_array(), - Aes256Gcm::generate_nonce(&mut rand::thread_rng()).into(), - )?; - - let cipher = message_encryption.encrypt_with_aes_key()?; - - sp_client::spclient::SpClient::replace_op_return_with(&mut new_psbt, &cipher)?; - - sp_wallet - .get_client() - .fill_sp_outputs(&mut new_psbt, partial_secret)?; - log::debug!("Definitive psbt: {}", new_psbt); - let mut aux_rand = [0u8; 32]; - rand::thread_rng().fill(&mut aux_rand); - let mut signed = sp_wallet.get_client().sign_psbt(new_psbt, &aux_rand)?; - log::debug!("signed psbt: {}", signed); - SpClient::finalize_psbt(&mut signed)?; - - let final_tx = signed.extract_tx()?; - - Ok((final_tx, SharedSecret { - secret: shared_secret.to_byte_array(), - shared_with: Some(sp_address.into()) - })) -} - -// This need to go -pub fn check_transaction( - tx: &Transaction, - blockheight: u32, - tweak_data: PublicKey, -) -> Result<String> { - // first check that we haven't scanned this transaction yet - if let Some((txid, _)) = lock_scanned_transactions()?.0.get_key_value(&tx.txid()) { - let err_msg = format!("Already scanned tx {}", txid); - return Err(Error::msg(err_msg)); - } - - let mut connected_user = lock_connected_user()?; - - let txid = tx.txid().to_string(); - if connected_user.try_get_mut_recover()?.update_wallet_with_transaction(tx, blockheight, tweak_data)? > 0 { - return Ok(txid); - } - - if connected_user.try_get_mut_main()?.update_wallet_with_transaction(tx, blockheight, tweak_data)? > 0 { - return Ok(txid); - } - - if connected_user.try_get_mut_revoke()?.update_wallet_with_transaction(tx, blockheight, tweak_data)? > 0 { - return Ok(txid); - } - - return Err(Error::msg("No new outputs found")); -} diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index 37de212..758c4f2 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -52,7 +52,11 @@ pub struct UserWallets { } impl UserWallets { - pub fn new(main: Option<SpWallet>, recover: Option<SpWallet>, revoke: Option<SpWallet>) -> Self { + pub fn new( + main: Option<SpWallet>, + recover: Option<SpWallet>, + revoke: Option<SpWallet>, + ) -> Self { Self { main, recover, diff --git a/src/index.ts b/src/index.ts index f0304ea..d379dd8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ import Services from './services'; import { WebSocketClient } from './websockets'; -const wsurl = "ws://192.168.1.44:8090"; +const wsurl = "ws://localhost:8090"; document.addEventListener('DOMContentLoaded', async () => { try { const services = await Services.getInstance(); diff --git a/src/services.ts b/src/services.ts index 5a3344e..802c089 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,4 +1,4 @@ -import { createUserReturn, User, Process, createNotificationTransactionReturn, parse_network_msg, outputs_list, parseNetworkMsgReturn, FaucetMessage, AnkFlag, NewTxMessage } from '../dist/pkg/sdk_client'; +import { createUserReturn, User, Process, createNotificationTransactionReturn, parse_network_msg, outputs_list, parseNetworkMsgReturn, FaucetMessage, AnkFlag, NewTxMessage, encryptWithNewKeyResult, AnkSharedSecret } from '../dist/pkg/sdk_client'; import IndexedDB from './database' import { WebSocketClient } from './websockets'; @@ -74,6 +74,26 @@ class Services { public async sendMessage(event: Event): Promise<void> { event.preventDefault(); + const services = await Services.getInstance(); + let availableAmt: number = 0; + + // check available amount + try { + availableAmt = await services.sdkClient.get_available_amount_for_user(true); + } catch (error) { + console.error('Failed to get available amount'); + return; + } + + if (availableAmt < 2000) { + try { + await services.obtainTokenWithFaucet(this.sp_address!); + } catch (error) { + console.error('Failed to obtain faucet token:', error); + return; + } + } + const spAddressElement = document.getElementById("sp_address") as HTMLInputElement; const messageElement = document.getElementById("message") as HTMLInputElement; @@ -84,11 +104,18 @@ class Services { const recipientSpAddress = spAddressElement.value; const message = messageElement.value; - const services = await Services.getInstance(); let notificationInfo = await services.notify_address_for_message(recipientSpAddress, message); if (notificationInfo) { - notificationInfo.transaction + console.info('Successfully sent notification transaction'); + // Save the secret to db + // encrypt the message(s) + services.encryptData(message, notificationInfo.address2secret); + // encrypt the key + + // add peers list + // add processes list + // send message (transaction in envelope) } console.log(notificationInfo); } @@ -151,7 +178,7 @@ class Services { } try { - this.sp_address = services.sdkClient.get_receiving_address(user.pre_id); + this.sp_address = services.sdkClient.get_recover_address(); if (this.sp_address) { console.info('Using sp_address:', this.sp_address); await services.obtainTokenWithFaucet(this.sp_address); @@ -196,12 +223,14 @@ class Services { const user = await services.getUserInfo(); if (user) { services.sdkClient.login_user(password, user.pre_id, user.recover_data, user.shares, user.outputs); - this.sp_address = services.sdkClient.get_receiving_address(user?.pre_id); + this.sp_address = services.sdkClient.get_recover_address(); } } catch (error) { console.error(error); } + console.info(this.sp_address); + // TODO: check blocks since last_scan and update outputs await services.displaySendMessage(); @@ -341,6 +370,7 @@ class Services { let user = await services.getUserInfo(); if (user) { user.outputs = latest_outputs; + // console.warn(user); await services.updateUser(user); } } catch (error) { @@ -772,7 +802,8 @@ class Services { } try { - let notificationInfo: createNotificationTransactionReturn = services.sdkClient.create_notification_transaction(user, sp_address, message); + const feeRate = 1000; + let notificationInfo: createNotificationTransactionReturn = services.sdkClient.create_notification_transaction(sp_address, message, feeRate); const flag: AnkFlag = "NewTx"; const newTxMsg: NewTxMessage = { 'transaction': notificationInfo.transaction, @@ -785,6 +816,37 @@ class Services { return null } } + + public async encryptData(data: string, sharedSecret: Record<string, AnkSharedSecret>): Promise<encryptWithNewKeyResult> { + const services = await Services.getInstance(); + let msg_cipher: encryptWithNewKeyResult; + try { + msg_cipher = services.sdkClient.encrypt_with_new_key(data); + } catch (error) { + throw error; + } + + let res = new Map<string, string>(); + for (const [recipient, secret] of Object.entries(sharedSecret)) { + try { + const key = secret.secret; + const encryptedKey = await services.sdkClient.encrypt_with_key(msg_cipher.key, key); + res.set(recipient, encryptedKey); + } catch (error) { + throw new Error(`Failed to encrypt key for recipient ${recipient}: ${error}`); + } + } +} + + public async decryptData(cipher: string, key: string): Promise<string> { + const services = await Services.getInstance(); + try { + let res = services.sdkClient.try_decrypt_with_key(cipher, key); + return res; + } catch (error) { + throw error; + } + } } export default Services; diff --git a/src/websockets.ts b/src/websockets.ts index c94b4af..c4fc134 100644 --- a/src/websockets.ts +++ b/src/websockets.ts @@ -22,7 +22,6 @@ class WebSocketClient { // Listen for messages this.ws.addEventListener('message', (event) => { const msgData = event.data; - console.log(msgData); (async () => { if (typeof(msgData) === 'string') { From e26ea1068d405ebb47d3744efca811f4abe5d704 Mon Sep 17 00:00:00 2001 From: Alex Silva <alex.pereiradasilva@atos.net> Date: Fri, 3 May 2024 13:02:11 +0200 Subject: [PATCH 68/90] Add create commit --- crates/sp_client/src/api.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 73bedb8..1b1b0a9 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -574,3 +574,11 @@ pub fn try_decrypt_with_key( let plain = String::from_utf8(aes_dec.decrypt_with_key()?)?; Ok(plain) } + +#[wasm_bindgen] +pub fn create_commitment(payload_to_hash: String) -> String{ + let mut engine = sha256::HashEngine::default(); + engine.write_all(&payload_to_hash.as_bytes()); + let hash = sha256::Hash::from_engine(engine); + String::from_utf8_lossy(hash.to_bytes()) +} From 46fded3791600bf014bb33144c2085a0d8654c0b Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Fri, 3 May 2024 13:52:39 +0200 Subject: [PATCH 69/90] bug fix --- crates/sp_client/src/user.rs | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index 758c4f2..5038554 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -363,12 +363,8 @@ impl User { engine.write_all(&entropy); let hash = sha256::Hash::from_engine(engine); - let aes_dec = Aes256Decryption::new( - Purpose::ThirtyTwoBytes, - ciphertext, - hash.to_byte_array().to_vec(), - None, - )?; + let aes_dec = + Aes256Decryption::new(Purpose::ThirtyTwoBytes, ciphertext, hash.to_byte_array())?; aes_dec.decrypt_with_key() } @@ -379,12 +375,7 @@ impl User { engine.write_all(&entropy); let hash = sha256::Hash::from_engine(engine); - let aes_dec = Aes256Decryption::new( - Purpose::Login, - ciphertext, - hash.to_byte_array().to_vec(), - None, - )?; + let aes_dec = Aes256Decryption::new(Purpose::Login, ciphertext, hash.to_byte_array())?; aes_dec.decrypt_with_key() } @@ -403,12 +394,7 @@ impl User { .ok_or_else(|| anyhow::Error::msg("Failed to retrieve the sharded secret"))?, )?; - let aes_dec = Aes256Decryption::new( - Purpose::Login, - part2_key_enc, - hash.to_byte_array().to_vec(), - None, - )?; + let aes_dec = Aes256Decryption::new(Purpose::Login, part2_key_enc, hash.to_byte_array())?; aes_dec.decrypt_with_key() } From f1c2f0e4ed68d244e4751c30c2009888e422ae69 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Fri, 3 May 2024 13:53:14 +0200 Subject: [PATCH 70/90] Decrypt unknown message --- crates/sp_client/src/api.rs | 68 ++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 1b1b0a9..e118698 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -398,6 +398,40 @@ pub fn parse_network_msg(raw: String) -> ApiResult<parseNetworkMsgReturn> { message: ank_msg.content.to_owned(), }) } + AnkFlag::Unknown => { + let transaction_cache = lock_scanned_transactions()?; + // try to decrypt the cipher with all available keys + let mut plaintext: String = "".to_owned(); + for (txid, secret_vec) in transaction_cache.iter() { + for (shared_with, ank_secret) in secret_vec.iter() { + let shared_secret = ank_secret.to_byte_array(); + if let Ok(msg_decrypt) = Aes256Decryption::new( + Purpose::Arbitrary, + ank_msg.content.as_bytes().to_vec(), + shared_secret, + ) { + if let Ok(plain) = msg_decrypt.decrypt_with_key() { + plaintext = String::from_utf8(plain)?; + break; + } + } + continue; + } + } + if plaintext.is_empty() { + // keep the message in cache, just in case + // return an error + return Err(ApiError { + message: "No key found".to_owned(), + }); + } else { + // return the plain text + return Ok(parseNetworkMsgReturn { + topic: AnkFlag::Unknown.as_str().to_owned(), + message: plaintext, + }); + } + } _ => unimplemented!(), } } else { @@ -493,13 +527,12 @@ pub fn create_notification_transaction( address2secret.push((sp_address.into(), shared_secret)); // update our cache - lock_scanned_transactions()? - .insert(transaction.txid(), address2secret.clone()); + lock_scanned_transactions()?.insert(transaction.txid(), address2secret.clone()); Ok(createNotificationTransactionReturn { txid: transaction.txid().to_string(), transaction: serialize(&transaction).to_lower_hex_string(), - address2secret: address2secret.into_iter().collect() + address2secret: address2secret.into_iter().collect(), }) } @@ -515,7 +548,7 @@ pub struct encryptWithNewKeyResult { pub fn encrypt_with_key(plaintext: String, key: String) -> ApiResult<String> { let nonce = Aes256Gcm::generate_nonce(&mut rand::thread_rng()); - let mut aes_key = [0u8;32]; + let mut aes_key = [0u8; 32]; aes_key.copy_from_slice(&Vec::from_hex(&key)?); // encrypt @@ -555,30 +588,25 @@ pub fn encrypt_with_new_key(plaintext: String) -> ApiResult<encryptWithNewKeyRes } #[wasm_bindgen] -pub fn try_decrypt_with_key( - cipher: String, - key: String, -) -> ApiResult<String> { +pub fn try_decrypt_with_key(cipher: String, key: String) -> ApiResult<String> { let key_bin = Vec::from_hex(&key)?; if key_bin.len() != 32 { - return Err(ApiError { message: "key of invalid lenght".to_owned() }); + return Err(ApiError { + message: "key of invalid lenght".to_owned(), + }); } - let mut aes_key = [0u8;32]; + let mut aes_key = [0u8; 32]; aes_key.copy_from_slice(&Vec::from_hex(&key)?); - let aes_dec = Aes256Decryption::new( - Purpose::Arbitrary, - Vec::from_hex(&cipher)?, - aes_key - )?; + let aes_dec = Aes256Decryption::new(Purpose::Arbitrary, Vec::from_hex(&cipher)?, aes_key)?; let plain = String::from_utf8(aes_dec.decrypt_with_key()?)?; Ok(plain) } #[wasm_bindgen] -pub fn create_commitment(payload_to_hash: String) -> String{ - let mut engine = sha256::HashEngine::default(); - engine.write_all(&payload_to_hash.as_bytes()); - let hash = sha256::Hash::from_engine(engine); - String::from_utf8_lossy(hash.to_bytes()) +pub fn create_commitment(payload_to_hash: String) -> String { + let mut engine = sha256::HashEngine::default(); + engine.write_all(&payload_to_hash.as_bytes()); + let hash = sha256::Hash::from_engine(engine); + hash.to_byte_array().to_lower_hex_string() } From 870fdc831f59abab0e7649e0795b0a0c854827a4 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Sat, 4 May 2024 01:18:05 +0200 Subject: [PATCH 71/90] Send and receive messages --- crates/sp_client/src/api.rs | 40 +++++++++++++++++----- src/services.ts | 68 ++++++++++++++++++++++++++----------- src/websockets.ts | 2 ++ 3 files changed, 83 insertions(+), 27 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index e118698..eb6b1aa 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -16,6 +16,7 @@ use serde_json::Error as SerdeJsonError; use shamir::SecretData; use sp_client::bitcoin::consensus::{deserialize, serialize}; use sp_client::bitcoin::hex::{parse, DisplayHex, FromHex, HexToBytesError}; +use sp_client::bitcoin::secp256k1::ecdh::shared_secret_point; use sp_client::bitcoin::secp256k1::{PublicKey, SecretKey}; use sp_client::bitcoin::{Amount, OutPoint, Transaction, Txid}; use sp_client::silentpayments::Error as SpError; @@ -336,27 +337,40 @@ pub fn check_transaction_for_silent_payments( tweak_data_hex: String, ) -> ApiResult<String> { let tx = deserialize::<Transaction>(&Vec::from_hex(&tx_hex)?)?; + // check that we don't already have scanned the tx + if lock_scanned_transactions()?.contains_key(&tx.txid()) { + return Err(ApiError { message: "Transaction already scanned".to_owned()}); + } + let tweak_data = PublicKey::from_str(&tweak_data_hex)?; let mut connected_user = lock_connected_user()?; if let Ok(recover) = connected_user.try_get_mut_recover() { if let Ok(txid) = check_transaction(&tx, recover, blockheight, tweak_data) { + let shared_point = shared_secret_point(&tweak_data, &recover.get_client().get_scan_key()); + lock_scanned_transactions()?.insert(tx.txid(), vec![("".to_owned(), AnkSharedSecret::new(shared_point, false))]); return Ok(txid); } } if let Ok(main) = connected_user.try_get_mut_main() { if let Ok(txid) = check_transaction(&tx, main, blockheight, tweak_data) { + let shared_point = shared_secret_point(&tweak_data, &main.get_client().get_scan_key()); + lock_scanned_transactions()?.insert(tx.txid(), vec![("".to_owned(), AnkSharedSecret::new(shared_point, false))]); return Ok(txid); } } if let Ok(revoke) = connected_user.try_get_mut_revoke() { if let Ok(txid) = check_transaction(&tx, revoke, blockheight, tweak_data) { + let shared_point = shared_secret_point(&tweak_data, &revoke.get_client().get_scan_key()); + lock_scanned_transactions()?.insert(tx.txid(), vec![("".to_owned(), AnkSharedSecret::new(shared_point, false))]); return Ok(txid); } } + // we still want to insert an empty entry in our cache to make sure we don't scan the transaction again + lock_scanned_transactions()?.insert(tx.txid(), vec![("".to_owned(), AnkSharedSecret::default())]); Err(ApiError { message: "No output found".to_owned(), }) @@ -399,23 +413,30 @@ pub fn parse_network_msg(raw: String) -> ApiResult<parseNetworkMsgReturn> { }) } AnkFlag::Unknown => { - let transaction_cache = lock_scanned_transactions()?; // try to decrypt the cipher with all available keys let mut plaintext: String = "".to_owned(); - for (txid, secret_vec) in transaction_cache.iter() { + for (txid, secret_vec) in lock_scanned_transactions()?.iter() { for (shared_with, ank_secret) in secret_vec.iter() { + if *ank_secret == AnkSharedSecret::default() { + continue; + } let shared_secret = ank_secret.to_byte_array(); if let Ok(msg_decrypt) = Aes256Decryption::new( Purpose::Arbitrary, - ank_msg.content.as_bytes().to_vec(), + Vec::from_hex(&ank_msg.content.trim_matches('\"'))?, shared_secret, ) { - if let Ok(plain) = msg_decrypt.decrypt_with_key() { - plaintext = String::from_utf8(plain)?; - break; + match msg_decrypt.decrypt_with_key() { + Ok(plain) => { + plaintext = String::from_utf8(plain)?; + break; + }, + Err(e) => { + debug!("{}", e); + debug!("Failed to decrypt message {} with key {}", ank_msg.content, shared_secret.to_lower_hex_string()); + } } } - continue; } } if plaintext.is_empty() { @@ -523,6 +544,8 @@ pub fn create_notification_transaction( Amount::from_sat(fee_rate.into()), )?; + debug!("Created transaction with secret {}", shared_secret.to_byte_array().to_lower_hex_string()); + let mut address2secret: Vec<(String, AnkSharedSecret)> = vec![]; address2secret.push((sp_address.into(), shared_secret)); @@ -560,7 +583,8 @@ pub fn encrypt_with_key(plaintext: String, key: String) -> ApiResult<String> { )?; let cipher = aes_enc.encrypt_with_aes_key()?; - Ok(String::from_utf8(cipher)?) + + Ok(cipher.to_lower_hex_string()) } #[wasm_bindgen] diff --git a/src/services.ts b/src/services.ts index 802c089..f975b67 100644 --- a/src/services.ts +++ b/src/services.ts @@ -107,17 +107,31 @@ class Services { let notificationInfo = await services.notify_address_for_message(recipientSpAddress, message); if (notificationInfo) { + let ciphers: string[] = []; console.info('Successfully sent notification transaction'); // Save the secret to db // encrypt the message(s) - services.encryptData(message, notificationInfo.address2secret); - // encrypt the key - + for (const [address, ankSharedSecret] of Object.entries(notificationInfo.address2secret)) { + try { + let cipher = await services.encryptData(message, ankSharedSecret.secret); + ciphers.push(cipher); + } catch (error) { + throw error; + } + } + const connection = await services.pickWebsocketConnectionRandom(); + const flag: AnkFlag = "Unknown"; + // for testing we only take the first cipher + const payload = ciphers.at(0); + if (!payload) { + console.error("No payload"); + return; + } // add peers list // add processes list // send message (transaction in envelope) + connection?.sendMessage(flag, payload); } - console.log(notificationInfo); } public async createId(event: Event): Promise<void> { @@ -224,6 +238,10 @@ class Services { if (user) { services.sdkClient.login_user(password, user.pre_id, user.recover_data, user.shares, user.outputs); this.sp_address = services.sdkClient.get_recover_address(); + if (this.sp_address) { + console.info('Using sp_address:', this.sp_address); + await services.obtainTokenWithFaucet(this.sp_address); + } } } catch (error) { console.error(error); @@ -802,7 +820,7 @@ class Services { } try { - const feeRate = 1000; + const feeRate = 1; let notificationInfo: createNotificationTransactionReturn = services.sdkClient.create_notification_transaction(sp_address, message, feeRate); const flag: AnkFlag = "NewTx"; const newTxMsg: NewTxMessage = { @@ -817,26 +835,38 @@ class Services { } } - public async encryptData(data: string, sharedSecret: Record<string, AnkSharedSecret>): Promise<encryptWithNewKeyResult> { + // public async encryptData(data: string, sharedSecret: Record<string, AnkSharedSecret>): Promise<Map<string, string>> { + // const services = await Services.getInstance(); + // let msg_cipher: encryptWithNewKeyResult; + // try { + // msg_cipher = services.sdkClient.encrypt_with_new_key(data); + // } catch (error) { + // throw error; + // } + + // let res = new Map<string, string>(); + // for (const [recipient, secret] of Object.entries(sharedSecret)) { + // try { + // const key = secret.secret; + // const encryptedKey: string = await services.sdkClient.encrypt_with_key(msg_cipher.key, key); + // res.set(recipient, encryptedKey); + // } catch (error) { + // throw new Error(`Failed to encrypt key for recipient ${recipient}: ${error}`); + // } + // } + + // return res; + // } + public async encryptData(data: string, key: string): Promise<string> { const services = await Services.getInstance(); - let msg_cipher: encryptWithNewKeyResult; + try { - msg_cipher = services.sdkClient.encrypt_with_new_key(data); + let res: string = services.sdkClient.encrypt_with_key(data, key); + return res; } catch (error) { throw error; } - - let res = new Map<string, string>(); - for (const [recipient, secret] of Object.entries(sharedSecret)) { - try { - const key = secret.secret; - const encryptedKey = await services.sdkClient.encrypt_with_key(msg_cipher.key, key); - res.set(recipient, encryptedKey); - } catch (error) { - throw new Error(`Failed to encrypt key for recipient ${recipient}: ${error}`); - } } -} public async decryptData(cipher: string, key: string): Promise<string> { const services = await Services.getInstance(); diff --git a/src/websockets.ts b/src/websockets.ts index c4fc134..79b9872 100644 --- a/src/websockets.ts +++ b/src/websockets.ts @@ -32,6 +32,8 @@ class WebSocketClient { // we received a tx window.alert(`New tx\n${res.message}`); await services.updateOwnedOutputsForUser(); + } else if (res.topic === 'unknown') { + window.alert(`new message: ${res.message}`); } } } else { From bcabeb9a0f0f163d577ba087d0c62ab30ba90fe2 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Tue, 7 May 2024 21:21:57 +0200 Subject: [PATCH 72/90] Add the sender address in message --- src/services.ts | 9 ++++++--- src/websockets.ts | 11 ++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/services.ts b/src/services.ts index f975b67..c328cd3 100644 --- a/src/services.ts +++ b/src/services.ts @@ -105,7 +105,9 @@ class Services { const recipientSpAddress = spAddressElement.value; const message = messageElement.value; - let notificationInfo = await services.notify_address_for_message(recipientSpAddress, message); + const msg_payload = JSON.stringify({sender: this.sp_address, payload: message}); + + let notificationInfo = await services.notify_address_for_message(recipientSpAddress, msg_payload); if (notificationInfo) { let ciphers: string[] = []; console.info('Successfully sent notification transaction'); @@ -113,7 +115,7 @@ class Services { // encrypt the message(s) for (const [address, ankSharedSecret] of Object.entries(notificationInfo.address2secret)) { try { - let cipher = await services.encryptData(message, ankSharedSecret.secret); + let cipher = await services.encryptData(msg_payload, ankSharedSecret.secret); ciphers.push(cipher); } catch (error) { throw error; @@ -821,7 +823,8 @@ class Services { try { const feeRate = 1; - let notificationInfo: createNotificationTransactionReturn = services.sdkClient.create_notification_transaction(sp_address, message, feeRate); + const commitment = services.sdkClient.create_commitment(message); + let notificationInfo: createNotificationTransactionReturn = services.sdkClient.create_notification_transaction(sp_address, commitment, feeRate); const flag: AnkFlag = "NewTx"; const newTxMsg: NewTxMessage = { 'transaction': notificationInfo.transaction, diff --git a/src/websockets.ts b/src/websockets.ts index 79b9872..3342c31 100644 --- a/src/websockets.ts +++ b/src/websockets.ts @@ -33,7 +33,16 @@ class WebSocketClient { window.alert(`New tx\n${res.message}`); await services.updateOwnedOutputsForUser(); } else if (res.topic === 'unknown') { - window.alert(`new message: ${res.message}`); + // Do we have a json with a sender? + try { + let parsed = JSON.parse(res.message); + if (parsed.sender !== undefined) { + console.info(`Message sent by ${parsed.sender}`); + } + window.alert(`new message: ${parsed.payload}`); + } catch (_) { + window.alert(`new message: ${res.message}`); + } } } } else { From fcafcff69e616301231e3520af8b2b7ad097ba90 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Mon, 13 May 2024 16:18:17 +0200 Subject: [PATCH 73/90] Return transaction to confirm identity --- crates/sp_client/src/api.rs | 181 ++++++++++++++++++++++++++---------- crates/sp_client/src/lib.rs | 34 ++++++- src/services.ts | 43 ++++++++- src/websockets.ts | 27 +++--- 4 files changed, 212 insertions(+), 73 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index eb6b1aa..0eb433c 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -5,15 +5,16 @@ use std::str::FromStr; use std::string::FromUtf8Error; use std::sync::{Mutex, OnceLock, PoisonError}; -use log::debug; +use log::{debug, warn}; use rand::{Fill, Rng}; use anyhow::Error as AnyhowError; use sdk_common::crypto::{ AeadCore, Aes256Decryption, Aes256Encryption, Aes256Gcm, AnkSharedSecret, KeyInit, Purpose, }; -use serde_json::Error as SerdeJsonError; +use serde_json::{Error as SerdeJsonError, Value}; use shamir::SecretData; +use sp_client::bitcoin::blockdata::fee_rate; use sp_client::bitcoin::consensus::{deserialize, serialize}; use sp_client::bitcoin::hex::{parse, DisplayHex, FromHex, HexToBytesError}; use sp_client::bitcoin::secp256k1::ecdh::shared_secret_point; @@ -27,16 +28,16 @@ use tsify::Tsify; use wasm_bindgen::convert::FromWasmAbi; use wasm_bindgen::prelude::*; -use sdk_common::network::{AnkFlag, AnkNetworkMsg, NewTxMessage}; +use sdk_common::network::{AnkFlag, AnkNetworkMsg, NewTxMessage, UnknownMessage}; use sdk_common::silentpayments::{ - check_transaction, create_transaction_for_address_with_shared_secret, + check_transaction, create_transaction, create_transaction_for_address_with_shared_secret, }; use sp_client::spclient::{derive_keys_from_seed, OutputList, OwnedOutput, SpClient}; use sp_client::spclient::{SpWallet, SpendKey}; use crate::user::{lock_connected_user, User, UserWallets, CONNECTED_USER}; -use crate::{images, lock_scanned_transactions, Txid2Secrets}; +use crate::{images, lock_scanned_transactions, lock_secrets, lock_watched, Txid2Secrets}; use crate::process::Process; @@ -330,16 +331,80 @@ pub fn login_user( Ok(res) } +pub fn scan_for_confirmation_transaction(tx_hex: String) -> anyhow::Result<String> { + let tx = deserialize::<Transaction>(&Vec::from_hex(&tx_hex)?)?; + + for i in tx.input.iter() { + if let Some(waiting) = lock_watched()?.remove(&i.previous_output) { + match lock_secrets()?.get_mut(&waiting) { + None => return Err(anyhow::Error::msg("No secret match for an error we're waiting for")), + Some(secret) => { + // for now we only handle the case of one secret for one transaction + let res = secret.get_mut(0).unwrap(); + res.1.trusted = true; + return Ok(res.0.clone()); + } + } + } + } + + Err(anyhow::Error::msg("Not spending a watched output")) +} + +fn handle_recover_transaction(tx: Transaction, sp_wallet: &mut SpWallet, tweak_data: PublicKey, fee_rate: u32) -> anyhow::Result<Option<Transaction>> { + // does this transaction spent a txid and output we're waiting confirmation for? + let scan_sk = sp_wallet.get_client().get_scan_key(); + let txid = tx.txid(); + for input in tx.input { + let prevout = input.previous_output; + match lock_secrets()?.get_mut(&prevout.txid) { + None => { + continue; + } + Some(secret) => { + // We found an input spending a notification transaction we sent + if let Some(res) = secret.get_mut(prevout.vout as usize) { + // This is a challenge from a previous message we sent + // we toggle the trusted value + if !res.1.trusted { + res.1.trusted = true; + } else { + return Err(anyhow::Error::msg("Received a confirmation for a transaction we already confirmed")); + } + // We spend the output back to the receiver + let sp_address = SilentPaymentAddress::try_from(res.0.as_str()).expect("Invalid silent payment address"); + let response_tx = create_transaction(sp_address, sp_wallet, Amount::from_sat(fee_rate.into()))?; + return Ok(Some(response_tx)); + } else { + return Err(anyhow::Error::msg("Received a confirmation from an umapped output")); + } + } + } + } + // If we exhausted all inputs without finding one of our transaction, it means it's a notification + let shared_point = + shared_secret_point(&tweak_data, &scan_sk); + lock_secrets()?.insert( + txid, + vec![("".to_owned(), AnkSharedSecret::new(shared_point, false))], + ); + Ok(None) +} + #[wasm_bindgen] pub fn check_transaction_for_silent_payments( tx_hex: String, blockheight: u32, tweak_data_hex: String, + fee_rate: u32, ) -> ApiResult<String> { let tx = deserialize::<Transaction>(&Vec::from_hex(&tx_hex)?)?; - // check that we don't already have scanned the tx - if lock_scanned_transactions()?.contains_key(&tx.txid()) { - return Err(ApiError { message: "Transaction already scanned".to_owned()}); + + // check that we don't already have scanned the tx, and insert it if we don't + if !lock_scanned_transactions()?.insert(tx.txid()) { + return Err(ApiError { + message: "Transaction already scanned".to_owned(), + }); } let tweak_data = PublicKey::from_str(&tweak_data_hex)?; @@ -347,30 +412,28 @@ pub fn check_transaction_for_silent_payments( let mut connected_user = lock_connected_user()?; if let Ok(recover) = connected_user.try_get_mut_recover() { if let Ok(txid) = check_transaction(&tx, recover, blockheight, tweak_data) { - let shared_point = shared_secret_point(&tweak_data, &recover.get_client().get_scan_key()); - lock_scanned_transactions()?.insert(tx.txid(), vec![("".to_owned(), AnkSharedSecret::new(shared_point, false))]); + if let Err(e) = scan_for_confirmation_transaction(tx_hex) { + log::error!("{}", e); + handle_recover_transaction(tx, recover, tweak_data, fee_rate)?; + } return Ok(txid); } } if let Ok(main) = connected_user.try_get_mut_main() { if let Ok(txid) = check_transaction(&tx, main, blockheight, tweak_data) { - let shared_point = shared_secret_point(&tweak_data, &main.get_client().get_scan_key()); - lock_scanned_transactions()?.insert(tx.txid(), vec![("".to_owned(), AnkSharedSecret::new(shared_point, false))]); + // TODO return Ok(txid); } } if let Ok(revoke) = connected_user.try_get_mut_revoke() { if let Ok(txid) = check_transaction(&tx, revoke, blockheight, tweak_data) { - let shared_point = shared_secret_point(&tweak_data, &revoke.get_client().get_scan_key()); - lock_scanned_transactions()?.insert(tx.txid(), vec![("".to_owned(), AnkSharedSecret::new(shared_point, false))]); + // TODO return Ok(txid); } } - // we still want to insert an empty entry in our cache to make sure we don't scan the transaction again - lock_scanned_transactions()?.insert(tx.txid(), vec![("".to_owned(), AnkSharedSecret::default())]); Err(ApiError { message: "No output found".to_owned(), }) @@ -385,7 +448,7 @@ pub struct parseNetworkMsgReturn { } #[wasm_bindgen] -pub fn parse_network_msg(raw: String) -> ApiResult<parseNetworkMsgReturn> { +pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<parseNetworkMsgReturn> { if let Ok(ank_msg) = serde_json::from_str::<AnkNetworkMsg>(&raw) { match ank_msg.flag { AnkFlag::NewTx => { @@ -399,6 +462,7 @@ pub fn parse_network_msg(raw: String) -> ApiResult<parseNetworkMsgReturn> { tx_message.transaction, 0, tx_message.tweak_data.unwrap(), + fee_rate, )?; return Ok(parseNetworkMsgReturn { topic: AnkFlag::NewTx.as_str().to_owned(), @@ -414,44 +478,60 @@ pub fn parse_network_msg(raw: String) -> ApiResult<parseNetworkMsgReturn> { } AnkFlag::Unknown => { // try to decrypt the cipher with all available keys - let mut plaintext: String = "".to_owned(); - for (txid, secret_vec) in lock_scanned_transactions()?.iter() { - for (shared_with, ank_secret) in secret_vec.iter() { - if *ank_secret == AnkSharedSecret::default() { - continue; - } + for (txid, secret_vec) in lock_secrets()?.iter_mut() { + // Actually we probably will ever have only one secret in the case we're receiver + for (shared_with, ank_secret) in secret_vec.iter_mut() { + // if we already have shared_with, that means we already used that key for another message + if !shared_with.is_empty() { continue } let shared_secret = ank_secret.to_byte_array(); - if let Ok(msg_decrypt) = Aes256Decryption::new( + debug!("{} {}", shared_with, shared_secret.to_lower_hex_string()); + let msg_decrypt = Aes256Decryption::new( Purpose::Arbitrary, Vec::from_hex(&ank_msg.content.trim_matches('\"'))?, shared_secret, - ) { - match msg_decrypt.decrypt_with_key() { - Ok(plain) => { - plaintext = String::from_utf8(plain)?; - break; - }, - Err(e) => { - debug!("{}", e); - debug!("Failed to decrypt message {} with key {}", ank_msg.content, shared_secret.to_lower_hex_string()); + )?; + match msg_decrypt.decrypt_with_key() { + Ok(plaintext) => { + let unknown_msg = serde_json::from_slice::<UnknownMessage>(&plaintext); + if unknown_msg.is_err() { + // The message we were sent is invalid, drop everything + // for now let's just fill the shared_with with garbage + *shared_with = "a".to_owned(); + return Err(ApiError { message: "Invalid msg".to_owned() }) } + let sender: Result<SilentPaymentAddress, SpError> = unknown_msg.unwrap().sender.try_into(); + if sender.is_err() { + // The sender is invalid address + *shared_with = "a".to_owned(); + return Err(ApiError { message: "Invalid sp address".to_owned() }) + } + + // we update our list with the sender address + *shared_with = sender.unwrap().into(); + + // We return the whole message + // ts is responsible for sending the confirmation message + return Ok(parseNetworkMsgReturn { + topic: AnkFlag::Unknown.as_str().to_owned(), + message: String::from_utf8(plaintext)?, + }); + } + Err(e) => { + debug!("{}", e); + debug!( + "Failed to decrypt message {} with key {}", + ank_msg.content, + shared_secret.to_lower_hex_string() + ); } } } } - if plaintext.is_empty() { - // keep the message in cache, just in case - // return an error - return Err(ApiError { - message: "No key found".to_owned(), - }); - } else { - // return the plain text - return Ok(parseNetworkMsgReturn { - topic: AnkFlag::Unknown.as_str().to_owned(), - message: plaintext, - }); - } + // keep the message in cache, just in case? + // return an error + return Err(ApiError { + message: "No key found".to_owned(), + }); } _ => unimplemented!(), } @@ -523,7 +603,7 @@ pub struct createNotificationTransactionReturn { #[wasm_bindgen] pub fn create_notification_transaction( recipient: String, - message: String, + message: Option<String>, fee_rate: u32, ) -> ApiResult<createNotificationTransactionReturn> { let sp_address: SilentPaymentAddress = recipient.try_into()?; @@ -544,13 +624,16 @@ pub fn create_notification_transaction( Amount::from_sat(fee_rate.into()), )?; - debug!("Created transaction with secret {}", shared_secret.to_byte_array().to_lower_hex_string()); + debug!( + "Created transaction with secret {}", + shared_secret.to_byte_array().to_lower_hex_string() + ); let mut address2secret: Vec<(String, AnkSharedSecret)> = vec![]; address2secret.push((sp_address.into(), shared_secret)); // update our cache - lock_scanned_transactions()?.insert(transaction.txid(), address2secret.clone()); + lock_secrets()?.insert(transaction.txid(), address2secret.clone()); Ok(createNotificationTransactionReturn { txid: transaction.txid().to_string(), diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index 8d7155c..4802a9f 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -2,9 +2,9 @@ use anyhow::Error; use sdk_common::crypto::AnkSharedSecret; use serde::{Deserialize, Serialize}; -use sp_client::bitcoin::Txid; +use sp_client::bitcoin::{OutPoint, Txid}; use sp_client::silentpayments::sending::SilentPaymentAddress; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::fmt::Debug; use std::sync::{Mutex, MutexGuard, OnceLock}; use tsify::Tsify; @@ -16,16 +16,40 @@ mod peers; mod process; mod user; +/// We map txid with one or n secrets +/// Each secret match one sp address +/// When we first detect a transaction, we can't tell who's the sender, so we like sp address empty +/// When we receive the corresponding message, we get a sp address declaration, we complete here +/// Then when we send the confirmation transaction and got the response we can flip the secret to trusted pub type Txid2Secrets = HashMap<Txid, Vec<(String, AnkSharedSecret)>>; -pub static TRANSACTIONCACHE: OnceLock<Mutex<Txid2Secrets>> = OnceLock::new(); +pub static SECRETCACHE: OnceLock<Mutex<Txid2Secrets>> = OnceLock::new(); -pub fn lock_scanned_transactions() -> Result<MutexGuard<'static, Txid2Secrets>, Error> { - TRANSACTIONCACHE +pub fn lock_secrets() -> Result<MutexGuard<'static, Txid2Secrets>, Error> { + SECRETCACHE .get_or_init(|| Mutex::new(Txid2Secrets::new())) .lock_anyhow() } +/// this is to keep track of transaction we already analysed without finding notification +/// This is not critical and there's no need to keep that in persistent storage, as most transactions would only show up twice +/// Worst case is we will scan again transactions when they got into a block +pub static TRANSACTIONCACHE: OnceLock<Mutex<HashSet<Txid>>> = OnceLock::new(); + +pub fn lock_scanned_transactions() -> Result<MutexGuard<'static, HashSet<Txid>>, Error> { + TRANSACTIONCACHE + .get_or_init(|| Mutex::new(HashSet::new())) + .lock_anyhow() +} + +pub static WATCHEDUTXO: OnceLock<Mutex<HashMap<OutPoint, Txid>>> = OnceLock::new(); + +pub fn lock_watched() -> Result<MutexGuard<'static, HashMap<OutPoint, Txid>>, Error> { + WATCHEDUTXO + .get_or_init(|| Mutex::new(HashMap::new())) + .lock_anyhow() +} + pub(crate) trait MutexExt<T> { fn lock_anyhow(&self) -> Result<MutexGuard<T>, Error>; } diff --git a/src/services.ts b/src/services.ts index c328cd3..4d95df8 100644 --- a/src/services.ts +++ b/src/services.ts @@ -105,7 +105,7 @@ class Services { const recipientSpAddress = spAddressElement.value; const message = messageElement.value; - const msg_payload = JSON.stringify({sender: this.sp_address, payload: message}); + const msg_payload = JSON.stringify({sender: this.sp_address, message: message}); let notificationInfo = await services.notify_address_for_message(recipientSpAddress, msg_payload); if (notificationInfo) { @@ -313,14 +313,13 @@ class Services { services.attachSubmitListener("form4nk", services.updateAnId); } - public async parseNetworkMessage(raw: string): Promise<parseNetworkMsgReturn | null> { + public async parseNetworkMessage(raw: string, feeRate: number): Promise<parseNetworkMsgReturn> { const services = await Services.getInstance(); try { - const msg: parseNetworkMsgReturn = services.sdkClient.parse_network_msg(raw); + const msg: parseNetworkMsgReturn = services.sdkClient.parse_network_msg(raw, feeRate); return msg; } catch (error) { - console.error(error); - return null; + throw error; } } @@ -802,6 +801,40 @@ class Services { } } + public async confirm_sender_address(sp_address: string): Promise<void> { + const services = await Services.getInstance(); + const connection = await services.pickWebsocketConnectionRandom(); + if (!connection) { + throw new Error("No connection to relay"); + } + let user: User; + try { + let possibleUser = await services.getUserInfo(); + if (!possibleUser) { + throw new Error("No user loaded, please first create a new user or login"); + } else { + user = possibleUser; + } + } catch (error) { + throw error; + } + + let notificationInfo: createNotificationTransactionReturn; + try { + const feeRate = 1; + notificationInfo = services.sdkClient.create_notification_transaction(sp_address, undefined, feeRate); + } catch (error) { + throw new Error(`Failed to create confirmation transaction: ${error}`); + } + const flag: AnkFlag = "NewTx"; + const newTxMsg: NewTxMessage = { + 'transaction': notificationInfo.transaction, + 'tweak_data': null + } + connection.sendMessage(flag, JSON.stringify(newTxMsg)); + return; + } + public async notify_address_for_message(sp_address: string, message: string): Promise<createNotificationTransactionReturn | null> { const services = await Services.getInstance(); const connection = await services.pickWebsocketConnectionRandom(); diff --git a/src/websockets.ts b/src/websockets.ts index 3342c31..0234f56 100644 --- a/src/websockets.ts +++ b/src/websockets.ts @@ -25,28 +25,27 @@ class WebSocketClient { (async () => { if (typeof(msgData) === 'string') { - console.log("Received text message: "+msgData); - let res = await services.parseNetworkMessage(msgData); - if (res) { + // console.log("Received text message: "+msgData); + try { + const feeRate = 1; + let res = await services.parseNetworkMessage(msgData, feeRate); if (res.topic === 'new_tx') { // we received a tx window.alert(`New tx\n${res.message}`); await services.updateOwnedOutputsForUser(); } else if (res.topic === 'unknown') { - // Do we have a json with a sender? - try { - let parsed = JSON.parse(res.message); - if (parsed.sender !== undefined) { - console.info(`Message sent by ${parsed.sender}`); - } - window.alert(`new message: ${parsed.payload}`); - } catch (_) { - window.alert(`new message: ${res.message}`); - } + let parsed = JSON.parse(res.message); + let message = parsed['message']; + let sender = parsed['sender']; + window.alert(`new message: ${message}\nAsking sender ${sender} to confirm identity...`); + console.debug(`sending confirm message to ${sender}`); + await services.confirm_sender_address(sender); } + } catch (error) { + console.error('Received an invalid message:', error); } } else { - console.error("Received an invalid message"); + console.error('Received a non-string message'); } })(); }); From 0f7bc644c8375c2d47715f4ca755beb2d4433a97 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Wed, 22 May 2024 10:15:42 +0200 Subject: [PATCH 74/90] Heavy refactor of the caching and message structure --- crates/sp_client/Cargo.toml | 4 +- crates/sp_client/src/api.rs | 581 ++++++++++++++++++++++++++---------- crates/sp_client/src/lib.rs | 35 +-- package.json | 2 +- src/database.ts | 5 + src/services.ts | 90 +++--- src/websockets.ts | 9 +- 7 files changed, 488 insertions(+), 238 deletions(-) diff --git a/crates/sp_client/Cargo.toml b/crates/sp_client/Cargo.toml index f64543a..264bd2f 100644 --- a/crates/sp_client/Cargo.toml +++ b/crates/sp_client/Cargo.toml @@ -8,8 +8,8 @@ name = "sdk_client" crate-type = ["cdylib"] [dependencies] -# sp_client= { path = "../../../sp-client" } -sp_client= { git = "https://github.com/Sosthene00/sp-client", branch = "sp_client" } +sp_client= { path = "../../../sp-client" } +# sp_client= { git = "https://github.com/Sosthene00/sp-client", branch = "sp_client" } anyhow = "1.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0" diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 0eb433c..19c348c 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -1,12 +1,14 @@ use std::any::Any; +use std::borrow::Borrow; use std::collections::HashMap; use std::io::Write; use std::str::FromStr; use std::string::FromUtf8Error; use std::sync::{Mutex, OnceLock, PoisonError}; +use std::time::{Duration, Instant}; use log::{debug, warn}; -use rand::{Fill, Rng}; +use rand::{thread_rng, Fill, Rng, RngCore}; use anyhow::Error as AnyhowError; use sdk_common::crypto::{ @@ -16,10 +18,13 @@ use serde_json::{Error as SerdeJsonError, Value}; use shamir::SecretData; use sp_client::bitcoin::blockdata::fee_rate; use sp_client::bitcoin::consensus::{deserialize, serialize}; -use sp_client::bitcoin::hex::{parse, DisplayHex, FromHex, HexToBytesError}; +use sp_client::bitcoin::hashes::HashEngine; +use sp_client::bitcoin::hashes::{sha256, Hash}; +use sp_client::bitcoin::hex::{parse, DisplayHex, FromHex, HexToArrayError, HexToBytesError}; +use sp_client::bitcoin::key::Secp256k1; use sp_client::bitcoin::secp256k1::ecdh::shared_secret_point; use sp_client::bitcoin::secp256k1::{PublicKey, SecretKey}; -use sp_client::bitcoin::{Amount, OutPoint, Transaction, Txid}; +use sp_client::bitcoin::{Amount, Network, OutPoint, Psbt, Transaction, Txid}; use sp_client::silentpayments::Error as SpError; use serde::{Deserialize, Serialize}; @@ -28,16 +33,21 @@ use tsify::Tsify; use wasm_bindgen::convert::FromWasmAbi; use wasm_bindgen::prelude::*; -use sdk_common::network::{AnkFlag, AnkNetworkMsg, NewTxMessage, UnknownMessage}; +use sdk_common::network::{ + self, AnkFlag, AnkNetworkMsg, FaucetMessage, NewTxMessage, UnknownMessage, +}; use sdk_common::silentpayments::{ - check_transaction, create_transaction, create_transaction_for_address_with_shared_secret, + create_transaction, create_transaction_for_address_with_shared_secret, + create_transaction_spend_outpoint, map_outputs_to_sp_address }; -use sp_client::spclient::{derive_keys_from_seed, OutputList, OwnedOutput, SpClient}; +use sp_client::spclient::{ + derive_keys_from_seed, OutputList, OutputSpendStatus, OwnedOutput, Recipient, SpClient, +}; use sp_client::spclient::{SpWallet, SpendKey}; use crate::user::{lock_connected_user, User, UserWallets, CONNECTED_USER}; -use crate::{images, lock_scanned_transactions, lock_secrets, lock_watched, Txid2Secrets}; +use crate::{images, lock_messages}; use crate::process::Process; @@ -82,6 +92,30 @@ impl From<HexToBytesError> for ApiError { } } +impl From<HexToArrayError> for ApiError { + fn from(value: HexToArrayError) -> Self { + ApiError { + message: value.to_string(), + } + } +} + +impl From<sp_client::bitcoin::psbt::PsbtParseError> for ApiError { + fn from(value: sp_client::bitcoin::psbt::PsbtParseError) -> Self { + ApiError { + message: value.to_string(), + } + } +} + +impl From<sp_client::bitcoin::psbt::ExtractTxError> for ApiError { + fn from(value: sp_client::bitcoin::psbt::ExtractTxError) -> Self { + ApiError { + message: value.to_string(), + } + } +} + impl From<sp_client::bitcoin::secp256k1::Error> for ApiError { fn from(value: sp_client::bitcoin::secp256k1::Error) -> Self { ApiError { @@ -331,112 +365,184 @@ pub fn login_user( Ok(res) } -pub fn scan_for_confirmation_transaction(tx_hex: String) -> anyhow::Result<String> { - let tx = deserialize::<Transaction>(&Vec::from_hex(&tx_hex)?)?; +fn handle_recover_transaction( + updated: HashMap<OutPoint, OwnedOutput>, + tx: &Transaction, + sp_wallet: &mut SpWallet, + tweak_data: PublicKey, + fee_rate: u32, +) -> anyhow::Result<NetworkMessage> { + // We need to look for different case: + // 1) faucet + // This one is the simplest, we only care about finding the commitment + let op_return = tx.output.iter().find(|o| o.script_pubkey.is_op_return()); + let commitment = if op_return.is_none() { + vec![] + } else { + op_return.unwrap().script_pubkey.as_bytes()[2..].to_vec() + }; + let commitment_str = commitment.to_lower_hex_string(); + let pos = lock_messages()? + .iter() + .position(|m| m.commitment.as_ref() == Some(&commitment_str)); - for i in tx.input.iter() { - if let Some(waiting) = lock_watched()?.remove(&i.previous_output) { - match lock_secrets()?.get_mut(&waiting) { - None => return Err(anyhow::Error::msg("No secret match for an error we're waiting for")), - Some(secret) => { - // for now we only handle the case of one secret for one transaction - let res = secret.get_mut(0).unwrap(); - res.1.trusted = true; - return Ok(res.0.clone()); - } - } - } + if pos.is_some() { + let messages = lock_messages()?; + let message = messages.get(pos.unwrap()); + return Ok(message.cloned().unwrap()); } - Err(anyhow::Error::msg("Not spending a watched output")) -} + // If we got updates from a transaction, it means that it creates an output to us, spend an output we owned, or both + // If we destroyed outputs it means we either notified others, or ask confirmation, or confirm + // We probably creates outputs too in this case because of change + // If we only created outputs it means we are being notified + let utxo_destroyed: HashMap<&OutPoint, &OwnedOutput> = updated + .iter() + .filter(|(outpoint, output)| output.spend_status != OutputSpendStatus::Unspent) + .collect(); + let utxo_created: HashMap<&OutPoint, &OwnedOutput> = updated + .iter() + .filter(|(outpoint, output)| output.spend_status == OutputSpendStatus::Unspent) + .collect(); -fn handle_recover_transaction(tx: Transaction, sp_wallet: &mut SpWallet, tweak_data: PublicKey, fee_rate: u32) -> anyhow::Result<Option<Transaction>> { - // does this transaction spent a txid and output we're waiting confirmation for? - let scan_sk = sp_wallet.get_client().get_scan_key(); - let txid = tx.txid(); - for input in tx.input { - let prevout = input.previous_output; - match lock_secrets()?.get_mut(&prevout.txid) { - None => { - continue; - } - Some(secret) => { - // We found an input spending a notification transaction we sent - if let Some(res) = secret.get_mut(prevout.vout as usize) { - // This is a challenge from a previous message we sent - // we toggle the trusted value - if !res.1.trusted { - res.1.trusted = true; - } else { - return Err(anyhow::Error::msg("Received a confirmation for a transaction we already confirmed")); + // 2) confirmation + // If the transaction spends one outpoint in `commited_in`, it means we are receiving a confirmation for a notification + // if we are receiver, then we must look for `confirmed_by` + // if we owned at least one input or no outputs, we can skip the check + if utxo_destroyed.is_empty() && !utxo_created.is_empty() { + for input in tx.input.iter() { + // Check for each input if it match a known commitment we made as a sender + // OR a confirmation for the receiver + let pos = lock_messages()?.iter().position(|m| { + m.commited_in == Some(input.previous_output) + || m.confirmed_by == Some(input.previous_output) + }); + if pos.is_some() { + let mut messages = lock_messages()?; + let message = messages.get_mut(pos.unwrap()).unwrap(); + // If we are receiver, that's pretty much it, just set status to complete + if message.recipient == Some(sp_wallet.get_client().get_receiving_address()) { + debug_assert!(message.confirmed_by == Some(input.previous_output)); + message.status = NetworkMessageStatus::Complete; + return Ok(message.clone()); + } + + // sender needs to spent it back again to receiver + let (outpoint, output) = utxo_created.iter().next().unwrap(); + + // If we are sender, then we must update the confirmed_by field + message.confirmed_by = Some(**outpoint); + + // Caller must interpret this message as "spend confirmed_by outpoint to receiver" + return Ok(message.clone()); + } else { + // we are being notified + let shared_point = + shared_secret_point(&tweak_data, &sp_wallet.get_client().get_scan_key()); + let shared_secret = AnkSharedSecret::new(shared_point); + + let mut messages = lock_messages()?; + let cipher_pos = messages.iter().position(|m| { + if m.status != NetworkMessageStatus::CipherWaitingTx { + return false; } - // We spend the output back to the receiver - let sp_address = SilentPaymentAddress::try_from(res.0.as_str()).expect("Invalid silent payment address"); - let response_tx = create_transaction(sp_address, sp_wallet, Amount::from_sat(fee_rate.into()))?; - return Ok(Some(response_tx)); + m.try_decrypt_with_shared_secret(shared_secret.to_byte_array()) + .is_some() + }); + + if cipher_pos.is_some() { + let message = messages.get_mut(cipher_pos.unwrap()).unwrap(); + let (outpoint, output) = utxo_created.iter().next().unwrap(); + message.commited_in = Some(**outpoint); + message.shared_secret = + Some(shared_secret.to_byte_array().to_lower_hex_string()); + message.commitment = Some(commitment.to_lower_hex_string()); + + let plaintext = message + .try_decrypt_with_shared_secret(shared_secret.to_byte_array()) + .unwrap(); + let unknown_msg: UnknownMessage = serde_json::from_slice(&plaintext)?; + message.plaintext = Some(unknown_msg.message); + message.sender = Some(unknown_msg.sender); + message.recipient = Some(sp_wallet.get_client().get_receiving_address()); + return Ok(message.clone()) } else { - return Err(anyhow::Error::msg("Received a confirmation from an umapped output")); + // store it and wait for the message + let mut new_msg = NetworkMessage::default(); + let (outpoint, output) = utxo_created.iter().next().unwrap(); + new_msg.commited_in = Some(**outpoint); + new_msg.commitment = Some(commitment.to_lower_hex_string()); + new_msg.recipient = Some(sp_wallet.get_client().get_receiving_address()); + new_msg.shared_secret = + Some(shared_secret.to_byte_array().to_lower_hex_string()); + new_msg.status = NetworkMessageStatus::TxWaitingCipher; + lock_messages()?.push(new_msg.clone()); + return Ok(new_msg.clone()); } } } + unreachable!("Transaction with no inputs"); + } else { + // We are sender of a notification transaction + // We only need to return the message + if let Some(message) = lock_messages()?.iter() + .find(|m| { + m.commitment.as_ref() == Some(&commitment_str) + }) + { + return Ok(message.clone()); + } else { + return Err(anyhow::Error::msg("We spent a transaction for a commitment we don't know")); + } } - // If we exhausted all inputs without finding one of our transaction, it means it's a notification - let shared_point = - shared_secret_point(&tweak_data, &scan_sk); - lock_secrets()?.insert( - txid, - vec![("".to_owned(), AnkSharedSecret::new(shared_point, false))], - ); - Ok(None) } -#[wasm_bindgen] -pub fn check_transaction_for_silent_payments( +/// If the transaction has anything to do with us, we create/update the relevant `NetworkMessage` +/// and return it to caller for persistent storage +fn process_transaction( tx_hex: String, blockheight: u32, tweak_data_hex: String, fee_rate: u32, -) -> ApiResult<String> { +) -> anyhow::Result<NetworkMessage> { let tx = deserialize::<Transaction>(&Vec::from_hex(&tx_hex)?)?; - // check that we don't already have scanned the tx, and insert it if we don't - if !lock_scanned_transactions()?.insert(tx.txid()) { - return Err(ApiError { - message: "Transaction already scanned".to_owned(), - }); + // check that we don't already have scanned the tx + if let Some(_) = lock_messages()?.iter().find(|message| { + if let Some(outpoint) = message.commited_in { + if outpoint.txid == tx.txid() { + return true; + } + } + return false; + }) { + return Err(anyhow::Error::msg("Transaction already scanned")); } let tweak_data = PublicKey::from_str(&tweak_data_hex)?; let mut connected_user = lock_connected_user()?; if let Ok(recover) = connected_user.try_get_mut_recover() { - if let Ok(txid) = check_transaction(&tx, recover, blockheight, tweak_data) { - if let Err(e) = scan_for_confirmation_transaction(tx_hex) { - log::error!("{}", e); - handle_recover_transaction(tx, recover, tweak_data, fee_rate)?; - } - return Ok(txid); + let updated = recover.update_wallet_with_transaction(&tx, blockheight, tweak_data)?; + + if updated.len() > 0 { + let updated_msg = + handle_recover_transaction(updated, &tx, recover, tweak_data, fee_rate)?; + return Ok(updated_msg); } } if let Ok(main) = connected_user.try_get_mut_main() { - if let Ok(txid) = check_transaction(&tx, main, blockheight, tweak_data) { - // TODO - return Ok(txid); - } + let updated = main.update_wallet_with_transaction(&tx, blockheight, tweak_data)?; + unimplemented!(); } if let Ok(revoke) = connected_user.try_get_mut_revoke() { - if let Ok(txid) = check_transaction(&tx, revoke, blockheight, tweak_data) { - // TODO - return Ok(txid); - } + let updated = revoke.update_wallet_with_transaction(&tx, blockheight, tweak_data)?; + unimplemented!(); } - Err(ApiError { - message: "No output found".to_owned(), - }) + Err(anyhow::Error::msg("No output found")) } #[derive(Tsify, Serialize, Deserialize)] @@ -444,7 +550,7 @@ pub fn check_transaction_for_silent_payments( #[allow(non_camel_case_types)] pub struct parseNetworkMsgReturn { topic: String, - message: String, + message: NetworkMessage, } #[wasm_bindgen] @@ -458,80 +564,57 @@ pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<parseNetworkMs message: "Missing tweak_data".to_owned(), }); } - let txid = check_transaction_for_silent_payments( + let network_msg = process_transaction( tx_message.transaction, 0, tx_message.tweak_data.unwrap(), fee_rate, )?; + debug!("{:?}", network_msg); return Ok(parseNetworkMsgReturn { - topic: AnkFlag::NewTx.as_str().to_owned(), - message: txid, + topic: ank_msg.flag.as_str().to_owned(), + message: network_msg, }); } AnkFlag::Faucet => unimplemented!(), AnkFlag::Error => { + let error_msg = NetworkMessage::new_error(ank_msg.content); return Ok(parseNetworkMsgReturn { topic: AnkFlag::Error.as_str().to_owned(), - message: ank_msg.content.to_owned(), + message: error_msg, }) } AnkFlag::Unknown => { - // try to decrypt the cipher with all available keys - for (txid, secret_vec) in lock_secrets()?.iter_mut() { - // Actually we probably will ever have only one secret in the case we're receiver - for (shared_with, ank_secret) in secret_vec.iter_mut() { - // if we already have shared_with, that means we already used that key for another message - if !shared_with.is_empty() { continue } - let shared_secret = ank_secret.to_byte_array(); - debug!("{} {}", shared_with, shared_secret.to_lower_hex_string()); - let msg_decrypt = Aes256Decryption::new( - Purpose::Arbitrary, - Vec::from_hex(&ank_msg.content.trim_matches('\"'))?, - shared_secret, - )?; - match msg_decrypt.decrypt_with_key() { - Ok(plaintext) => { - let unknown_msg = serde_json::from_slice::<UnknownMessage>(&plaintext); - if unknown_msg.is_err() { - // The message we were sent is invalid, drop everything - // for now let's just fill the shared_with with garbage - *shared_with = "a".to_owned(); - return Err(ApiError { message: "Invalid msg".to_owned() }) - } - let sender: Result<SilentPaymentAddress, SpError> = unknown_msg.unwrap().sender.try_into(); - if sender.is_err() { - // The sender is invalid address - *shared_with = "a".to_owned(); - return Err(ApiError { message: "Invalid sp address".to_owned() }) - } - - // we update our list with the sender address - *shared_with = sender.unwrap().into(); - - // We return the whole message - // ts is responsible for sending the confirmation message - return Ok(parseNetworkMsgReturn { - topic: AnkFlag::Unknown.as_str().to_owned(), - message: String::from_utf8(plaintext)?, - }); - } - Err(e) => { - debug!("{}", e); - debug!( - "Failed to decrypt message {} with key {}", - ank_msg.content, - shared_secret.to_lower_hex_string() - ); - } - } + // let's try to decrypt with keys we found in transactions but haven't used yet + let mut messages = lock_messages()?; + let cipher = Vec::from_hex(&ank_msg.content)?; + let cipher_pos = messages.iter().position(|m| { + if m.status != NetworkMessageStatus::TxWaitingCipher { + return false; } - } - // keep the message in cache, just in case? - // return an error - return Err(ApiError { - message: "No key found".to_owned(), + m.try_decrypt_cipher(cipher.clone()).is_some() }); + if cipher_pos.is_some() { + let mut message = messages.get_mut(cipher_pos.unwrap()).unwrap(); + let plain = message.try_decrypt_cipher(cipher).unwrap(); + let unknown_msg: UnknownMessage = serde_json::from_slice(&plain)?; + message.plaintext = Some(unknown_msg.message); + message.sender = Some(unknown_msg.sender); + message.ciphertext = Some(ank_msg.content); + return Ok(parseNetworkMsgReturn { + topic: AnkFlag::Unknown.as_str().to_owned(), + message: message.clone(), + }); + } else { + // let's keep it in case we receive the transaction later + let mut new_msg = NetworkMessage::default(); + new_msg.status = NetworkMessageStatus::CipherWaitingTx; + new_msg.ciphertext = Some(ank_msg.content); + messages.push(new_msg); + return Err(ApiError { + message: "Can't decrypt message".to_owned(), + }); + } } _ => unimplemented!(), } @@ -597,16 +680,20 @@ pub fn is_tx_owned_by_user(pre_id: String, tx: String) -> ApiResult<bool> { pub struct createNotificationTransactionReturn { pub txid: String, pub transaction: String, - pub address2secret: HashMap<String, AnkSharedSecret>, + pub new_network_msg: NetworkMessage, } +/// This is what we call to confirm as a receiver #[wasm_bindgen] -pub fn create_notification_transaction( - recipient: String, - message: Option<String>, +pub fn create_confirmation_transaction( + message: NetworkMessage, fee_rate: u32, ) -> ApiResult<createNotificationTransactionReturn> { - let sp_address: SilentPaymentAddress = recipient.try_into()?; + if message.sender.is_none() || message.confirmed_by.is_none() { + return Err(ApiError { message: "Invalid network message".to_owned() }); + } + + let sp_address: SilentPaymentAddress = message.sender.as_ref().unwrap().as_str().try_into()?; let connected_user = lock_connected_user()?; @@ -617,28 +704,97 @@ pub fn create_notification_transaction( sp_wallet = connected_user.try_get_main()?; } - let (transaction, shared_secret) = create_transaction_for_address_with_shared_secret( - sp_address, + let recipient = Recipient { + address: sp_address.into(), + amount: Amount::from_sat(1200), + nb_outputs: 1, + }; + + let signed_psbt = create_transaction_spend_outpoint( + &message.confirmed_by.unwrap(), + sp_wallet, + recipient, + Amount::from_sat(fee_rate.into()) + )?; + + let final_tx = signed_psbt.extract_tx()?; + + Ok(createNotificationTransactionReturn { + txid: final_tx.txid().to_string(), + transaction: serialize(&final_tx).to_lower_hex_string(), + new_network_msg: message + }) +} + +#[wasm_bindgen] +pub fn create_notification_transaction( + address: String, + commitment: Option<String>, + fee_rate: u32, +) -> ApiResult<createNotificationTransactionReturn> { + let sp_address: SilentPaymentAddress = address.as_str().try_into()?; + + let connected_user = lock_connected_user()?; + + let sp_wallet: &SpWallet; + if sp_address.is_testnet() { + sp_wallet = connected_user.try_get_recover()?; + } else { + sp_wallet = connected_user.try_get_main()?; + } + + let recipient = Recipient { + address: sp_address.into(), + amount: Amount::from_sat(1200), + nb_outputs: 1, + }; + + let signed_psbt = create_transaction_for_address_with_shared_secret( + recipient, sp_wallet, - message, + commitment.as_deref(), Amount::from_sat(fee_rate.into()), )?; + let psbt = Psbt::from_str(&signed_psbt)?; + + let partial_secret = sp_wallet + .get_client() + .get_partial_secret_from_psbt(&psbt)?; + + let shared_point = shared_secret_point( + &sp_wallet + .get_client() + .get_scan_key() + .public_key(&Secp256k1::signing_only()), + &partial_secret, + ); + + let shared_secret = AnkSharedSecret::new(shared_point); + debug!( "Created transaction with secret {}", shared_secret.to_byte_array().to_lower_hex_string() ); - let mut address2secret: Vec<(String, AnkSharedSecret)> = vec![]; - address2secret.push((sp_address.into(), shared_secret)); - // update our cache - lock_secrets()?.insert(transaction.txid(), address2secret.clone()); + let sp_address2vouts = map_outputs_to_sp_address(&signed_psbt)?; + let recipients_vouts = sp_address2vouts.get::<String>(&address).expect("recipients didn't change").as_slice(); + // for now let's just take the smallest vout that belongs to the recipient + let final_tx = psbt.extract_tx()?; + let mut new_msg = NetworkMessage::default(); + new_msg.commitment = commitment; + new_msg.commited_in = Some(OutPoint { txid: final_tx.txid(), vout: recipients_vouts[0] as u32 }); + new_msg.shared_secret = Some(shared_secret.to_byte_array().to_lower_hex_string()); + new_msg.recipient = Some(address); + new_msg.sender = Some(sp_wallet.get_client().get_receiving_address()); + // plaintext and ciphertext to be added later when sending the encrypted message + lock_messages()?.push(new_msg.clone()); Ok(createNotificationTransactionReturn { - txid: transaction.txid().to_string(), - transaction: serialize(&transaction).to_lower_hex_string(), - address2secret: address2secret.into_iter().collect(), + txid: final_tx.txid().to_string(), + transaction: serialize(&final_tx).to_lower_hex_string(), + new_network_msg: new_msg, }) } @@ -710,6 +866,18 @@ pub fn try_decrypt_with_key(cipher: String, key: String) -> ApiResult<String> { Ok(plain) } +#[wasm_bindgen] +pub fn create_faucet_msg() -> ApiResult<FaucetMessage> { + let user = lock_connected_user()?; + let sp_address = user.try_get_recover()?.get_client().get_receiving_address(); + let faucet_msg = FaucetMessage::new(sp_address); + // we write the commitment in a networkmessage so that we can keep track + let mut network_msg = NetworkMessage::default(); + network_msg.commitment = Some(faucet_msg.commitment.clone()); + lock_messages()?.push(network_msg); + Ok(faucet_msg) +} + #[wasm_bindgen] pub fn create_commitment(payload_to_hash: String) -> String { let mut engine = sha256::HashEngine::default(); @@ -717,3 +885,110 @@ pub fn create_commitment(payload_to_hash: String) -> String { let hash = sha256::Hash::from_engine(engine); hash.to_byte_array().to_lower_hex_string() } + +#[derive(Debug, Serialize, Deserialize, PartialEq, Tsify, Clone)] +pub enum NetworkMessageStatus { + NoStatus, // Default + CipherWaitingTx, + TxWaitingCipher, + SentWaitingConfirmation, + MustSpentConfirmation, + Complete, +} + +impl Default for NetworkMessageStatus { + fn default() -> Self { + Self::NoStatus + } +} + +/// Unique struct for both 4nk messages and notification/key exchange, both rust and ts +/// 1. Faucet: commited_in with nothing else, status is NoStatus +/// 2. notification: +/// 1. sender: ciphertext, plaintext, commited_in, sender, recipient, shared_secret, key +/// 2. receiver (without tx): ciphertext +/// 3. receiver (tx without msg): commited_in, commitment, recipient, shared_secret +/// 4. receiver (receive tx after msg): plaintext, key, sender, commited_in, commitment, recipient, shared_secret +/// 5. receiver (msg after tx): ciphertext, key, plaintext, sender +/// 3. confirmation: +/// 1. receiver (spend the smallest vout that pays him in the first tx): confirmed_by +/// 2. sender (detect a transaction that pays him and spend commited_by): confirmed_by +/// 3. sender toggle status to complete when it spent confirmed_by, receiver when it detects the confirmed_by is spent +#[derive(Debug, Default, Serialize, Deserialize, Tsify, Clone)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[allow(non_camel_case_types)] +pub struct NetworkMessage { + pub id: u32, + pub status: NetworkMessageStatus, + pub ciphertext: Option<String>, // When we receive message we can't decrypt we only have this and commited_in_tx + pub plaintext: Option<String>, // Never None when message sent + pub commited_in: Option<OutPoint>, + pub commitment: Option<String>, // content of the op_return + pub sender: Option<String>, // Never None when message sent + pub recipient: Option<String>, // Never None when message sent + pub shared_secret: Option<String>, // Never None when message sent + pub key: Option<String>, // Never None when message sent + pub confirmed_by: Option<OutPoint>, // If this None, Sender keeps sending + pub timestamp: u64, + pub error: Option<String>, +} + +impl NetworkMessage { + pub fn new() -> Self { + let mut new = NetworkMessage::default(); + let mut buf = [0u8;4]; + thread_rng().fill_bytes(&mut buf); + new.id = u32::from_be_bytes(buf); + new + } + + pub fn new_error(error: String) -> Self { + let mut new = NetworkMessage::default(); + new.error = Some(error); + new + } + + pub fn try_decrypt_cipher(&self, cipher: Vec<u8>) -> Option<Vec<u8>> { + if self.ciphertext.is_some() || self.shared_secret.is_none() { + log::error!( + "Can't try decrypt this message, there's already a ciphertext or no shared secret" + ); + return None; + } + let mut shared_secret = [0u8; 32]; + shared_secret + .copy_from_slice(&Vec::from_hex(self.shared_secret.as_ref().unwrap()).unwrap()); + let aes_decrypt = Aes256Decryption::new(Purpose::Arbitrary, cipher, shared_secret); + + if aes_decrypt.is_err() { + log::error!("Failed to create decrypt object"); + return None; + } + + aes_decrypt.unwrap().decrypt_with_key().ok() + } + + pub fn try_decrypt_with_shared_secret(&self, shared_secret: [u8; 32]) -> Option<Vec<u8>> { + if self.ciphertext.is_none() || self.shared_secret.is_some() { + log::error!( + "Can't try decrypt this message, ciphertext is none or shared_secret already found" + ); + return None; + } + let cipher_bin = Vec::from_hex(self.ciphertext.as_ref().unwrap()); + if cipher_bin.is_err() { + let error = cipher_bin.unwrap_err(); + log::error!("Invalid hex in ciphertext: {}", error.to_string()); + return None; + } + let aes_decrypt = + Aes256Decryption::new(Purpose::Arbitrary, cipher_bin.unwrap(), shared_secret); + + if aes_decrypt.is_err() { + log::error!("Failed to create decrypt object"); + return None; + } + + aes_decrypt.unwrap().decrypt_with_key().ok() + } +} diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index 4802a9f..4980f18 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -1,5 +1,6 @@ #![allow(warnings)] use anyhow::Error; +use api::NetworkMessage; use sdk_common::crypto::AnkSharedSecret; use serde::{Deserialize, Serialize}; use sp_client::bitcoin::{OutPoint, Txid}; @@ -16,37 +17,11 @@ mod peers; mod process; mod user; -/// We map txid with one or n secrets -/// Each secret match one sp address -/// When we first detect a transaction, we can't tell who's the sender, so we like sp address empty -/// When we receive the corresponding message, we get a sp address declaration, we complete here -/// Then when we send the confirmation transaction and got the response we can flip the secret to trusted -pub type Txid2Secrets = HashMap<Txid, Vec<(String, AnkSharedSecret)>>; +pub static NETWORKMESSAGES: OnceLock<Mutex<Vec<NetworkMessage>>> = OnceLock::new(); -pub static SECRETCACHE: OnceLock<Mutex<Txid2Secrets>> = OnceLock::new(); - -pub fn lock_secrets() -> Result<MutexGuard<'static, Txid2Secrets>, Error> { - SECRETCACHE - .get_or_init(|| Mutex::new(Txid2Secrets::new())) - .lock_anyhow() -} - -/// this is to keep track of transaction we already analysed without finding notification -/// This is not critical and there's no need to keep that in persistent storage, as most transactions would only show up twice -/// Worst case is we will scan again transactions when they got into a block -pub static TRANSACTIONCACHE: OnceLock<Mutex<HashSet<Txid>>> = OnceLock::new(); - -pub fn lock_scanned_transactions() -> Result<MutexGuard<'static, HashSet<Txid>>, Error> { - TRANSACTIONCACHE - .get_or_init(|| Mutex::new(HashSet::new())) - .lock_anyhow() -} - -pub static WATCHEDUTXO: OnceLock<Mutex<HashMap<OutPoint, Txid>>> = OnceLock::new(); - -pub fn lock_watched() -> Result<MutexGuard<'static, HashMap<OutPoint, Txid>>, Error> { - WATCHEDUTXO - .get_or_init(|| Mutex::new(HashMap::new())) +pub fn lock_messages() -> Result<MutexGuard<'static, Vec<NetworkMessage>>, Error> { + NETWORKMESSAGES + .get_or_init(|| Mutex::new(vec![])) .lock_anyhow() } diff --git a/package.json b/package.json index 6dabb0b..ed3c7b3 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "build_wasm": "wasm-pack build --out-dir ../../dist/pkg ./crates/sp_client --target bundler", + "build_wasm": "wasm-pack build --out-dir ../../dist/pkg ./crates/sp_client --target bundler --dev", "start": "webpack serve", "build": "webpack" }, diff --git a/src/database.ts b/src/database.ts index 3c2fc30..d5eaa83 100644 --- a/src/database.ts +++ b/src/database.ts @@ -24,6 +24,11 @@ class Database { 'unique': true } }] + }, + AnkMessages: { + name: "messages", + options: {'keyPath': 'id'}, + indices: [] } } diff --git a/src/services.ts b/src/services.ts index 4d95df8..b5ca897 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,4 +1,4 @@ -import { createUserReturn, User, Process, createNotificationTransactionReturn, parse_network_msg, outputs_list, parseNetworkMsgReturn, FaucetMessage, AnkFlag, NewTxMessage, encryptWithNewKeyResult, AnkSharedSecret } from '../dist/pkg/sdk_client'; +import { createUserReturn, User, Process, createNotificationTransactionReturn, parse_network_msg, outputs_list, parseNetworkMsgReturn, FaucetMessage, AnkFlag, NewTxMessage, encryptWithNewKeyResult, AnkSharedSecret, NetworkMessage } from '../dist/pkg/sdk_client'; import IndexedDB from './database' import { WebSocketClient } from './websockets'; @@ -109,30 +109,39 @@ class Services { let notificationInfo = await services.notify_address_for_message(recipientSpAddress, msg_payload); if (notificationInfo) { + let networkMsg = notificationInfo.new_network_msg; + const msgId = notificationInfo.new_network_msg.id; + let shared_secret = ''; + if (networkMsg.shared_secret) { + shared_secret = networkMsg.shared_secret; + } else { + throw 'no shared_secret'; + } let ciphers: string[] = []; console.info('Successfully sent notification transaction'); // Save the secret to db + const indexedDb = await IndexedDB.getInstance(); + const db = await indexedDb.getDb(); + // encrypt the message(s) - for (const [address, ankSharedSecret] of Object.entries(notificationInfo.address2secret)) { - try { - let cipher = await services.encryptData(msg_payload, ankSharedSecret.secret); - ciphers.push(cipher); - } catch (error) { - throw error; - } + try { + const cipher = await services.encryptData(msg_payload, shared_secret); + let updated_msg = notificationInfo.new_network_msg; + updated_msg.plaintext = msg_payload; + updated_msg.ciphertext = cipher; + await indexedDb.writeObject(db, indexedDb.getStoreList().AnkMessages, updated_msg, null); + ciphers.push(cipher); + } catch (error) { + throw error; } const connection = await services.pickWebsocketConnectionRandom(); const flag: AnkFlag = "Unknown"; - // for testing we only take the first cipher - const payload = ciphers.at(0); - if (!payload) { - console.error("No payload"); - return; - } // add peers list // add processes list // send message (transaction in envelope) - connection?.sendMessage(flag, payload); + for (const payload of ciphers) { + connection?.sendMessage(flag, payload); + } } } @@ -397,19 +406,6 @@ class Services { } } - public async checkTransaction(tx: string, tweak_data: string, blkheight: number): Promise<string | null> { - const services = await Services.getInstance(); - - try { - const txid = services.sdkClient.check_transaction_for_silent_payments(tx, blkheight, tweak_data); - await services.updateOwnedOutputsForUser(); - return txid; - } catch (error) { - console.error(error); - return null; - } - } - public async getAllProcessForUser(pre_id: string): Promise<Process[]> { const services = await Services.getInstance(); let user: User; @@ -447,6 +443,17 @@ class Services { return process; } + public async updateMessages(message: NetworkMessage): Promise<void> { + const indexedDb = await IndexedDB.getInstance(); + const db = await indexedDb.getDb(); + + try { + await indexedDb.setObject(db, indexedDb.getStoreList().AnkMessages, message, null); + } catch (error) { + throw error; + } + } + public async updateProcesses(): Promise<void> { const services = await Services.getInstance(); const processList: Process[] = services.sdkClient.get_processes(); @@ -758,10 +765,8 @@ class Services { return null; } try { - const flag: AnkFlag = "Faucet"; - const faucetMsg: FaucetMessage = { - 'sp_address': spaddress - } + const flag: AnkFlag = 'Faucet'; + const faucetMsg = services.sdkClient.create_faucet_msg(); connection.sendMessage(flag, JSON.stringify(faucetMsg)); } catch (error) { console.error("Failed to obtain tokens with relay ", connection.getUrl()); @@ -822,7 +827,7 @@ class Services { let notificationInfo: createNotificationTransactionReturn; try { const feeRate = 1; - notificationInfo = services.sdkClient.create_notification_transaction(sp_address, undefined, feeRate); + notificationInfo = services.sdkClient.create_notification_transaction(sp_address, null, feeRate); } catch (error) { throw new Error(`Failed to create confirmation transaction: ${error}`); } @@ -835,23 +840,11 @@ class Services { return; } - public async notify_address_for_message(sp_address: string, message: string): Promise<createNotificationTransactionReturn | null> { + public async notify_address_for_message(sp_address: string, message: string): Promise<createNotificationTransactionReturn> { const services = await Services.getInstance(); const connection = await services.pickWebsocketConnectionRandom(); if (!connection) { - return null; - } - let user: User; - try { - let possibleUser = await services.getUserInfo(); - if (!possibleUser) { - console.error("No user loaded, please first create a new user or login"); - return null; - } else { - user = possibleUser; - } - } catch (error) { - throw error; + throw 'No available connection'; } try { @@ -866,8 +859,7 @@ class Services { connection.sendMessage(flag, JSON.stringify(newTxMsg)); return notificationInfo; } catch (error) { - console.error("Failed to create notification transaction:", error); - return null + throw 'Failed to create notification transaction:", error'; } } diff --git a/src/websockets.ts b/src/websockets.ts index 0234f56..5067254 100644 --- a/src/websockets.ts +++ b/src/websockets.ts @@ -34,11 +34,14 @@ class WebSocketClient { window.alert(`New tx\n${res.message}`); await services.updateOwnedOutputsForUser(); } else if (res.topic === 'unknown') { - let parsed = JSON.parse(res.message); - let message = parsed['message']; - let sender = parsed['sender']; + let message = res.message['plaintext']; + let sender = res.message['sender']; + if (!message || !sender) { + throw 'Message missing plaintext and/or sender'; + } window.alert(`new message: ${message}\nAsking sender ${sender} to confirm identity...`); console.debug(`sending confirm message to ${sender}`); + await services.updateMessages(res.message); await services.confirm_sender_address(sender); } } catch (error) { From a93aed0edef42745c75c6f65fb81b98d48b1761e Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Wed, 22 May 2024 20:17:53 +0200 Subject: [PATCH 75/90] [bug fix] Working faucet + small fixes --- crates/sp_client/src/api.rs | 255 +++++++++++++----------------------- crates/sp_client/src/lib.rs | 8 +- 2 files changed, 95 insertions(+), 168 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 19c348c..91f8c67 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -34,7 +34,7 @@ use wasm_bindgen::convert::FromWasmAbi; use wasm_bindgen::prelude::*; use sdk_common::network::{ - self, AnkFlag, AnkNetworkMsg, FaucetMessage, NewTxMessage, UnknownMessage, + self, AnkFlag, AnkNetworkMsg, CachedMessage, CachedMessageStatus, FaucetMessage, NewTxMessage, UnknownMessage }; use sdk_common::silentpayments::{ create_transaction, create_transaction_for_address_with_shared_secret, @@ -371,10 +371,10 @@ fn handle_recover_transaction( sp_wallet: &mut SpWallet, tweak_data: PublicKey, fee_rate: u32, -) -> anyhow::Result<NetworkMessage> { +) -> anyhow::Result<CachedMessage> { // We need to look for different case: // 1) faucet - // This one is the simplest, we only care about finding the commitment + // This one is the simplest, we only care about finding the commitment.clone() let op_return = tx.output.iter().find(|o| o.script_pubkey.is_op_return()); let commitment = if op_return.is_none() { vec![] @@ -382,14 +382,18 @@ fn handle_recover_transaction( op_return.unwrap().script_pubkey.as_bytes()[2..].to_vec() }; let commitment_str = commitment.to_lower_hex_string(); - let pos = lock_messages()? - .iter() - .position(|m| m.commitment.as_ref() == Some(&commitment_str)); + { + let mut messages = lock_messages()?; + let pos = messages + .iter() + .position(|m| m.commitment.as_ref() == Some(&commitment_str)); - if pos.is_some() { - let messages = lock_messages()?; - let message = messages.get(pos.unwrap()); - return Ok(message.cloned().unwrap()); + if pos.is_some() { + let mut message = messages.swap_remove(pos.unwrap()); + message.commited_in = updated.into_iter().next().map(|(outpoint, _)| outpoint); + message.status = CachedMessageStatus::FaucetComplete; + return Ok(message); + } } // If we got updates from a transaction, it means that it creates an output to us, spend an output we owned, or both @@ -423,7 +427,7 @@ fn handle_recover_transaction( // If we are receiver, that's pretty much it, just set status to complete if message.recipient == Some(sp_wallet.get_client().get_receiving_address()) { debug_assert!(message.confirmed_by == Some(input.previous_output)); - message.status = NetworkMessageStatus::Complete; + message.status = CachedMessageStatus::Complete; return Ok(message.clone()); } @@ -443,11 +447,11 @@ fn handle_recover_transaction( let mut messages = lock_messages()?; let cipher_pos = messages.iter().position(|m| { - if m.status != NetworkMessageStatus::CipherWaitingTx { + if m.status != CachedMessageStatus::CipherWaitingTx { return false; } m.try_decrypt_with_shared_secret(shared_secret.to_byte_array()) - .is_some() + .is_ok() }); if cipher_pos.is_some() { @@ -468,15 +472,17 @@ fn handle_recover_transaction( return Ok(message.clone()) } else { // store it and wait for the message - let mut new_msg = NetworkMessage::default(); - let (outpoint, output) = utxo_created.iter().next().unwrap(); - new_msg.commited_in = Some(**outpoint); + let mut new_msg = CachedMessage::new(); + debug!("{:?}", utxo_created); + let (outpoint, output) = utxo_created.into_iter().next().expect("utxo_created shouldn't be empty"); + new_msg.commited_in = Some(outpoint.clone()); new_msg.commitment = Some(commitment.to_lower_hex_string()); new_msg.recipient = Some(sp_wallet.get_client().get_receiving_address()); new_msg.shared_secret = Some(shared_secret.to_byte_array().to_lower_hex_string()); - new_msg.status = NetworkMessageStatus::TxWaitingCipher; + new_msg.status = CachedMessageStatus::TxWaitingCipher; lock_messages()?.push(new_msg.clone()); + debug!("returning {:?}", new_msg); return Ok(new_msg.clone()); } } @@ -497,14 +503,14 @@ fn handle_recover_transaction( } } -/// If the transaction has anything to do with us, we create/update the relevant `NetworkMessage` +/// If the transaction has anything to do with us, we create/update the relevant `CachedMessage` /// and return it to caller for persistent storage fn process_transaction( tx_hex: String, blockheight: u32, tweak_data_hex: String, fee_rate: u32, -) -> anyhow::Result<NetworkMessage> { +) -> anyhow::Result<CachedMessage> { let tx = deserialize::<Transaction>(&Vec::from_hex(&tx_hex)?)?; // check that we don't already have scanned the tx @@ -545,16 +551,8 @@ fn process_transaction( Err(anyhow::Error::msg("No output found")) } -#[derive(Tsify, Serialize, Deserialize)] -#[tsify(into_wasm_abi, from_wasm_abi)] -#[allow(non_camel_case_types)] -pub struct parseNetworkMsgReturn { - topic: String, - message: NetworkMessage, -} - #[wasm_bindgen] -pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<parseNetworkMsgReturn> { +pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<CachedMessage> { if let Ok(ank_msg) = serde_json::from_str::<AnkNetworkMsg>(&raw) { match ank_msg.flag { AnkFlag::NewTx => { @@ -570,29 +568,23 @@ pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<parseNetworkMs tx_message.tweak_data.unwrap(), fee_rate, )?; - debug!("{:?}", network_msg); - return Ok(parseNetworkMsgReturn { - topic: ank_msg.flag.as_str().to_owned(), - message: network_msg, - }); + return Ok(network_msg); } AnkFlag::Faucet => unimplemented!(), AnkFlag::Error => { - let error_msg = NetworkMessage::new_error(ank_msg.content); - return Ok(parseNetworkMsgReturn { - topic: AnkFlag::Error.as_str().to_owned(), - message: error_msg, - }) + let error_msg = CachedMessage::new_error(ank_msg.content); + return Ok(error_msg) } AnkFlag::Unknown => { // let's try to decrypt with keys we found in transactions but haven't used yet let mut messages = lock_messages()?; - let cipher = Vec::from_hex(&ank_msg.content)?; + let cipher = Vec::from_hex(&ank_msg.content.trim_matches('\"'))?; let cipher_pos = messages.iter().position(|m| { - if m.status != NetworkMessageStatus::TxWaitingCipher { + debug!("Trying message: {:?}", m); + if m.status != CachedMessageStatus::TxWaitingCipher { return false; } - m.try_decrypt_cipher(cipher.clone()).is_some() + m.try_decrypt_cipher(cipher.clone()).is_ok() }); if cipher_pos.is_some() { let mut message = messages.get_mut(cipher_pos.unwrap()).unwrap(); @@ -601,14 +593,11 @@ pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<parseNetworkMs message.plaintext = Some(unknown_msg.message); message.sender = Some(unknown_msg.sender); message.ciphertext = Some(ank_msg.content); - return Ok(parseNetworkMsgReturn { - topic: AnkFlag::Unknown.as_str().to_owned(), - message: message.clone(), - }); + return Ok(message.clone()); } else { // let's keep it in case we receive the transaction later - let mut new_msg = NetworkMessage::default(); - new_msg.status = NetworkMessageStatus::CipherWaitingTx; + let mut new_msg = CachedMessage::default(); + new_msg.status = CachedMessageStatus::CipherWaitingTx; new_msg.ciphertext = Some(ank_msg.content); messages.push(new_msg); return Err(ApiError { @@ -677,18 +666,61 @@ pub fn is_tx_owned_by_user(pre_id: String, tx: String) -> ApiResult<bool> { #[derive(Tsify, Serialize, Deserialize)] #[tsify(into_wasm_abi, from_wasm_abi)] #[allow(non_camel_case_types)] -pub struct createNotificationTransactionReturn { +pub struct createTransactionReturn { pub txid: String, pub transaction: String, - pub new_network_msg: NetworkMessage, + pub new_network_msg: CachedMessage, +} + +/// This is what we call to answer a confirmation as a sender +#[wasm_bindgen] +pub fn answer_confirmation_transaction( + message: CachedMessage, + fee_rate: u32, +) -> ApiResult<createTransactionReturn> { + if message.recipient.is_none() || message.confirmed_by.is_none() { + return Err(ApiError { message: "Invalid network message".to_owned() }); + } + + let sp_address: SilentPaymentAddress = message.recipient.as_ref().unwrap().as_str().try_into()?; + + let connected_user = lock_connected_user()?; + + let sp_wallet: &SpWallet; + if sp_address.is_testnet() { + sp_wallet = connected_user.try_get_recover()?; + } else { + sp_wallet = connected_user.try_get_main()?; + } + + let recipient = Recipient { + address: sp_address.into(), + amount: Amount::from_sat(0), // we'll set amount to what's available in the confirmed_by output we don't want change + nb_outputs: 1, + }; + + let signed_psbt = create_transaction_spend_outpoint( + &message.confirmed_by.unwrap(), + sp_wallet, + recipient, + Amount::from_sat(fee_rate.into()) + )?; + + let final_tx = signed_psbt.extract_tx()?; + + Ok(createTransactionReturn { + txid: final_tx.txid().to_string(), + transaction: serialize(&final_tx).to_lower_hex_string(), + new_network_msg: message + }) } /// This is what we call to confirm as a receiver #[wasm_bindgen] pub fn create_confirmation_transaction( - message: NetworkMessage, + message: CachedMessage, fee_rate: u32, -) -> ApiResult<createNotificationTransactionReturn> { +) -> ApiResult<createTransactionReturn> { if message.sender.is_none() || message.confirmed_by.is_none() { return Err(ApiError { message: "Invalid network message".to_owned() }); } @@ -706,7 +738,7 @@ pub fn create_confirmation_transaction( let recipient = Recipient { address: sp_address.into(), - amount: Amount::from_sat(1200), + amount: Amount::from_sat(0), nb_outputs: 1, }; @@ -719,7 +751,7 @@ pub fn create_confirmation_transaction( let final_tx = signed_psbt.extract_tx()?; - Ok(createNotificationTransactionReturn { + Ok(createTransactionReturn { txid: final_tx.txid().to_string(), transaction: serialize(&final_tx).to_lower_hex_string(), new_network_msg: message @@ -731,7 +763,7 @@ pub fn create_notification_transaction( address: String, commitment: Option<String>, fee_rate: u32, -) -> ApiResult<createNotificationTransactionReturn> { +) -> ApiResult<createTransactionReturn> { let sp_address: SilentPaymentAddress = address.as_str().try_into()?; let connected_user = lock_connected_user()?; @@ -782,16 +814,17 @@ pub fn create_notification_transaction( let recipients_vouts = sp_address2vouts.get::<String>(&address).expect("recipients didn't change").as_slice(); // for now let's just take the smallest vout that belongs to the recipient let final_tx = psbt.extract_tx()?; - let mut new_msg = NetworkMessage::default(); + let mut new_msg = CachedMessage::default(); new_msg.commitment = commitment; new_msg.commited_in = Some(OutPoint { txid: final_tx.txid(), vout: recipients_vouts[0] as u32 }); new_msg.shared_secret = Some(shared_secret.to_byte_array().to_lower_hex_string()); new_msg.recipient = Some(address); new_msg.sender = Some(sp_wallet.get_client().get_receiving_address()); + new_msg.status = CachedMessageStatus::SentWaitingConfirmation; // plaintext and ciphertext to be added later when sending the encrypted message lock_messages()?.push(new_msg.clone()); - Ok(createNotificationTransactionReturn { + Ok(createTransactionReturn { txid: final_tx.txid().to_string(), transaction: serialize(&final_tx).to_lower_hex_string(), new_network_msg: new_msg, @@ -872,8 +905,9 @@ pub fn create_faucet_msg() -> ApiResult<FaucetMessage> { let sp_address = user.try_get_recover()?.get_client().get_receiving_address(); let faucet_msg = FaucetMessage::new(sp_address); // we write the commitment in a networkmessage so that we can keep track - let mut network_msg = NetworkMessage::default(); + let mut network_msg = CachedMessage::new(); network_msg.commitment = Some(faucet_msg.commitment.clone()); + network_msg.status = CachedMessageStatus::FaucetWaiting; lock_messages()?.push(network_msg); Ok(faucet_msg) } @@ -885,110 +919,3 @@ pub fn create_commitment(payload_to_hash: String) -> String { let hash = sha256::Hash::from_engine(engine); hash.to_byte_array().to_lower_hex_string() } - -#[derive(Debug, Serialize, Deserialize, PartialEq, Tsify, Clone)] -pub enum NetworkMessageStatus { - NoStatus, // Default - CipherWaitingTx, - TxWaitingCipher, - SentWaitingConfirmation, - MustSpentConfirmation, - Complete, -} - -impl Default for NetworkMessageStatus { - fn default() -> Self { - Self::NoStatus - } -} - -/// Unique struct for both 4nk messages and notification/key exchange, both rust and ts -/// 1. Faucet: commited_in with nothing else, status is NoStatus -/// 2. notification: -/// 1. sender: ciphertext, plaintext, commited_in, sender, recipient, shared_secret, key -/// 2. receiver (without tx): ciphertext -/// 3. receiver (tx without msg): commited_in, commitment, recipient, shared_secret -/// 4. receiver (receive tx after msg): plaintext, key, sender, commited_in, commitment, recipient, shared_secret -/// 5. receiver (msg after tx): ciphertext, key, plaintext, sender -/// 3. confirmation: -/// 1. receiver (spend the smallest vout that pays him in the first tx): confirmed_by -/// 2. sender (detect a transaction that pays him and spend commited_by): confirmed_by -/// 3. sender toggle status to complete when it spent confirmed_by, receiver when it detects the confirmed_by is spent -#[derive(Debug, Default, Serialize, Deserialize, Tsify, Clone)] -#[tsify(into_wasm_abi, from_wasm_abi)] -#[allow(non_camel_case_types)] -pub struct NetworkMessage { - pub id: u32, - pub status: NetworkMessageStatus, - pub ciphertext: Option<String>, // When we receive message we can't decrypt we only have this and commited_in_tx - pub plaintext: Option<String>, // Never None when message sent - pub commited_in: Option<OutPoint>, - pub commitment: Option<String>, // content of the op_return - pub sender: Option<String>, // Never None when message sent - pub recipient: Option<String>, // Never None when message sent - pub shared_secret: Option<String>, // Never None when message sent - pub key: Option<String>, // Never None when message sent - pub confirmed_by: Option<OutPoint>, // If this None, Sender keeps sending - pub timestamp: u64, - pub error: Option<String>, -} - -impl NetworkMessage { - pub fn new() -> Self { - let mut new = NetworkMessage::default(); - let mut buf = [0u8;4]; - thread_rng().fill_bytes(&mut buf); - new.id = u32::from_be_bytes(buf); - new - } - - pub fn new_error(error: String) -> Self { - let mut new = NetworkMessage::default(); - new.error = Some(error); - new - } - - pub fn try_decrypt_cipher(&self, cipher: Vec<u8>) -> Option<Vec<u8>> { - if self.ciphertext.is_some() || self.shared_secret.is_none() { - log::error!( - "Can't try decrypt this message, there's already a ciphertext or no shared secret" - ); - return None; - } - let mut shared_secret = [0u8; 32]; - shared_secret - .copy_from_slice(&Vec::from_hex(self.shared_secret.as_ref().unwrap()).unwrap()); - let aes_decrypt = Aes256Decryption::new(Purpose::Arbitrary, cipher, shared_secret); - - if aes_decrypt.is_err() { - log::error!("Failed to create decrypt object"); - return None; - } - - aes_decrypt.unwrap().decrypt_with_key().ok() - } - - pub fn try_decrypt_with_shared_secret(&self, shared_secret: [u8; 32]) -> Option<Vec<u8>> { - if self.ciphertext.is_none() || self.shared_secret.is_some() { - log::error!( - "Can't try decrypt this message, ciphertext is none or shared_secret already found" - ); - return None; - } - let cipher_bin = Vec::from_hex(self.ciphertext.as_ref().unwrap()); - if cipher_bin.is_err() { - let error = cipher_bin.unwrap_err(); - log::error!("Invalid hex in ciphertext: {}", error.to_string()); - return None; - } - let aes_decrypt = - Aes256Decryption::new(Purpose::Arbitrary, cipher_bin.unwrap(), shared_secret); - - if aes_decrypt.is_err() { - log::error!("Failed to create decrypt object"); - return None; - } - - aes_decrypt.unwrap().decrypt_with_key().ok() - } -} diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index 4980f18..3643833 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -1,7 +1,7 @@ #![allow(warnings)] use anyhow::Error; -use api::NetworkMessage; use sdk_common::crypto::AnkSharedSecret; +use sdk_common::network::CachedMessage; use serde::{Deserialize, Serialize}; use sp_client::bitcoin::{OutPoint, Txid}; use sp_client::silentpayments::sending::SilentPaymentAddress; @@ -17,10 +17,10 @@ mod peers; mod process; mod user; -pub static NETWORKMESSAGES: OnceLock<Mutex<Vec<NetworkMessage>>> = OnceLock::new(); +pub static CACHEDMESSAGES: OnceLock<Mutex<Vec<CachedMessage>>> = OnceLock::new(); -pub fn lock_messages() -> Result<MutexGuard<'static, Vec<NetworkMessage>>, Error> { - NETWORKMESSAGES +pub fn lock_messages() -> Result<MutexGuard<'static, Vec<CachedMessage>>, Error> { + CACHEDMESSAGES .get_or_init(|| Mutex::new(vec![])) .lock_anyhow() } From 29c1db586991625adc8825a3d44d42861b7f057d Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Wed, 22 May 2024 20:21:59 +0200 Subject: [PATCH 76/90] database add rmObject --- src/database.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/database.ts b/src/database.ts index d5eaa83..81bb802 100644 --- a/src/database.ts +++ b/src/database.ts @@ -117,6 +117,17 @@ class Database { }); } + public rmObject(db: IDBDatabase, storeName: string, key: IDBValidKey): Promise<void> { + return new Promise((resolve, reject) => { + const transaction = db.transaction(storeName, 'readwrite'); + const store = transaction.objectStore(storeName); + const request = store.delete(key); + + request.onerror = () => reject(request.error); + request.onsuccess = () => resolve(request.result); + }); + } + public getFirstMatchWithIndex<T>(db: IDBDatabase, storeName: string, indexName: string, lookup: string): Promise<T | null> { return new Promise((resolve, reject) => { const transaction = db.transaction(storeName, 'readonly'); From 2f4cd4fb9b320e83a845101dc57ddf162ba162c7 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Wed, 22 May 2024 20:43:31 +0200 Subject: [PATCH 77/90] Reformat websocket message parsing --- src/websockets.ts | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/websockets.ts b/src/websockets.ts index 5067254..67d8434 100644 --- a/src/websockets.ts +++ b/src/websockets.ts @@ -1,5 +1,5 @@ import Services from "./services"; -import { AnkFlag, AnkNetworkMsg, parseNetworkMsgReturn } from "../dist/pkg/sdk_client"; +import { AnkFlag, AnkNetworkMsg, CachedMessage } from "../dist/pkg/sdk_client"; class WebSocketClient { private ws: WebSocket; @@ -25,24 +25,38 @@ class WebSocketClient { (async () => { if (typeof(msgData) === 'string') { - // console.log("Received text message: "+msgData); + console.log("Received text message: "+msgData); try { const feeRate = 1; - let res = await services.parseNetworkMessage(msgData, feeRate); - if (res.topic === 'new_tx') { - // we received a tx - window.alert(`New tx\n${res.message}`); + // By parsing the message, we can link it with existing cached message and return the updated version of the message + let res: CachedMessage = await services.parseNetworkMessage(msgData, feeRate); + console.debug(res); + if (res.status === 'FaucetComplete') { + // we received a faucet tx, there's nothing else to do + window.alert(`New faucet output\n${res.commited_in}`); + await services.removeMessage(res.id); await services.updateOwnedOutputsForUser(); - } else if (res.topic === 'unknown') { - let message = res.message['plaintext']; - let sender = res.message['sender']; - if (!message || !sender) { - throw 'Message missing plaintext and/or sender'; - } - window.alert(`new message: ${message}\nAsking sender ${sender} to confirm identity...`); - console.debug(`sending confirm message to ${sender}`); - await services.updateMessages(res.message); - await services.confirm_sender_address(sender); + } else if (res.status === 'TxWaitingCipher') { + // we received a tx but we don't have the cipher + console.debug(`received notification in output ${res.commited_in}, waiting for cipher message`); + await services.updateMessages(res); + await services.updateOwnedOutputsForUser(); + } else if (res.status === 'CipherWaitingTx') { + // we received a cipher but we don't have the key + console.debug(`received a cipher`); + await services.updateMessages(res); + } else if (res.status === 'SentWaitingConfirmation') { + // We are sender and we're waiting for the challenge that will confirm recipient got the transaction and the message + await services.updateOwnedOutputsForUser(); + } else if (res.status === 'MustSpendConfirmation') { + // we received a challenge for a notification we made + // that means we can stop rebroadcasting the tx and we must spend the challenge to confirm + window.alert(`Spending ${res.confirmed_by} to prove our identity`); + console.debug(`sending confirm message to ${res.recipient}`); + await services.updateMessages(res); + await services.confirm_sender_address(res); + } else { + console.debug('Received an unimplemented valid message'); } } catch (error) { console.error('Received an invalid message:', error); From a251458f04f32228349feacc1a44564ab960a134 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Wed, 22 May 2024 20:53:40 +0200 Subject: [PATCH 78/90] services various improvements --- src/services.ts | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/services.ts b/src/services.ts index b5ca897..16b5a93 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,4 +1,4 @@ -import { createUserReturn, User, Process, createNotificationTransactionReturn, parse_network_msg, outputs_list, parseNetworkMsgReturn, FaucetMessage, AnkFlag, NewTxMessage, encryptWithNewKeyResult, AnkSharedSecret, NetworkMessage } from '../dist/pkg/sdk_client'; +import { createUserReturn, User, Process, createTransactionReturn, parse_network_msg, outputs_list, FaucetMessage, AnkFlag, NewTxMessage, encryptWithNewKeyResult, AnkSharedSecret, CachedMessage } from '../dist/pkg/sdk_client'; import IndexedDB from './database' import { WebSocketClient } from './websockets'; @@ -110,38 +110,31 @@ class Services { let notificationInfo = await services.notify_address_for_message(recipientSpAddress, msg_payload); if (notificationInfo) { let networkMsg = notificationInfo.new_network_msg; - const msgId = notificationInfo.new_network_msg.id; let shared_secret = ''; if (networkMsg.shared_secret) { shared_secret = networkMsg.shared_secret; } else { throw 'no shared_secret'; } - let ciphers: string[] = []; console.info('Successfully sent notification transaction'); - // Save the secret to db - const indexedDb = await IndexedDB.getInstance(); - const db = await indexedDb.getDb(); - + + const connection = await services.pickWebsocketConnectionRandom(); + const flag: AnkFlag = "Unknown"; // encrypt the message(s) + // TODO we'd rather do that in the wasm as part of notify_address_for_message try { const cipher = await services.encryptData(msg_payload, shared_secret); let updated_msg = notificationInfo.new_network_msg; updated_msg.plaintext = msg_payload; updated_msg.ciphertext = cipher; - await indexedDb.writeObject(db, indexedDb.getStoreList().AnkMessages, updated_msg, null); - ciphers.push(cipher); + await services.updateMessages(updated_msg); + connection?.sendMessage(flag, cipher); } catch (error) { throw error; } - const connection = await services.pickWebsocketConnectionRandom(); - const flag: AnkFlag = "Unknown"; // add peers list // add processes list // send message (transaction in envelope) - for (const payload of ciphers) { - connection?.sendMessage(flag, payload); - } } } @@ -322,10 +315,10 @@ class Services { services.attachSubmitListener("form4nk", services.updateAnId); } - public async parseNetworkMessage(raw: string, feeRate: number): Promise<parseNetworkMsgReturn> { + public async parseNetworkMessage(raw: string, feeRate: number): Promise<CachedMessage> { const services = await Services.getInstance(); try { - const msg: parseNetworkMsgReturn = services.sdkClient.parse_network_msg(raw, feeRate); + const msg: CachedMessage = services.sdkClient.parse_network_msg(raw, feeRate); return msg; } catch (error) { throw error; @@ -443,7 +436,7 @@ class Services { return process; } - public async updateMessages(message: NetworkMessage): Promise<void> { + public async updateMessages(message: CachedMessage): Promise<void> { const indexedDb = await IndexedDB.getInstance(); const db = await indexedDb.getDb(); @@ -454,6 +447,17 @@ class Services { } } + public async removeMessage(id: number): Promise<void> { + const indexedDb = await IndexedDB.getInstance(); + const db = await indexedDb.getDb(); + + try { + await indexedDb.rmObject(db, indexedDb.getStoreList().AnkMessages, id); + } catch (error) { + throw error; + } + } + public async updateProcesses(): Promise<void> { const services = await Services.getInstance(); const processList: Process[] = services.sdkClient.get_processes(); @@ -768,6 +772,7 @@ class Services { const flag: AnkFlag = 'Faucet'; const faucetMsg = services.sdkClient.create_faucet_msg(); connection.sendMessage(flag, JSON.stringify(faucetMsg)); + await services.updateMessages(faucetMsg); } catch (error) { console.error("Failed to obtain tokens with relay ", connection.getUrl()); return null; @@ -806,7 +811,7 @@ class Services { } } - public async confirm_sender_address(sp_address: string): Promise<void> { + public async confirm_sender_address(msg: CachedMessage): Promise<void> { const services = await Services.getInstance(); const connection = await services.pickWebsocketConnectionRandom(); if (!connection) { @@ -824,10 +829,10 @@ class Services { throw error; } - let notificationInfo: createNotificationTransactionReturn; + let notificationInfo: createTransactionReturn; try { const feeRate = 1; - notificationInfo = services.sdkClient.create_notification_transaction(sp_address, null, feeRate); + notificationInfo = services.sdkClient.answer_confirmation_transaction(msg, feeRate); } catch (error) { throw new Error(`Failed to create confirmation transaction: ${error}`); } @@ -840,7 +845,7 @@ class Services { return; } - public async notify_address_for_message(sp_address: string, message: string): Promise<createNotificationTransactionReturn> { + public async notify_address_for_message(sp_address: string, message: string): Promise<createTransactionReturn> { const services = await Services.getInstance(); const connection = await services.pickWebsocketConnectionRandom(); if (!connection) { @@ -850,7 +855,7 @@ class Services { try { const feeRate = 1; const commitment = services.sdkClient.create_commitment(message); - let notificationInfo: createNotificationTransactionReturn = services.sdkClient.create_notification_transaction(sp_address, commitment, feeRate); + let notificationInfo: createTransactionReturn = services.sdkClient.create_notification_transaction(sp_address, commitment, feeRate); const flag: AnkFlag = "NewTx"; const newTxMsg: NewTxMessage = { 'transaction': notificationInfo.transaction, From 30c3ec9673a9e8de66ec733bf68b80c1b3400f92 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Wed, 22 May 2024 23:36:18 +0200 Subject: [PATCH 79/90] obtainTokenWithFaucet slight improvement --- crates/sp_client/src/api.rs | 19 +++++++------ src/services.ts | 57 +++++++++++++++++++++---------------- 2 files changed, 44 insertions(+), 32 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 91f8c67..1f54f16 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -900,16 +900,19 @@ pub fn try_decrypt_with_key(cipher: String, key: String) -> ApiResult<String> { } #[wasm_bindgen] -pub fn create_faucet_msg() -> ApiResult<FaucetMessage> { +pub fn create_faucet_msg() -> ApiResult<CachedMessage> { let user = lock_connected_user()?; let sp_address = user.try_get_recover()?.get_client().get_receiving_address(); - let faucet_msg = FaucetMessage::new(sp_address); - // we write the commitment in a networkmessage so that we can keep track - let mut network_msg = CachedMessage::new(); - network_msg.commitment = Some(faucet_msg.commitment.clone()); - network_msg.status = CachedMessageStatus::FaucetWaiting; - lock_messages()?.push(network_msg); - Ok(faucet_msg) + + let mut commitment = [0u8;64]; + thread_rng().fill_bytes(&mut commitment); + + let mut cached_msg = CachedMessage::new(); + cached_msg.recipient = Some(sp_address); + cached_msg.commitment = Some(commitment.to_lower_hex_string()); + cached_msg.status = CachedMessageStatus::FaucetWaiting; + lock_messages()?.push(cached_msg.clone()); + Ok(cached_msg) } #[wasm_bindgen] diff --git a/src/services.ts b/src/services.ts index 16b5a93..7ad857d 100644 --- a/src/services.ts +++ b/src/services.ts @@ -87,7 +87,7 @@ class Services { if (availableAmt < 2000) { try { - await services.obtainTokenWithFaucet(this.sp_address!); + await services.obtainTokenWithFaucet(); } catch (error) { console.error('Failed to obtain faucet token:', error); return; @@ -150,16 +150,14 @@ class Services { return; } } catch (error) { - console.error(error); - return; + throw error; } const passwordElement = document.getElementById("password") as HTMLInputElement; const processElement = document.getElementById("selectProcess") as HTMLSelectElement; if (!passwordElement || !processElement) { - console.error("One or more elements not found"); - return; + throw 'One or more elements not found'; } const password = passwordElement.value; @@ -172,7 +170,12 @@ class Services { const birthday_signet = 50000; const birthday_main = 500000; - let createUserReturn: createUserReturn = services.sdkClient.create_user(password, label, birthday_main, birthday_signet, this.current_process); + let createUserReturn: createUserReturn; + try { + createUserReturn = services.sdkClient.create_user(password, label, birthday_main, birthday_signet, this.current_process); + } catch (error) { + throw error; + } let user = createUserReturn.user; @@ -180,8 +183,7 @@ class Services { // send the shares on the network const revokeData = user.revoke_data; if (!revokeData) { - console.error('Failed to get revoke data from wasm'); - return; + throw 'Failed to get revoke data from wasm'; } // user.shares = []; @@ -192,17 +194,13 @@ class Services { const db = await indexedDb.getDb(); await indexedDb.writeObject(db, indexedDb.getStoreList().AnkUser, user, null); } catch (error) { - console.error("Failed to write user object :", error); + throw `Failed to write user object: ${error}`; } try { - this.sp_address = services.sdkClient.get_recover_address(); - if (this.sp_address) { - console.info('Using sp_address:', this.sp_address); - await services.obtainTokenWithFaucet(this.sp_address); - } + await services.obtainTokenWithFaucet(); } catch (error) { - console.error(error); + throw error; } await services.displayRevokeImage(new Uint8Array(revokeData)); @@ -244,7 +242,7 @@ class Services { this.sp_address = services.sdkClient.get_recover_address(); if (this.sp_address) { console.info('Using sp_address:', this.sp_address); - await services.obtainTokenWithFaucet(this.sp_address); + await services.obtainTokenWithFaucet(); } } } catch (error) { @@ -762,22 +760,33 @@ class Services { } } - public async obtainTokenWithFaucet(spaddress: string): Promise<string | null> { + public async obtainTokenWithFaucet(): Promise<void> { const services = await Services.getInstance(); const connection = await services.pickWebsocketConnectionRandom(); if (!connection) { - return null; + throw 'no available relay connections'; } + + let cachedMsg: CachedMessage; try { const flag: AnkFlag = 'Faucet'; - const faucetMsg = services.sdkClient.create_faucet_msg(); - connection.sendMessage(flag, JSON.stringify(faucetMsg)); - await services.updateMessages(faucetMsg); + cachedMsg = services.sdkClient.create_faucet_msg(); + if (cachedMsg.commitment && cachedMsg.recipient) { + let faucetMsg: FaucetMessage = { + sp_address: cachedMsg.recipient, + commitment: cachedMsg.commitment, + } + connection.sendMessage(flag, JSON.stringify(faucetMsg)); + } } catch (error) { - console.error("Failed to obtain tokens with relay ", connection.getUrl()); - return null; + throw `Failed to obtain tokens with relay ${connection.getUrl()}: ${error}`; + } + + try { + await services.updateMessages(cachedMsg); + } catch (error) { + throw error; } - return null; } public async updateUser(user: User): Promise<void> { From f03abf15b9d3ff414c29f21f0bef3d7f23fac059 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Wed, 22 May 2024 23:37:54 +0200 Subject: [PATCH 80/90] [bug] fix duplicate transactions issue in handle_recover_transaction + refactor --- crates/sp_client/src/api.rs | 192 ++++++++++++++++++------------------ 1 file changed, 96 insertions(+), 96 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 1f54f16..a6f2a66 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -372,9 +372,6 @@ fn handle_recover_transaction( tweak_data: PublicKey, fee_rate: u32, ) -> anyhow::Result<CachedMessage> { - // We need to look for different case: - // 1) faucet - // This one is the simplest, we only care about finding the commitment.clone() let op_return = tx.output.iter().find(|o| o.script_pubkey.is_op_return()); let commitment = if op_return.is_none() { vec![] @@ -382,24 +379,9 @@ fn handle_recover_transaction( op_return.unwrap().script_pubkey.as_bytes()[2..].to_vec() }; let commitment_str = commitment.to_lower_hex_string(); - { - let mut messages = lock_messages()?; - let pos = messages - .iter() - .position(|m| m.commitment.as_ref() == Some(&commitment_str)); - - if pos.is_some() { - let mut message = messages.swap_remove(pos.unwrap()); - message.commited_in = updated.into_iter().next().map(|(outpoint, _)| outpoint); - message.status = CachedMessageStatus::FaucetComplete; - return Ok(message); - } - } // If we got updates from a transaction, it means that it creates an output to us, spend an output we owned, or both - // If we destroyed outputs it means we either notified others, or ask confirmation, or confirm - // We probably creates outputs too in this case because of change - // If we only created outputs it means we are being notified + // Basically a transaction that destroyed utxo is a transaction we sent. let utxo_destroyed: HashMap<&OutPoint, &OwnedOutput> = updated .iter() .filter(|(outpoint, output)| output.spend_status != OutputSpendStatus::Unspent) @@ -409,89 +391,107 @@ fn handle_recover_transaction( .filter(|(outpoint, output)| output.spend_status == OutputSpendStatus::Unspent) .collect(); - // 2) confirmation - // If the transaction spends one outpoint in `commited_in`, it means we are receiving a confirmation for a notification - // if we are receiver, then we must look for `confirmed_by` - // if we owned at least one input or no outputs, we can skip the check - if utxo_destroyed.is_empty() && !utxo_created.is_empty() { - for input in tx.input.iter() { - // Check for each input if it match a known commitment we made as a sender - // OR a confirmation for the receiver - let pos = lock_messages()?.iter().position(|m| { - m.commited_in == Some(input.previous_output) - || m.confirmed_by == Some(input.previous_output) - }); - if pos.is_some() { - let mut messages = lock_messages()?; - let message = messages.get_mut(pos.unwrap()).unwrap(); - // If we are receiver, that's pretty much it, just set status to complete - if message.recipient == Some(sp_wallet.get_client().get_receiving_address()) { - debug_assert!(message.confirmed_by == Some(input.previous_output)); - message.status = CachedMessageStatus::Complete; - return Ok(message.clone()); - } + let mut messages = lock_messages()?; - // sender needs to spent it back again to receiver - let (outpoint, output) = utxo_created.iter().next().unwrap(); - - // If we are sender, then we must update the confirmed_by field - message.confirmed_by = Some(**outpoint); - - // Caller must interpret this message as "spend confirmed_by outpoint to receiver" - return Ok(message.clone()); + // empty utxo_destroyed means we received this transaction + if utxo_destroyed.is_empty() { + // We first check for faucet transactions + if let Some(pos) = messages.iter().position(|m| { + if m.status == CachedMessageStatus::FaucetWaiting { + m.commitment.as_ref() == Some(&commitment_str) } else { - // we are being notified - let shared_point = - shared_secret_point(&tweak_data, &sp_wallet.get_client().get_scan_key()); - let shared_secret = AnkSharedSecret::new(shared_point); - - let mut messages = lock_messages()?; - let cipher_pos = messages.iter().position(|m| { - if m.status != CachedMessageStatus::CipherWaitingTx { - return false; - } - m.try_decrypt_with_shared_secret(shared_secret.to_byte_array()) - .is_ok() - }); - - if cipher_pos.is_some() { - let message = messages.get_mut(cipher_pos.unwrap()).unwrap(); - let (outpoint, output) = utxo_created.iter().next().unwrap(); - message.commited_in = Some(**outpoint); - message.shared_secret = - Some(shared_secret.to_byte_array().to_lower_hex_string()); - message.commitment = Some(commitment.to_lower_hex_string()); - - let plaintext = message - .try_decrypt_with_shared_secret(shared_secret.to_byte_array()) - .unwrap(); - let unknown_msg: UnknownMessage = serde_json::from_slice(&plaintext)?; - message.plaintext = Some(unknown_msg.message); - message.sender = Some(unknown_msg.sender); - message.recipient = Some(sp_wallet.get_client().get_receiving_address()); - return Ok(message.clone()) - } else { - // store it and wait for the message - let mut new_msg = CachedMessage::new(); - debug!("{:?}", utxo_created); - let (outpoint, output) = utxo_created.into_iter().next().expect("utxo_created shouldn't be empty"); - new_msg.commited_in = Some(outpoint.clone()); - new_msg.commitment = Some(commitment.to_lower_hex_string()); - new_msg.recipient = Some(sp_wallet.get_client().get_receiving_address()); - new_msg.shared_secret = - Some(shared_secret.to_byte_array().to_lower_hex_string()); - new_msg.status = CachedMessageStatus::TxWaitingCipher; - lock_messages()?.push(new_msg.clone()); - debug!("returning {:?}", new_msg); - return Ok(new_msg.clone()); - } + false + } + }) + { + let message = messages.get_mut(pos).unwrap(); + match message.status { + CachedMessageStatus::FaucetWaiting => { + message.status = CachedMessageStatus::FaucetComplete; + message.commited_in = utxo_created.into_iter().next().map(|(outpoint, _)| *outpoint); + return Ok(message.clone()); + }, + CachedMessageStatus::FaucetComplete => return Ok(message.clone()), + _ => () } } - unreachable!("Transaction with no inputs"); + + // we inspect inputs looking for links with previous tx + for input in tx.input.iter() { + if let Some(pos) = messages.iter().position(|m| { + m.confirmed_by == Some(input.previous_output) + }) + { + let message = messages.get_mut(pos).unwrap(); + // If we are receiver, that's pretty much it, just set status to complete + message.status = CachedMessageStatus::Complete; + return Ok(message.clone()); + } else if let Some(pos) = messages.iter().position(|m| { + m.commited_in == Some(input.previous_output) + }) + { + // sender needs to spent it back again to receiver + let (outpoint, output) = utxo_created.into_iter().next().unwrap(); + + let message = messages.get_mut(pos).unwrap(); + + message.confirmed_by = Some(outpoint.clone()); + message.status = CachedMessageStatus::MustSpendConfirmation; + + // Caller must interpret this message as "do spend confirmed_by outpoint to receiver" + return Ok(message.clone()); + } + } + + // if we've found nothing we are being notified + let shared_point = + shared_secret_point(&tweak_data, &sp_wallet.get_client().get_scan_key()); + let shared_secret = AnkSharedSecret::new(shared_point); + + if let Some(cipher_pos) = messages.iter().position(|m| { + if m.status != CachedMessageStatus::CipherWaitingTx { + return false; + } + m.try_decrypt_with_shared_secret(shared_secret.to_byte_array()) + .is_ok() + }) + { + let message = messages.get_mut(cipher_pos).unwrap(); + + let (outpoint, output) = utxo_created.into_iter().next().unwrap(); + + message.commited_in = Some(outpoint.clone()); + message.shared_secret = + Some(shared_secret.to_byte_array().to_lower_hex_string()); + message.commitment = Some(commitment_str); + + let plaintext = message + .try_decrypt_with_shared_secret(shared_secret.to_byte_array()) + .unwrap(); + let unknown_msg: UnknownMessage = serde_json::from_slice(&plaintext)?; + message.plaintext = Some(unknown_msg.message); + message.sender = Some(unknown_msg.sender); + message.recipient = Some(sp_wallet.get_client().get_receiving_address()); + message.status = CachedMessageStatus::ReceivedMustConfirm; + + return Ok(message.clone()) + } else { + // store it and wait for the message + let mut new_msg = CachedMessage::new(); + let (outpoint, output) = utxo_created.into_iter().next().expect("utxo_created shouldn't be empty"); + new_msg.commited_in = Some(outpoint.clone()); + new_msg.commitment = Some(commitment.to_lower_hex_string()); + new_msg.recipient = Some(sp_wallet.get_client().get_receiving_address()); + new_msg.shared_secret = + Some(shared_secret.to_byte_array().to_lower_hex_string()); + new_msg.status = CachedMessageStatus::TxWaitingCipher; + messages.push(new_msg.clone()); + return Ok(new_msg.clone()); + } } else { - // We are sender of a notification transaction + // We are sender of a transaction // We only need to return the message - if let Some(message) = lock_messages()?.iter() + if let Some(message) = messages.iter() .find(|m| { m.commitment.as_ref() == Some(&commitment_str) }) From c3e435a22854f0f0a83f981aa32d979d703c7886 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Thu, 23 May 2024 15:36:40 +0200 Subject: [PATCH 81/90] [bug] don't panic if there's a main/revoke wallet loaded --- crates/sp_client/src/api.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index a6f2a66..b3b4b34 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -540,12 +540,16 @@ fn process_transaction( if let Ok(main) = connected_user.try_get_mut_main() { let updated = main.update_wallet_with_transaction(&tx, blockheight, tweak_data)?; - unimplemented!(); + if updated.len() > 0 { + unimplemented!(); + } } if let Ok(revoke) = connected_user.try_get_mut_revoke() { let updated = revoke.update_wallet_with_transaction(&tx, blockheight, tweak_data)?; - unimplemented!(); + if updated.len() > 0 { + unimplemented!(); + } } Err(anyhow::Error::msg("No output found")) @@ -596,7 +600,7 @@ pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<CachedMessage> return Ok(message.clone()); } else { // let's keep it in case we receive the transaction later - let mut new_msg = CachedMessage::default(); + let mut new_msg = CachedMessage::new(); new_msg.status = CachedMessageStatus::CipherWaitingTx; new_msg.ciphertext = Some(ank_msg.content); messages.push(new_msg); From bc6f95a98fc9933eb0fe8dd1f3732ed3c16676d8 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Fri, 24 May 2024 22:40:40 +0200 Subject: [PATCH 82/90] Message processing heavy refactoring --- crates/sp_client/src/api.rs | 206 +++++++++++++++++++++++------------- src/services.ts | 111 ++++++++----------- src/websockets.ts | 15 ++- 3 files changed, 191 insertions(+), 141 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index b3b4b34..d1edc07 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -25,7 +25,8 @@ use sp_client::bitcoin::key::Secp256k1; use sp_client::bitcoin::secp256k1::ecdh::shared_secret_point; use sp_client::bitcoin::secp256k1::{PublicKey, SecretKey}; use sp_client::bitcoin::{Amount, Network, OutPoint, Psbt, Transaction, Txid}; -use sp_client::silentpayments::Error as SpError; +use sp_client::silentpayments::utils as sp_utils; +use sp_client::silentpayments::{Error as SpError, Network as SpNetwork}; use serde::{Deserialize, Serialize}; use sp_client::silentpayments::sending::SilentPaymentAddress; @@ -34,11 +35,12 @@ use wasm_bindgen::convert::FromWasmAbi; use wasm_bindgen::prelude::*; use sdk_common::network::{ - self, AnkFlag, AnkNetworkMsg, CachedMessage, CachedMessageStatus, FaucetMessage, NewTxMessage, UnknownMessage + self, AnkFlag, AnkNetworkMsg, CachedMessage, CachedMessageStatus, FaucetMessage, NewTxMessage, + UnknownMessage, }; use sdk_common::silentpayments::{ create_transaction, create_transaction_for_address_with_shared_secret, - create_transaction_spend_outpoint, map_outputs_to_sp_address + create_transaction_spend_outpoint, map_outputs_to_sp_address, }; use sp_client::spclient::{ @@ -402,23 +404,29 @@ fn handle_recover_transaction( } else { false } - }) - { + }) { let message = messages.get_mut(pos).unwrap(); match message.status { CachedMessageStatus::FaucetWaiting => { message.status = CachedMessageStatus::FaucetComplete; - message.commited_in = utxo_created.into_iter().next().map(|(outpoint, _)| *outpoint); + message.commited_in = utxo_created + .into_iter() + .next() + .map(|(outpoint, _)| *outpoint); return Ok(message.clone()); - }, + } + // Actually this is unreachable CachedMessageStatus::FaucetComplete => return Ok(message.clone()), - _ => () + _ => (), } } // we inspect inputs looking for links with previous tx for input in tx.input.iter() { - if let Some(pos) = messages.iter().position(|m| { + if let Some(pos) = messages + .iter() + .position(|m| { + debug!("{:?}", Some(input.previous_output)); m.confirmed_by == Some(input.previous_output) }) { @@ -426,9 +434,9 @@ fn handle_recover_transaction( // If we are receiver, that's pretty much it, just set status to complete message.status = CachedMessageStatus::Complete; return Ok(message.clone()); - } else if let Some(pos) = messages.iter().position(|m| { - m.commited_in == Some(input.previous_output) - }) + } else if let Some(pos) = messages + .iter() + .position(|m| m.commited_in == Some(input.previous_output)) { // sender needs to spent it back again to receiver let (outpoint, output) = utxo_created.into_iter().next().unwrap(); @@ -444,9 +452,16 @@ fn handle_recover_transaction( } // if we've found nothing we are being notified - let shared_point = - shared_secret_point(&tweak_data, &sp_wallet.get_client().get_scan_key()); - let shared_secret = AnkSharedSecret::new(shared_point); + let shared_point = sp_utils::receiving::calculate_shared_point( + &tweak_data, + &sp_wallet.get_client().get_scan_key(), + ); + let shared_secret = AnkSharedSecret::new(PublicKey::from_slice(&shared_point)?); + + debug!( + "Shared secret: {}", + shared_secret.to_byte_array().to_lower_hex_string() + ); if let Some(cipher_pos) = messages.iter().position(|m| { if m.status != CachedMessageStatus::CipherWaitingTx { @@ -454,15 +469,13 @@ fn handle_recover_transaction( } m.try_decrypt_with_shared_secret(shared_secret.to_byte_array()) .is_ok() - }) - { + }) { let message = messages.get_mut(cipher_pos).unwrap(); let (outpoint, output) = utxo_created.into_iter().next().unwrap(); message.commited_in = Some(outpoint.clone()); - message.shared_secret = - Some(shared_secret.to_byte_array().to_lower_hex_string()); + message.shared_secret = Some(shared_secret.to_byte_array().to_lower_hex_string()); message.commitment = Some(commitment_str); let plaintext = message @@ -474,16 +487,18 @@ fn handle_recover_transaction( message.recipient = Some(sp_wallet.get_client().get_receiving_address()); message.status = CachedMessageStatus::ReceivedMustConfirm; - return Ok(message.clone()) + return Ok(message.clone()); } else { // store it and wait for the message let mut new_msg = CachedMessage::new(); - let (outpoint, output) = utxo_created.into_iter().next().expect("utxo_created shouldn't be empty"); + let (outpoint, output) = utxo_created + .into_iter() + .next() + .expect("utxo_created shouldn't be empty"); new_msg.commited_in = Some(outpoint.clone()); new_msg.commitment = Some(commitment.to_lower_hex_string()); new_msg.recipient = Some(sp_wallet.get_client().get_receiving_address()); - new_msg.shared_secret = - Some(shared_secret.to_byte_array().to_lower_hex_string()); + new_msg.shared_secret = Some(shared_secret.to_byte_array().to_lower_hex_string()); new_msg.status = CachedMessageStatus::TxWaitingCipher; messages.push(new_msg.clone()); return Ok(new_msg.clone()); @@ -491,14 +506,15 @@ fn handle_recover_transaction( } else { // We are sender of a transaction // We only need to return the message - if let Some(message) = messages.iter() - .find(|m| { - m.commitment.as_ref() == Some(&commitment_str) - }) + if let Some(message) = messages + .iter() + .find(|m| m.commitment.as_ref() == Some(&commitment_str)) { return Ok(message.clone()); } else { - return Err(anyhow::Error::msg("We spent a transaction for a commitment we don't know")); + return Err(anyhow::Error::msg( + "We spent a transaction for a commitment we don't know", + )); } } } @@ -577,7 +593,7 @@ pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<CachedMessage> AnkFlag::Faucet => unimplemented!(), AnkFlag::Error => { let error_msg = CachedMessage::new_error(ank_msg.content); - return Ok(error_msg) + return Ok(error_msg); } AnkFlag::Unknown => { // let's try to decrypt with keys we found in transactions but haven't used yet @@ -597,16 +613,15 @@ pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<CachedMessage> message.plaintext = Some(unknown_msg.message); message.sender = Some(unknown_msg.sender); message.ciphertext = Some(ank_msg.content); + message.status = CachedMessageStatus::ReceivedMustConfirm; return Ok(message.clone()); } else { // let's keep it in case we receive the transaction later let mut new_msg = CachedMessage::new(); new_msg.status = CachedMessageStatus::CipherWaitingTx; new_msg.ciphertext = Some(ank_msg.content); - messages.push(new_msg); - return Err(ApiError { - message: "Can't decrypt message".to_owned(), - }); + messages.push(new_msg.clone()); + return Ok(new_msg); } } _ => unimplemented!(), @@ -676,22 +691,33 @@ pub struct createTransactionReturn { pub new_network_msg: CachedMessage, } -/// This is what we call to answer a confirmation as a sender +/// This is what we call to answer a confirmation as a sender #[wasm_bindgen] pub fn answer_confirmation_transaction( - message: CachedMessage, + message_id: u32, fee_rate: u32, ) -> ApiResult<createTransactionReturn> { - if message.recipient.is_none() || message.confirmed_by.is_none() { - return Err(ApiError { message: "Invalid network message".to_owned() }); + let mut messages = lock_messages()?; + let message: &mut CachedMessage; + if let Some(m) = messages.iter_mut().find(|m| m.id == message_id) { + if m.sender.is_none() || m.commited_in.is_none() { + return Err(ApiError { + message: "Invalid network message".to_owned(), + }); + } + + message = m; + } else { + return Err(ApiError { message: format!("Can't find message for id {}", message_id) }); } - let sp_address: SilentPaymentAddress = message.recipient.as_ref().unwrap().as_str().try_into()?; + let sp_address: SilentPaymentAddress = + message.recipient.as_ref().unwrap().as_str().try_into()?; let connected_user = lock_connected_user()?; let sp_wallet: &SpWallet; - if sp_address.is_testnet() { + if sp_address.get_network() != SpNetwork::Mainnet { sp_wallet = connected_user.try_get_recover()?; } else { sp_wallet = connected_user.try_get_main()?; @@ -703,38 +729,53 @@ pub fn answer_confirmation_transaction( nb_outputs: 1, }; + let confirmed_by = message.confirmed_by.clone().unwrap(); + let commited_in = message.commited_in.clone().unwrap(); + let signed_psbt = create_transaction_spend_outpoint( - &message.confirmed_by.unwrap(), - sp_wallet, - recipient, - Amount::from_sat(fee_rate.into()) + &confirmed_by, + sp_wallet, + recipient, + &commited_in.txid, + Amount::from_sat(fee_rate.into()), )?; let final_tx = signed_psbt.extract_tx()?; + message.status = CachedMessageStatus::Complete; + Ok(createTransactionReturn { txid: final_tx.txid().to_string(), transaction: serialize(&final_tx).to_lower_hex_string(), - new_network_msg: message + new_network_msg: message.clone(), }) } /// This is what we call to confirm as a receiver #[wasm_bindgen] pub fn create_confirmation_transaction( - message: CachedMessage, + message_id: u32, fee_rate: u32, ) -> ApiResult<createTransactionReturn> { - if message.sender.is_none() || message.confirmed_by.is_none() { - return Err(ApiError { message: "Invalid network message".to_owned() }); + let mut messages = lock_messages()?; + let message: &mut CachedMessage; + if let Some(m) = messages.iter_mut().find(|m| m.id == message_id) { + if m.sender.is_none() || m.commited_in.is_none() { + return Err(ApiError { + message: "Invalid network message".to_owned(), + }); + } + + message = m; + } else { + return Err(ApiError { message: format!("Can't find message for id {}", message_id) }); } let sp_address: SilentPaymentAddress = message.sender.as_ref().unwrap().as_str().try_into()?; - let connected_user = lock_connected_user()?; let sp_wallet: &SpWallet; - if sp_address.is_testnet() { + if sp_address.get_network() != SpNetwork::Mainnet { sp_wallet = connected_user.try_get_recover()?; } else { sp_wallet = connected_user.try_get_main()?; @@ -746,26 +787,38 @@ pub fn create_confirmation_transaction( nb_outputs: 1, }; + let commited_in = message.commited_in.clone().unwrap(); + let signed_psbt = create_transaction_spend_outpoint( - &message.confirmed_by.unwrap(), - sp_wallet, - recipient, - Amount::from_sat(fee_rate.into()) + &commited_in, + sp_wallet, + recipient, + &commited_in.txid, + Amount::from_sat(fee_rate.into()), )?; + // what's the vout of the output sent to sender? + let sp_address2vouts = map_outputs_to_sp_address(&signed_psbt.to_string())?; + let recipients_vouts = sp_address2vouts + .get::<String>(&sp_address.into()) + .expect("recipients didn't change") + .as_slice(); + let final_tx = signed_psbt.extract_tx()?; + message.confirmed_by = Some(OutPoint { txid: final_tx.txid(), vout: recipients_vouts[0] as u32 }); + Ok(createTransactionReturn { txid: final_tx.txid().to_string(), transaction: serialize(&final_tx).to_lower_hex_string(), - new_network_msg: message + new_network_msg: message.clone(), }) } #[wasm_bindgen] pub fn create_notification_transaction( address: String, - commitment: Option<String>, + message: UnknownMessage, fee_rate: u32, ) -> ApiResult<createTransactionReturn> { let sp_address: SilentPaymentAddress = address.as_str().try_into()?; @@ -773,7 +826,7 @@ pub fn create_notification_transaction( let connected_user = lock_connected_user()?; let sp_wallet: &SpWallet; - if sp_address.is_testnet() { + if sp_address.get_network() != SpNetwork::Mainnet { sp_wallet = connected_user.try_get_recover()?; } else { sp_wallet = connected_user.try_get_main()?; @@ -785,42 +838,47 @@ pub fn create_notification_transaction( nb_outputs: 1, }; + let commitment = create_commitment(serde_json::to_string(&message)?); + let signed_psbt = create_transaction_for_address_with_shared_secret( recipient, sp_wallet, - commitment.as_deref(), + Some(&commitment), Amount::from_sat(fee_rate.into()), )?; let psbt = Psbt::from_str(&signed_psbt)?; - let partial_secret = sp_wallet - .get_client() - .get_partial_secret_from_psbt(&psbt)?; + let partial_secret = sp_wallet.get_client().get_partial_secret_from_psbt(&psbt)?; - let shared_point = shared_secret_point( - &sp_wallet - .get_client() - .get_scan_key() - .public_key(&Secp256k1::signing_only()), - &partial_secret, - ); + let shared_point = + sp_utils::sending::calculate_shared_point(&sp_address.get_scan_key(), &partial_secret); - let shared_secret = AnkSharedSecret::new(shared_point); + let shared_secret = AnkSharedSecret::new(PublicKey::from_slice(&shared_point)?); debug!( "Created transaction with secret {}", shared_secret.to_byte_array().to_lower_hex_string() ); + let cipher = encrypt_with_key(serde_json::to_string(&message)?, shared_secret.to_byte_array().to_lower_hex_string())?; + // update our cache let sp_address2vouts = map_outputs_to_sp_address(&signed_psbt)?; - let recipients_vouts = sp_address2vouts.get::<String>(&address).expect("recipients didn't change").as_slice(); + let recipients_vouts = sp_address2vouts + .get::<String>(&address) + .expect("recipients didn't change") + .as_slice(); // for now let's just take the smallest vout that belongs to the recipient let final_tx = psbt.extract_tx()?; - let mut new_msg = CachedMessage::default(); - new_msg.commitment = commitment; - new_msg.commited_in = Some(OutPoint { txid: final_tx.txid(), vout: recipients_vouts[0] as u32 }); + let mut new_msg = CachedMessage::new(); + new_msg.plaintext = Some(message.message); + new_msg.ciphertext = Some(cipher); + new_msg.commitment = Some(commitment); + new_msg.commited_in = Some(OutPoint { + txid: final_tx.txid(), + vout: recipients_vouts[0] as u32, + }); new_msg.shared_secret = Some(shared_secret.to_byte_array().to_lower_hex_string()); new_msg.recipient = Some(address); new_msg.sender = Some(sp_wallet.get_client().get_receiving_address()); @@ -908,11 +966,11 @@ pub fn create_faucet_msg() -> ApiResult<CachedMessage> { let user = lock_connected_user()?; let sp_address = user.try_get_recover()?.get_client().get_receiving_address(); - let mut commitment = [0u8;64]; + let mut commitment = [0u8; 64]; thread_rng().fill_bytes(&mut commitment); let mut cached_msg = CachedMessage::new(); - cached_msg.recipient = Some(sp_address); + cached_msg.recipient = Some(sp_address); cached_msg.commitment = Some(commitment.to_lower_hex_string()); cached_msg.status = CachedMessageStatus::FaucetWaiting; lock_messages()?.push(cached_msg.clone()); diff --git a/src/services.ts b/src/services.ts index 7ad857d..d02fb70 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,4 +1,4 @@ -import { createUserReturn, User, Process, createTransactionReturn, parse_network_msg, outputs_list, FaucetMessage, AnkFlag, NewTxMessage, encryptWithNewKeyResult, AnkSharedSecret, CachedMessage } from '../dist/pkg/sdk_client'; +import { createUserReturn, User, Process, createTransactionReturn, parse_network_msg, outputs_list, FaucetMessage, AnkFlag, NewTxMessage, encryptWithNewKeyResult, AnkSharedSecret, CachedMessage, UnknownMessage } from '../dist/pkg/sdk_client'; import IndexedDB from './database' import { WebSocketClient } from './websockets'; @@ -105,36 +105,24 @@ class Services { const recipientSpAddress = spAddressElement.value; const message = messageElement.value; - const msg_payload = JSON.stringify({sender: this.sp_address, message: message}); + const msg_payload: UnknownMessage = {sender: this.sp_address!, message: message}; let notificationInfo = await services.notify_address_for_message(recipientSpAddress, msg_payload); if (notificationInfo) { let networkMsg = notificationInfo.new_network_msg; - let shared_secret = ''; - if (networkMsg.shared_secret) { - shared_secret = networkMsg.shared_secret; - } else { - throw 'no shared_secret'; - } - console.info('Successfully sent notification transaction'); + console.debug(networkMsg); const connection = await services.pickWebsocketConnectionRandom(); const flag: AnkFlag = "Unknown"; - // encrypt the message(s) - // TODO we'd rather do that in the wasm as part of notify_address_for_message try { - const cipher = await services.encryptData(msg_payload, shared_secret); - let updated_msg = notificationInfo.new_network_msg; - updated_msg.plaintext = msg_payload; - updated_msg.ciphertext = cipher; - await services.updateMessages(updated_msg); - connection?.sendMessage(flag, cipher); + // send message (transaction in envelope) + await services.updateMessages(networkMsg); + connection?.sendMessage(flag, networkMsg.ciphertext!); } catch (error) { throw error; } // add peers list // add processes list - // send message (transaction in envelope) } } @@ -820,6 +808,41 @@ class Services { } } + public async answer_confirmation_message(msg: CachedMessage): Promise<void> { + const services = await Services.getInstance(); + const connection = await services.pickWebsocketConnectionRandom(); + if (!connection) { + throw new Error("No connection to relay"); + } + let user: User; + try { + let possibleUser = await services.getUserInfo(); + if (!possibleUser) { + throw new Error("No user loaded, please first create a new user or login"); + } else { + user = possibleUser; + } + } catch (error) { + throw error; + } + + let notificationInfo: createTransactionReturn; + try { + const feeRate = 1; + notificationInfo = services.sdkClient.answer_confirmation_transaction(msg.id, feeRate); + } catch (error) { + throw new Error(`Failed to create confirmation transaction: ${error}`); + } + const flag: AnkFlag = "NewTx"; + const newTxMsg: NewTxMessage = { + 'transaction': notificationInfo.transaction, + 'tweak_data': null + } + connection.sendMessage(flag, JSON.stringify(newTxMsg)); + await services.updateMessages(notificationInfo.new_network_msg); + return; + } + public async confirm_sender_address(msg: CachedMessage): Promise<void> { const services = await Services.getInstance(); const connection = await services.pickWebsocketConnectionRandom(); @@ -841,7 +864,7 @@ class Services { let notificationInfo: createTransactionReturn; try { const feeRate = 1; - notificationInfo = services.sdkClient.answer_confirmation_transaction(msg, feeRate); + notificationInfo = services.sdkClient.create_confirmation_transaction(msg.id, feeRate); } catch (error) { throw new Error(`Failed to create confirmation transaction: ${error}`); } @@ -851,10 +874,11 @@ class Services { 'tweak_data': null } connection.sendMessage(flag, JSON.stringify(newTxMsg)); + await services.updateMessages(notificationInfo.new_network_msg); return; } - public async notify_address_for_message(sp_address: string, message: string): Promise<createTransactionReturn> { + public async notify_address_for_message(sp_address: string, message: UnknownMessage): Promise<createTransactionReturn> { const services = await Services.getInstance(); const connection = await services.pickWebsocketConnectionRandom(); if (!connection) { @@ -863,62 +887,19 @@ class Services { try { const feeRate = 1; - const commitment = services.sdkClient.create_commitment(message); - let notificationInfo: createTransactionReturn = services.sdkClient.create_notification_transaction(sp_address, commitment, feeRate); + let notificationInfo: createTransactionReturn = services.sdkClient.create_notification_transaction(sp_address, message, feeRate); const flag: AnkFlag = "NewTx"; const newTxMsg: NewTxMessage = { 'transaction': notificationInfo.transaction, 'tweak_data': null } connection.sendMessage(flag, JSON.stringify(newTxMsg)); + console.info('Successfully sent notification transaction'); return notificationInfo; } catch (error) { throw 'Failed to create notification transaction:", error'; } } - - // public async encryptData(data: string, sharedSecret: Record<string, AnkSharedSecret>): Promise<Map<string, string>> { - // const services = await Services.getInstance(); - // let msg_cipher: encryptWithNewKeyResult; - // try { - // msg_cipher = services.sdkClient.encrypt_with_new_key(data); - // } catch (error) { - // throw error; - // } - - // let res = new Map<string, string>(); - // for (const [recipient, secret] of Object.entries(sharedSecret)) { - // try { - // const key = secret.secret; - // const encryptedKey: string = await services.sdkClient.encrypt_with_key(msg_cipher.key, key); - // res.set(recipient, encryptedKey); - // } catch (error) { - // throw new Error(`Failed to encrypt key for recipient ${recipient}: ${error}`); - // } - // } - - // return res; - // } - public async encryptData(data: string, key: string): Promise<string> { - const services = await Services.getInstance(); - - try { - let res: string = services.sdkClient.encrypt_with_key(data, key); - return res; - } catch (error) { - throw error; - } - } - - public async decryptData(cipher: string, key: string): Promise<string> { - const services = await Services.getInstance(); - try { - let res = services.sdkClient.try_decrypt_with_key(cipher, key); - return res; - } catch (error) { - throw error; - } - } } export default Services; diff --git a/src/websockets.ts b/src/websockets.ts index 67d8434..6cc35c5 100644 --- a/src/websockets.ts +++ b/src/websockets.ts @@ -34,7 +34,7 @@ class WebSocketClient { if (res.status === 'FaucetComplete') { // we received a faucet tx, there's nothing else to do window.alert(`New faucet output\n${res.commited_in}`); - await services.removeMessage(res.id); + await services.updateMessages(res); await services.updateOwnedOutputsForUser(); } else if (res.status === 'TxWaitingCipher') { // we received a tx but we don't have the cipher @@ -47,6 +47,7 @@ class WebSocketClient { await services.updateMessages(res); } else if (res.status === 'SentWaitingConfirmation') { // We are sender and we're waiting for the challenge that will confirm recipient got the transaction and the message + await services.updateMessages(res); await services.updateOwnedOutputsForUser(); } else if (res.status === 'MustSpendConfirmation') { // we received a challenge for a notification we made @@ -54,7 +55,17 @@ class WebSocketClient { window.alert(`Spending ${res.confirmed_by} to prove our identity`); console.debug(`sending confirm message to ${res.recipient}`); await services.updateMessages(res); + await services.answer_confirmation_message(res); + } else if (res.status === 'ReceivedMustConfirm') { + // we found a notification and decrypted the cipher + window.alert(`Received message from ${res.sender}\n${res.plaintext}`); + // we must spend the commited_in output to sender + await services.updateMessages(res); await services.confirm_sender_address(res); + } else if (res.status === 'Complete') { + window.alert(`Received confirmation that ${res.sender} is the author of message ${res.plaintext}`) + await services.updateMessages(res); + await services.updateOwnedOutputsForUser(); } else { console.debug('Received an unimplemented valid message'); } @@ -88,7 +99,7 @@ class WebSocketClient { // console.debug("Sending message:", JSON.stringify(networkMessage)); this.ws.send(JSON.stringify(networkMessage)); } else { - console.error('WebSocket is not open. ReadyState:', this.ws.readyState); + console.warn('WebSocket is not open. ReadyState:', this.ws.readyState); this.messageQueue.push(message); } } From cca4e742c055ff4da7e0f20886b5a30399e726f6 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Mon, 27 May 2024 12:14:53 +0200 Subject: [PATCH 83/90] websocket check for error message --- src/websockets.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/websockets.ts b/src/websockets.ts index 6cc35c5..04d47ef 100644 --- a/src/websockets.ts +++ b/src/websockets.ts @@ -31,7 +31,11 @@ class WebSocketClient { // By parsing the message, we can link it with existing cached message and return the updated version of the message let res: CachedMessage = await services.parseNetworkMessage(msgData, feeRate); console.debug(res); - if (res.status === 'FaucetComplete') { + if (res.status === 'Error') { + if (res.error) { + console.error(res.error); + } + } else if (res.status === 'FaucetComplete') { // we received a faucet tx, there's nothing else to do window.alert(`New faucet output\n${res.commited_in}`); await services.updateMessages(res); From b875b64a0a9cc44330d637f6181d2a536354d050 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Mon, 27 May 2024 12:17:39 +0200 Subject: [PATCH 84/90] adapt api to new AnkMsg types --- crates/sp_client/src/api.rs | 58 ++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index d1edc07..19c49ba 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -36,7 +36,7 @@ use wasm_bindgen::prelude::*; use sdk_common::network::{ self, AnkFlag, AnkNetworkMsg, CachedMessage, CachedMessageStatus, FaucetMessage, NewTxMessage, - UnknownMessage, + CipherMessage, }; use sdk_common::silentpayments::{ create_transaction, create_transaction_for_address_with_shared_secret, @@ -49,7 +49,7 @@ use sp_client::spclient::{ use sp_client::spclient::{SpWallet, SpendKey}; use crate::user::{lock_connected_user, User, UserWallets, CONNECTED_USER}; -use crate::{images, lock_messages}; +use crate::{images, lock_messages, CACHEDMESSAGES}; use crate::process::Process; @@ -481,9 +481,9 @@ fn handle_recover_transaction( let plaintext = message .try_decrypt_with_shared_secret(shared_secret.to_byte_array()) .unwrap(); - let unknown_msg: UnknownMessage = serde_json::from_slice(&plaintext)?; - message.plaintext = Some(unknown_msg.message); - message.sender = Some(unknown_msg.sender); + let cipher_msg: CipherMessage = serde_json::from_slice(&plaintext)?; + message.plaintext = Some(cipher_msg.message); + message.sender = Some(cipher_msg.sender); message.recipient = Some(sp_wallet.get_client().get_receiving_address()); message.status = CachedMessageStatus::ReceivedMustConfirm; @@ -529,18 +529,6 @@ fn process_transaction( ) -> anyhow::Result<CachedMessage> { let tx = deserialize::<Transaction>(&Vec::from_hex(&tx_hex)?)?; - // check that we don't already have scanned the tx - if let Some(_) = lock_messages()?.iter().find(|message| { - if let Some(outpoint) = message.commited_in { - if outpoint.txid == tx.txid() { - return true; - } - } - return false; - }) { - return Err(anyhow::Error::msg("Transaction already scanned")); - } - let tweak_data = PublicKey::from_str(&tweak_data_hex)?; let mut connected_user = lock_connected_user()?; @@ -571,12 +559,26 @@ fn process_transaction( Err(anyhow::Error::msg("No output found")) } +fn process_new_tx_error(msg: NewTxMessage) -> anyhow::Result<CachedMessage> { + // how do we match this error with the cached message? + unimplemented!(); +} + #[wasm_bindgen] pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<CachedMessage> { if let Ok(ank_msg) = serde_json::from_str::<AnkNetworkMsg>(&raw) { match ank_msg.flag { AnkFlag::NewTx => { let tx_message = serde_json::from_str::<NewTxMessage>(&ank_msg.content)?; + if let Some(ref error) = tx_message.error { + // Transaction failed to broadcast + // we can retry later or check the availability of our spent output, depending on the actual error + // we should probably look up the cached message and record the error + log::error!("{}", error); + // let updated = process_new_tx_error(tx_message)?; + let updated = CachedMessage::new(); + return Ok(updated); + } if tx_message.tweak_data.is_none() { return Err(ApiError { message: "Missing tweak_data".to_owned(), @@ -590,12 +592,14 @@ pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<CachedMessage> )?; return Ok(network_msg); } - AnkFlag::Faucet => unimplemented!(), - AnkFlag::Error => { - let error_msg = CachedMessage::new_error(ank_msg.content); - return Ok(error_msg); - } - AnkFlag::Unknown => { + AnkFlag::Faucet => { + let faucet_msg = serde_json::from_str::<FaucetMessage>(&ank_msg.content)?; + if let Some(error) = faucet_msg.error { + debug!("Faucet msg returned with an error: {}", error); + } + unimplemented!(); + }, + AnkFlag::Cipher => { // let's try to decrypt with keys we found in transactions but haven't used yet let mut messages = lock_messages()?; let cipher = Vec::from_hex(&ank_msg.content.trim_matches('\"'))?; @@ -609,9 +613,9 @@ pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<CachedMessage> if cipher_pos.is_some() { let mut message = messages.get_mut(cipher_pos.unwrap()).unwrap(); let plain = message.try_decrypt_cipher(cipher).unwrap(); - let unknown_msg: UnknownMessage = serde_json::from_slice(&plain)?; - message.plaintext = Some(unknown_msg.message); - message.sender = Some(unknown_msg.sender); + let cipher_msg: CipherMessage = serde_json::from_slice(&plain)?; + message.plaintext = Some(cipher_msg.message); + message.sender = Some(cipher_msg.sender); message.ciphertext = Some(ank_msg.content); message.status = CachedMessageStatus::ReceivedMustConfirm; return Ok(message.clone()); @@ -818,7 +822,7 @@ pub fn create_confirmation_transaction( #[wasm_bindgen] pub fn create_notification_transaction( address: String, - message: UnknownMessage, + message: CipherMessage, fee_rate: u32, ) -> ApiResult<createTransactionReturn> { let sp_address: SilentPaymentAddress = address.as_str().try_into()?; From 184d4af31fc3ebfdbd76d3bdba3e00275cec997f Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Mon, 27 May 2024 14:41:33 +0200 Subject: [PATCH 85/90] [bug] false negative when decrypting message --- crates/sp_client/src/api.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 19c49ba..c2ea56e 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -463,25 +463,27 @@ fn handle_recover_transaction( shared_secret.to_byte_array().to_lower_hex_string() ); + let mut plaintext: Vec<u8> = vec![]; if let Some(cipher_pos) = messages.iter().position(|m| { if m.status != CachedMessageStatus::CipherWaitingTx { return false; } - m.try_decrypt_with_shared_secret(shared_secret.to_byte_array()) - .is_ok() + let res = m.try_decrypt_with_shared_secret(shared_secret.to_byte_array()); + if res.is_ok() { + plaintext = res.unwrap(); + return true; + } else { + return false; + } }) { let message = messages.get_mut(cipher_pos).unwrap(); let (outpoint, output) = utxo_created.into_iter().next().unwrap(); + let cipher_msg: CipherMessage = serde_json::from_slice(&plaintext)?; message.commited_in = Some(outpoint.clone()); message.shared_secret = Some(shared_secret.to_byte_array().to_lower_hex_string()); message.commitment = Some(commitment_str); - - let plaintext = message - .try_decrypt_with_shared_secret(shared_secret.to_byte_array()) - .unwrap(); - let cipher_msg: CipherMessage = serde_json::from_slice(&plaintext)?; message.plaintext = Some(cipher_msg.message); message.sender = Some(cipher_msg.sender); message.recipient = Some(sp_wallet.get_client().get_receiving_address()); From 1f689d33c38afd0331ab79b28132890a496f9750 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Mon, 27 May 2024 14:42:32 +0200 Subject: [PATCH 86/90] conform service.ts to new message format --- src/services.ts | 18 +++++++++++------- src/websockets.ts | 6 +----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/services.ts b/src/services.ts index d02fb70..81298d3 100644 --- a/src/services.ts +++ b/src/services.ts @@ -1,4 +1,4 @@ -import { createUserReturn, User, Process, createTransactionReturn, parse_network_msg, outputs_list, FaucetMessage, AnkFlag, NewTxMessage, encryptWithNewKeyResult, AnkSharedSecret, CachedMessage, UnknownMessage } from '../dist/pkg/sdk_client'; +import { createUserReturn, User, Process, createTransactionReturn, outputs_list, FaucetMessage, AnkFlag, NewTxMessage, CipherMessage, CachedMessage } from '../dist/pkg/sdk_client'; import IndexedDB from './database' import { WebSocketClient } from './websockets'; @@ -105,7 +105,7 @@ class Services { const recipientSpAddress = spAddressElement.value; const message = messageElement.value; - const msg_payload: UnknownMessage = {sender: this.sp_address!, message: message}; + const msg_payload: CipherMessage = {sender: this.sp_address!, message: message, error: null}; let notificationInfo = await services.notify_address_for_message(recipientSpAddress, msg_payload); if (notificationInfo) { @@ -113,7 +113,7 @@ class Services { console.debug(networkMsg); const connection = await services.pickWebsocketConnectionRandom(); - const flag: AnkFlag = "Unknown"; + const flag: AnkFlag = 'Cipher'; try { // send message (transaction in envelope) await services.updateMessages(networkMsg); @@ -763,6 +763,7 @@ class Services { let faucetMsg: FaucetMessage = { sp_address: cachedMsg.recipient, commitment: cachedMsg.commitment, + error: null, } connection.sendMessage(flag, JSON.stringify(faucetMsg)); } @@ -836,7 +837,8 @@ class Services { const flag: AnkFlag = "NewTx"; const newTxMsg: NewTxMessage = { 'transaction': notificationInfo.transaction, - 'tweak_data': null + 'tweak_data': null, + 'error': null, } connection.sendMessage(flag, JSON.stringify(newTxMsg)); await services.updateMessages(notificationInfo.new_network_msg); @@ -871,14 +873,15 @@ class Services { const flag: AnkFlag = "NewTx"; const newTxMsg: NewTxMessage = { 'transaction': notificationInfo.transaction, - 'tweak_data': null + 'tweak_data': null, + 'error': null, } connection.sendMessage(flag, JSON.stringify(newTxMsg)); await services.updateMessages(notificationInfo.new_network_msg); return; } - public async notify_address_for_message(sp_address: string, message: UnknownMessage): Promise<createTransactionReturn> { + public async notify_address_for_message(sp_address: string, message: CipherMessage): Promise<createTransactionReturn> { const services = await Services.getInstance(); const connection = await services.pickWebsocketConnectionRandom(); if (!connection) { @@ -891,7 +894,8 @@ class Services { const flag: AnkFlag = "NewTx"; const newTxMsg: NewTxMessage = { 'transaction': notificationInfo.transaction, - 'tweak_data': null + 'tweak_data': null, + 'error': null, } connection.sendMessage(flag, JSON.stringify(newTxMsg)); console.info('Successfully sent notification transaction'); diff --git a/src/websockets.ts b/src/websockets.ts index 04d47ef..6cc35c5 100644 --- a/src/websockets.ts +++ b/src/websockets.ts @@ -31,11 +31,7 @@ class WebSocketClient { // By parsing the message, we can link it with existing cached message and return the updated version of the message let res: CachedMessage = await services.parseNetworkMessage(msgData, feeRate); console.debug(res); - if (res.status === 'Error') { - if (res.error) { - console.error(res.error); - } - } else if (res.status === 'FaucetComplete') { + if (res.status === 'FaucetComplete') { // we received a faucet tx, there's nothing else to do window.alert(`New faucet output\n${res.commited_in}`); await services.updateMessages(res); From de133cc0a3ec71e281709fa3a0908d162793cd1a Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Mon, 27 May 2024 15:59:29 +0200 Subject: [PATCH 87/90] [experimental] identify transaction we sent according to commitment value --- crates/sp_client/src/api.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index c2ea56e..9a5d7c1 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -508,9 +508,33 @@ fn handle_recover_transaction( } else { // We are sender of a transaction // We only need to return the message + // eiter this is notification, a challenge, or response to a challenge + // if notification, commitment is the same than in the message + // if challenge or response, commitment is H(commitment | b_scan), b_scan being different depending on who we are if let Some(message) = messages .iter() - .find(|m| m.commitment.as_ref() == Some(&commitment_str)) + .find(|m| { + if commitment.is_empty() || m.commitment.is_none() { return false } + match m.status { + CachedMessageStatus::SentWaitingConfirmation => { + // commitment we're looking for is simply what's in the message + m.commitment.as_ref().map(|c| Vec::from_hex(&c).unwrap()).unwrap() == commitment + }, + CachedMessageStatus::MustSpendConfirmation | CachedMessageStatus::ReceivedMustConfirm => { + // we compute the potential commitment + let m_commitment = m.commitment.as_ref().map(|c| Vec::from_hex(&c).unwrap()).unwrap(); + let mut buf = [0u8;64]; + buf[..32].copy_from_slice(&m_commitment); + buf[32..].copy_from_slice(&sp_wallet.get_client().get_scan_key().secret_bytes()); + + let mut engine = sha256::HashEngine::default(); + engine.write_all(&buf).unwrap(); + let hash = sha256::Hash::from_engine(engine); + hash.to_byte_array().to_vec() == commitment + }, + _ => return false + } + }) { return Ok(message.clone()); } else { From 7da19aa28c5570c2017c56310c33c5c8f0c70444 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Tue, 28 May 2024 11:31:18 +0200 Subject: [PATCH 88/90] Import sp_client through sdk_common --- crates/sp_client/Cargo.toml | 2 - crates/sp_client/src/api.rs | 139 ++++++++++++++++++-------------- crates/sp_client/src/images.rs | 2 +- crates/sp_client/src/process.rs | 2 +- crates/sp_client/src/user.rs | 22 ++--- 5 files changed, 91 insertions(+), 76 deletions(-) diff --git a/crates/sp_client/Cargo.toml b/crates/sp_client/Cargo.toml index 264bd2f..3999e06 100644 --- a/crates/sp_client/Cargo.toml +++ b/crates/sp_client/Cargo.toml @@ -8,8 +8,6 @@ name = "sdk_client" crate-type = ["cdylib"] [dependencies] -sp_client= { path = "../../../sp-client" } -# sp_client= { git = "https://github.com/Sosthene00/sp-client", branch = "sp_client" } anyhow = "1.0" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0" diff --git a/crates/sp_client/src/api.rs b/crates/sp_client/src/api.rs index 9a5d7c1..16ddacc 100644 --- a/crates/sp_client/src/api.rs +++ b/crates/sp_client/src/api.rs @@ -14,39 +14,41 @@ use anyhow::Error as AnyhowError; use sdk_common::crypto::{ AeadCore, Aes256Decryption, Aes256Encryption, Aes256Gcm, AnkSharedSecret, KeyInit, Purpose, }; +use sdk_common::sp_client::bitcoin::blockdata::fee_rate; +use sdk_common::sp_client::bitcoin::consensus::{deserialize, serialize}; +use sdk_common::sp_client::bitcoin::hashes::HashEngine; +use sdk_common::sp_client::bitcoin::hashes::{sha256, Hash}; +use sdk_common::sp_client::bitcoin::hex::{ + parse, DisplayHex, FromHex, HexToArrayError, HexToBytesError, +}; +use sdk_common::sp_client::bitcoin::key::Secp256k1; +use sdk_common::sp_client::bitcoin::secp256k1::ecdh::shared_secret_point; +use sdk_common::sp_client::bitcoin::secp256k1::{PublicKey, SecretKey}; +use sdk_common::sp_client::bitcoin::{Amount, Network, OutPoint, Psbt, Transaction, Txid}; +use sdk_common::sp_client::silentpayments::utils as sp_utils; +use sdk_common::sp_client::silentpayments::{Error as SpError, Network as SpNetwork}; use serde_json::{Error as SerdeJsonError, Value}; use shamir::SecretData; -use sp_client::bitcoin::blockdata::fee_rate; -use sp_client::bitcoin::consensus::{deserialize, serialize}; -use sp_client::bitcoin::hashes::HashEngine; -use sp_client::bitcoin::hashes::{sha256, Hash}; -use sp_client::bitcoin::hex::{parse, DisplayHex, FromHex, HexToArrayError, HexToBytesError}; -use sp_client::bitcoin::key::Secp256k1; -use sp_client::bitcoin::secp256k1::ecdh::shared_secret_point; -use sp_client::bitcoin::secp256k1::{PublicKey, SecretKey}; -use sp_client::bitcoin::{Amount, Network, OutPoint, Psbt, Transaction, Txid}; -use sp_client::silentpayments::utils as sp_utils; -use sp_client::silentpayments::{Error as SpError, Network as SpNetwork}; +use sdk_common::sp_client::silentpayments::sending::SilentPaymentAddress; use serde::{Deserialize, Serialize}; -use sp_client::silentpayments::sending::SilentPaymentAddress; use tsify::Tsify; use wasm_bindgen::convert::FromWasmAbi; use wasm_bindgen::prelude::*; use sdk_common::network::{ - self, AnkFlag, AnkNetworkMsg, CachedMessage, CachedMessageStatus, FaucetMessage, NewTxMessage, - CipherMessage, + self, AnkFlag, AnkNetworkMsg, CachedMessage, CachedMessageStatus, CipherMessage, FaucetMessage, + NewTxMessage, }; use sdk_common::silentpayments::{ create_transaction, create_transaction_for_address_with_shared_secret, create_transaction_spend_outpoint, map_outputs_to_sp_address, }; -use sp_client::spclient::{ +use sdk_common::sp_client::spclient::{ derive_keys_from_seed, OutputList, OutputSpendStatus, OwnedOutput, Recipient, SpClient, }; -use sp_client::spclient::{SpWallet, SpendKey}; +use sdk_common::sp_client::spclient::{SpWallet, SpendKey}; use crate::user::{lock_connected_user, User, UserWallets, CONNECTED_USER}; use crate::{images, lock_messages, CACHEDMESSAGES}; @@ -102,32 +104,32 @@ impl From<HexToArrayError> for ApiError { } } -impl From<sp_client::bitcoin::psbt::PsbtParseError> for ApiError { - fn from(value: sp_client::bitcoin::psbt::PsbtParseError) -> Self { +impl From<sdk_common::sp_client::bitcoin::psbt::PsbtParseError> for ApiError { + fn from(value: sdk_common::sp_client::bitcoin::psbt::PsbtParseError) -> Self { ApiError { message: value.to_string(), } } } -impl From<sp_client::bitcoin::psbt::ExtractTxError> for ApiError { - fn from(value: sp_client::bitcoin::psbt::ExtractTxError) -> Self { +impl From<sdk_common::sp_client::bitcoin::psbt::ExtractTxError> for ApiError { + fn from(value: sdk_common::sp_client::bitcoin::psbt::ExtractTxError) -> Self { ApiError { message: value.to_string(), } } } -impl From<sp_client::bitcoin::secp256k1::Error> for ApiError { - fn from(value: sp_client::bitcoin::secp256k1::Error) -> Self { +impl From<sdk_common::sp_client::bitcoin::secp256k1::Error> for ApiError { + fn from(value: sdk_common::sp_client::bitcoin::secp256k1::Error) -> Self { ApiError { message: value.to_string(), } } } -impl From<sp_client::bitcoin::consensus::encode::Error> for ApiError { - fn from(value: sp_client::bitcoin::consensus::encode::Error) -> Self { +impl From<sdk_common::sp_client::bitcoin::consensus::encode::Error> for ApiError { + fn from(value: sdk_common::sp_client::bitcoin::consensus::encode::Error) -> Self { ApiError { message: value.to_string(), } @@ -423,13 +425,10 @@ fn handle_recover_transaction( // we inspect inputs looking for links with previous tx for input in tx.input.iter() { - if let Some(pos) = messages - .iter() - .position(|m| { - debug!("{:?}", Some(input.previous_output)); - m.confirmed_by == Some(input.previous_output) - }) - { + if let Some(pos) = messages.iter().position(|m| { + debug!("{:?}", Some(input.previous_output)); + m.confirmed_by == Some(input.previous_output) + }) { let message = messages.get_mut(pos).unwrap(); // If we are receiver, that's pretty much it, just set status to complete message.status = CachedMessageStatus::Complete; @@ -511,31 +510,40 @@ fn handle_recover_transaction( // eiter this is notification, a challenge, or response to a challenge // if notification, commitment is the same than in the message // if challenge or response, commitment is H(commitment | b_scan), b_scan being different depending on who we are - if let Some(message) = messages - .iter() - .find(|m| { - if commitment.is_empty() || m.commitment.is_none() { return false } - match m.status { - CachedMessageStatus::SentWaitingConfirmation => { - // commitment we're looking for is simply what's in the message - m.commitment.as_ref().map(|c| Vec::from_hex(&c).unwrap()).unwrap() == commitment - }, - CachedMessageStatus::MustSpendConfirmation | CachedMessageStatus::ReceivedMustConfirm => { - // we compute the potential commitment - let m_commitment = m.commitment.as_ref().map(|c| Vec::from_hex(&c).unwrap()).unwrap(); - let mut buf = [0u8;64]; - buf[..32].copy_from_slice(&m_commitment); - buf[32..].copy_from_slice(&sp_wallet.get_client().get_scan_key().secret_bytes()); - - let mut engine = sha256::HashEngine::default(); - engine.write_all(&buf).unwrap(); - let hash = sha256::Hash::from_engine(engine); - hash.to_byte_array().to_vec() == commitment - }, - _ => return false + if let Some(message) = messages.iter().find(|m| { + if commitment.is_empty() || m.commitment.is_none() { + return false; + } + match m.status { + CachedMessageStatus::SentWaitingConfirmation => { + // commitment we're looking for is simply what's in the message + m.commitment + .as_ref() + .map(|c| Vec::from_hex(&c).unwrap()) + .unwrap() + == commitment } - }) - { + CachedMessageStatus::MustSpendConfirmation + | CachedMessageStatus::ReceivedMustConfirm => { + // we compute the potential commitment + let m_commitment = m + .commitment + .as_ref() + .map(|c| Vec::from_hex(&c).unwrap()) + .unwrap(); + let mut buf = [0u8; 64]; + buf[..32].copy_from_slice(&m_commitment); + buf[32..] + .copy_from_slice(&sp_wallet.get_client().get_scan_key().secret_bytes()); + + let mut engine = sha256::HashEngine::default(); + engine.write_all(&buf).unwrap(); + let hash = sha256::Hash::from_engine(engine); + hash.to_byte_array().to_vec() == commitment + } + _ => return false, + } + }) { return Ok(message.clone()); } else { return Err(anyhow::Error::msg( @@ -624,7 +632,7 @@ pub fn parse_network_msg(raw: String, fee_rate: u32) -> ApiResult<CachedMessage> debug!("Faucet msg returned with an error: {}", error); } unimplemented!(); - }, + } AnkFlag::Cipher => { // let's try to decrypt with keys we found in transactions but haven't used yet let mut messages = lock_messages()?; @@ -738,7 +746,9 @@ pub fn answer_confirmation_transaction( message = m; } else { - return Err(ApiError { message: format!("Can't find message for id {}", message_id) }); + return Err(ApiError { + message: format!("Can't find message for id {}", message_id), + }); } let sp_address: SilentPaymentAddress = @@ -798,7 +808,9 @@ pub fn create_confirmation_transaction( message = m; } else { - return Err(ApiError { message: format!("Can't find message for id {}", message_id) }); + return Err(ApiError { + message: format!("Can't find message for id {}", message_id), + }); } let sp_address: SilentPaymentAddress = message.sender.as_ref().unwrap().as_str().try_into()?; @@ -836,7 +848,10 @@ pub fn create_confirmation_transaction( let final_tx = signed_psbt.extract_tx()?; - message.confirmed_by = Some(OutPoint { txid: final_tx.txid(), vout: recipients_vouts[0] as u32 }); + message.confirmed_by = Some(OutPoint { + txid: final_tx.txid(), + vout: recipients_vouts[0] as u32, + }); Ok(createTransactionReturn { txid: final_tx.txid().to_string(), @@ -891,7 +906,10 @@ pub fn create_notification_transaction( shared_secret.to_byte_array().to_lower_hex_string() ); - let cipher = encrypt_with_key(serde_json::to_string(&message)?, shared_secret.to_byte_array().to_lower_hex_string())?; + let cipher = encrypt_with_key( + serde_json::to_string(&message)?, + shared_secret.to_byte_array().to_lower_hex_string(), + )?; // update our cache let sp_address2vouts = map_outputs_to_sp_address(&signed_psbt)?; @@ -913,7 +931,6 @@ pub fn create_notification_transaction( new_msg.recipient = Some(address); new_msg.sender = Some(sp_wallet.get_client().get_receiving_address()); new_msg.status = CachedMessageStatus::SentWaitingConfirmation; - // plaintext and ciphertext to be added later when sending the encrypted message lock_messages()?.push(new_msg.clone()); Ok(createTransactionReturn { diff --git a/crates/sp_client/src/images.rs b/crates/sp_client/src/images.rs index f0e0698..75f3a0d 100644 --- a/crates/sp_client/src/images.rs +++ b/crates/sp_client/src/images.rs @@ -1,7 +1,7 @@ use anyhow::{Error, Result}; use img_parts::{jpeg::Jpeg, Bytes, ImageEXIF}; +use sdk_common::sp_client::bitcoin::secp256k1::SecretKey; use serde::{Deserialize, Serialize}; -use sp_client::bitcoin::secp256k1::SecretKey; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct BackUpImage(Vec<u8>); diff --git a/crates/sp_client/src/process.rs b/crates/sp_client/src/process.rs index 36e1c47..25eed24 100644 --- a/crates/sp_client/src/process.rs +++ b/crates/sp_client/src/process.rs @@ -1,8 +1,8 @@ use std::fmt::DebugStruct; +use sdk_common::sp_client::silentpayments::sending::SilentPaymentAddress; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; -use sp_client::silentpayments::sending::SilentPaymentAddress; use tsify::Tsify; use wasm_bindgen::prelude::*; diff --git a/crates/sp_client/src/user.rs b/crates/sp_client/src/user.rs index 5038554..f7af595 100644 --- a/crates/sp_client/src/user.rs +++ b/crates/sp_client/src/user.rs @@ -1,13 +1,13 @@ use anyhow::{Error, Result}; use rand::{self, thread_rng, Rng, RngCore}; +use sdk_common::sp_client::bitcoin::hashes::Hash; +use sdk_common::sp_client::bitcoin::hashes::HashEngine; +use sdk_common::sp_client::bitcoin::hex::{DisplayHex, FromHex}; +use sdk_common::sp_client::bitcoin::secp256k1::SecretKey; +use sdk_common::sp_client::bitcoin::secp256k1::ThirtyTwoByteHash; +use sdk_common::sp_client::spclient::SpClient; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; -use sp_client::bitcoin::hashes::Hash; -use sp_client::bitcoin::hashes::HashEngine; -use sp_client::bitcoin::hex::{DisplayHex, FromHex}; -use sp_client::bitcoin::secp256k1::SecretKey; -use sp_client::bitcoin::secp256k1::ThirtyTwoByteHash; -use sp_client::spclient::SpClient; use tsify::Tsify; use wasm_bindgen::prelude::*; @@ -18,11 +18,11 @@ use std::io::{Cursor, Read, Write}; use std::str::FromStr; use std::sync::{Mutex, MutexGuard, OnceLock}; -use sp_client::bitcoin::secp256k1::constants::SECRET_KEY_SIZE; -use sp_client::silentpayments::bitcoin_hashes::sha256; -use sp_client::silentpayments::sending::SilentPaymentAddress; -use sp_client::spclient::SpendKey; -use sp_client::spclient::{OutputList, SpWallet}; +use sdk_common::sp_client::bitcoin::secp256k1::constants::SECRET_KEY_SIZE; +use sdk_common::sp_client::silentpayments::bitcoin_hashes::sha256; +use sdk_common::sp_client::silentpayments::sending::SilentPaymentAddress; +use sdk_common::sp_client::spclient::SpendKey; +use sdk_common::sp_client::spclient::{OutputList, SpWallet}; use crate::peers::Peer; use crate::user; From 834e6b3749f8c118230869290675dfbb4566c5c7 Mon Sep 17 00:00:00 2001 From: Sosthene <contact@sosthene.net> Date: Tue, 28 May 2024 11:51:30 +0200 Subject: [PATCH 89/90] rm dead code --- crates/sp_client/src/Prd_list.rs | 73 -------------------------------- crates/sp_client/src/lib.rs | 3 -- 2 files changed, 76 deletions(-) delete mode 100644 crates/sp_client/src/Prd_list.rs diff --git a/crates/sp_client/src/Prd_list.rs b/crates/sp_client/src/Prd_list.rs deleted file mode 100644 index 9ed63d0..0000000 --- a/crates/sp_client/src/Prd_list.rs +++ /dev/null @@ -1,73 +0,0 @@ -use serde::{Deserialize, Serialize}; -use serde_json::{json, Value}; -use sp_client::bitcoin::PublicKey; -//use sp_client::silentpayments::sending::SilentPaymentAddress; -use std::marker::Copy; -use tsify::Tsify; -use wasm_bindgen::prelude::*; - -#[wasm_bindgen] -#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq, Copy)] -pub enum Role { - Manager, - #[default] - User, -} - -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] -pub struct SilentPaymentAddress { - version: u8, - scan_pubkey: PublicKey, - m_pubkey: PublicKey, - is_testnet: bool, -} - -#[derive(Debug, Copy, Clone)] -pub struct ItemMember { - pub role: Role, - pub sp_address: SilentPaymentAddress, - //pre_id: hash(password, part1) - //shard, - //priv_key_mainnet_spend, (enc) - //priv_key_mainnet_scan, - //priv_key_signet_scan, -} - -impl ItemMember { - pub fn new(role: Role, sp_address: SilentPaymentAddress) -> Self { - ItemMember { role, sp_address } - } -} - -#[derive(Debug, Clone)] -pub struct Prdlist { - //pub id: String, - //pub version: String, - pub gestionnaires: Vec<ItemMember>, - // pub gestionnaires: Box<Vec<ItemMember>>, -} - -#[derive(Serialize)] -#[wasm_bindgen] -struct RequestBody { - message: String, -} - -pub fn send_PrdRequest(prdlist: &Prdlist) -> Result<(), JsValue> { - let managers: Vec<&ItemMember> = prdlist - .gestionnaires - .iter() - .filter(|m| m.role == Role::Manager) - .collect(); - for manager in managers { - let request_body = RequestBody { - message: "Asking for the Prd list".to_string(), - }; - - let json_body = serde_json::to_string(&request_body).map_err(|e| { - JsValue::from_str(&format!("Failed to serialize request body: {:?}", e)) - })?; - println!("Sending request to manager {:?}", manager.sp_address); - } - Ok(()) -} diff --git a/crates/sp_client/src/lib.rs b/crates/sp_client/src/lib.rs index 3643833..1168492 100644 --- a/crates/sp_client/src/lib.rs +++ b/crates/sp_client/src/lib.rs @@ -3,14 +3,11 @@ use anyhow::Error; use sdk_common::crypto::AnkSharedSecret; use sdk_common::network::CachedMessage; use serde::{Deserialize, Serialize}; -use sp_client::bitcoin::{OutPoint, Txid}; -use sp_client::silentpayments::sending::SilentPaymentAddress; use std::collections::{HashMap, HashSet}; use std::fmt::Debug; use std::sync::{Mutex, MutexGuard, OnceLock}; use tsify::Tsify; -mod Prd_list; pub mod api; mod images; mod peers; From e7e02dfa8a607830d956925c35d2e7d0a91451b7 Mon Sep 17 00:00:00 2001 From: Nicolas Cantu <nicolas.cantu@pm.me> Date: Fri, 31 May 2024 15:57:12 +0000 Subject: [PATCH 90/90] sdk_common = { git = "https://git.4nkweb.com/4nk/sdk_common.git", branch = "dev" } --- crates/sp_client/Cargo.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/sp_client/Cargo.toml b/crates/sp_client/Cargo.toml index 3999e06..a5eb259 100644 --- a/crates/sp_client/Cargo.toml +++ b/crates/sp_client/Cargo.toml @@ -17,8 +17,9 @@ wasm-logger = "0.2.0" rand = "0.8.5" log = "0.4.6" tsify = { git = "https://github.com/Sosthene00/tsify", branch = "next" } -sdk_common = { path = "../../../sdk_common" } -#sdk_common = { git = "https://git.4nkweb.com/4nk/sdk_common.git", branch = "demo" } +# sdk_common = { path = "../../../sdk_common" } +# sdk_common = { git = "https://git.4nkweb.com/4nk/sdk_common.git", branch = "demo" } +sdk_common = { git = "https://git.4nkweb.com/4nk/sdk_common.git", branch = "dev" } shamir = { git = "https://github.com/Sosthene00/shamir", branch = "master" } img-parts = "0.3.0"