diff --git a/util/RustSdk/rust/Cargo.lock b/util/RustSdk/rust/Cargo.lock index 1665f387c4..cba06d35ea 100644 --- a/util/RustSdk/rust/Cargo.lock +++ b/util/RustSdk/rust/Cargo.lock @@ -135,8 +135,9 @@ checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bitwarden-api-api" version = "1.0.0" -source = "git+https://github.com/bitwarden/sdk-internal.git?rev=29c6158636d50141788e41736d15f2f6c7bc7fa8#29c6158636d50141788e41736d15f2f6c7bc7fa8" +source = "git+https://github.com/bitwarden/sdk-internal.git?rev=1461b3ba6bb6e2d0114770eb4572a1398b4789ef#1461b3ba6bb6e2d0114770eb4572a1398b4789ef" dependencies = [ + "async-trait", "reqwest", "serde", "serde_json", @@ -149,8 +150,9 @@ dependencies = [ [[package]] name = "bitwarden-api-identity" version = "1.0.0" -source = "git+https://github.com/bitwarden/sdk-internal.git?rev=29c6158636d50141788e41736d15f2f6c7bc7fa8#29c6158636d50141788e41736d15f2f6c7bc7fa8" +source = "git+https://github.com/bitwarden/sdk-internal.git?rev=1461b3ba6bb6e2d0114770eb4572a1398b4789ef#1461b3ba6bb6e2d0114770eb4572a1398b4789ef" dependencies = [ + "async-trait", "reqwest", "serde", "serde_json", @@ -163,13 +165,13 @@ dependencies = [ [[package]] name = "bitwarden-core" version = "1.0.0" -source = "git+https://github.com/bitwarden/sdk-internal.git?rev=29c6158636d50141788e41736d15f2f6c7bc7fa8#29c6158636d50141788e41736d15f2f6c7bc7fa8" +source = "git+https://github.com/bitwarden/sdk-internal.git?rev=1461b3ba6bb6e2d0114770eb4572a1398b4789ef#1461b3ba6bb6e2d0114770eb4572a1398b4789ef" dependencies = [ "async-trait", - "base64", "bitwarden-api-api", "bitwarden-api-identity", "bitwarden-crypto", + "bitwarden-encoding", "bitwarden-error", "bitwarden-state", "bitwarden-uuid", @@ -180,7 +182,7 @@ dependencies = [ "reqwest", "rustls", "rustls-platform-verifier", - "schemars 0.8.22", + "schemars 1.0.4", "serde", "serde_bytes", "serde_json", @@ -194,11 +196,11 @@ dependencies = [ [[package]] name = "bitwarden-crypto" version = "1.0.0" -source = "git+https://github.com/bitwarden/sdk-internal.git?rev=29c6158636d50141788e41736d15f2f6c7bc7fa8#29c6158636d50141788e41736d15f2f6c7bc7fa8" +source = "git+https://github.com/bitwarden/sdk-internal.git?rev=1461b3ba6bb6e2d0114770eb4572a1398b4789ef#1461b3ba6bb6e2d0114770eb4572a1398b4789ef" dependencies = [ "aes", "argon2", - "base64", + "bitwarden-encoding", "bitwarden-error", "cbc", "chacha20poly1305", @@ -215,7 +217,7 @@ dependencies = [ "rand_chacha 0.3.1", "rayon", "rsa", - "schemars 0.8.22", + "schemars 1.0.4", "serde", "serde_bytes", "serde_repr", @@ -229,10 +231,21 @@ dependencies = [ "zeroizing-alloc", ] +[[package]] +name = "bitwarden-encoding" +version = "1.0.0" +source = "git+https://github.com/bitwarden/sdk-internal.git?rev=1461b3ba6bb6e2d0114770eb4572a1398b4789ef#1461b3ba6bb6e2d0114770eb4572a1398b4789ef" +dependencies = [ + "data-encoding", + "data-encoding-macro", + "serde", + "thiserror 1.0.69", +] + [[package]] name = "bitwarden-error" version = "1.0.0" -source = "git+https://github.com/bitwarden/sdk-internal.git?rev=29c6158636d50141788e41736d15f2f6c7bc7fa8#29c6158636d50141788e41736d15f2f6c7bc7fa8" +source = "git+https://github.com/bitwarden/sdk-internal.git?rev=1461b3ba6bb6e2d0114770eb4572a1398b4789ef#1461b3ba6bb6e2d0114770eb4572a1398b4789ef" dependencies = [ "bitwarden-error-macro", ] @@ -240,7 +253,7 @@ dependencies = [ [[package]] name = "bitwarden-error-macro" version = "1.0.0" -source = "git+https://github.com/bitwarden/sdk-internal.git?rev=29c6158636d50141788e41736d15f2f6c7bc7fa8#29c6158636d50141788e41736d15f2f6c7bc7fa8" +source = "git+https://github.com/bitwarden/sdk-internal.git?rev=1461b3ba6bb6e2d0114770eb4572a1398b4789ef#1461b3ba6bb6e2d0114770eb4572a1398b4789ef" dependencies = [ "darling", "proc-macro2", @@ -251,16 +264,38 @@ dependencies = [ [[package]] name = "bitwarden-state" version = "1.0.0" -source = "git+https://github.com/bitwarden/sdk-internal.git?rev=29c6158636d50141788e41736d15f2f6c7bc7fa8#29c6158636d50141788e41736d15f2f6c7bc7fa8" +source = "git+https://github.com/bitwarden/sdk-internal.git?rev=1461b3ba6bb6e2d0114770eb4572a1398b4789ef#1461b3ba6bb6e2d0114770eb4572a1398b4789ef" dependencies = [ "async-trait", + "bitwarden-error", + "bitwarden-threading", + "indexed-db", + "js-sys", + "rusqlite", + "serde", + "serde_json", "thiserror 1.0.69", + "tokio", + "tsify", +] + +[[package]] +name = "bitwarden-threading" +version = "1.0.0" +source = "git+https://github.com/bitwarden/sdk-internal.git?rev=1461b3ba6bb6e2d0114770eb4572a1398b4789ef#1461b3ba6bb6e2d0114770eb4572a1398b4789ef" +dependencies = [ + "bitwarden-error", + "log", + "serde", + "thiserror 1.0.69", + "tokio", + "tokio-util", ] [[package]] name = "bitwarden-uuid" version = "1.0.0" -source = "git+https://github.com/bitwarden/sdk-internal.git?rev=29c6158636d50141788e41736d15f2f6c7bc7fa8#29c6158636d50141788e41736d15f2f6c7bc7fa8" +source = "git+https://github.com/bitwarden/sdk-internal.git?rev=1461b3ba6bb6e2d0114770eb4572a1398b4789ef#1461b3ba6bb6e2d0114770eb4572a1398b4789ef" dependencies = [ "bitwarden-uuid-macro", ] @@ -268,7 +303,7 @@ dependencies = [ [[package]] name = "bitwarden-uuid-macro" version = "1.0.0" -source = "git+https://github.com/bitwarden/sdk-internal.git?rev=29c6158636d50141788e41736d15f2f6c7bc7fa8#29c6158636d50141788e41736d15f2f6c7bc7fa8" +source = "git+https://github.com/bitwarden/sdk-internal.git?rev=1461b3ba6bb6e2d0114770eb4572a1398b4789ef#1461b3ba6bb6e2d0114770eb4572a1398b4789ef" dependencies = [ "quote", "syn", @@ -595,6 +630,32 @@ dependencies = [ "syn", ] +[[package]] +name = "data-encoding" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" + +[[package]] +name = "data-encoding-macro" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47ce6c96ea0102f01122a185683611bd5ac8d99e62bc59dd12e6bda344ee673d" +dependencies = [ + "data-encoding", + "data-encoding-macro-internal", +] + +[[package]] +name = "data-encoding-macro-internal" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" +dependencies = [ + "data-encoding", + "syn", +] + [[package]] name = "der" version = "0.7.10" @@ -682,6 +743,18 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + [[package]] name = "fiat-crypto" version = "0.2.9" @@ -694,6 +767,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -718,6 +797,17 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.31" @@ -737,9 +827,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", + "futures-macro", "futures-task", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -826,6 +918,18 @@ name = "hashbrown" version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.4", +] [[package]] name = "hex" @@ -1088,6 +1192,20 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "indexed-db" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78f4ecbb6cd50773303683617a93fc2782267d2c94546e9545ec4190eb69aa1a" +dependencies = [ + "futures-channel", + "futures-util", + "pin-project-lite", + "scoped-tls", + "thiserror 2.0.12", + "web-sys", +] + [[package]] name = "indexmap" version = "1.9.3" @@ -1195,6 +1313,17 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "libsqlite3-sys" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "litemap" version = "0.8.0" @@ -1413,6 +1542,12 @@ dependencies = [ "spki", ] +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + [[package]] name = "poly1305" version = "0.8.0" @@ -1729,6 +1864,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rusqlite" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f" +dependencies = [ + "bitflags", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + [[package]] name = "rustc-demangle" version = "0.1.25" @@ -1854,20 +2003,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "schemars" -version = "0.8.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" -dependencies = [ - "chrono", - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", - "uuid", -] - [[package]] name = "schemars" version = "0.9.0" @@ -1881,10 +2016,25 @@ dependencies = [ ] [[package]] -name = "schemars_derive" -version = "0.8.22" +name = "schemars" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +dependencies = [ + "chrono", + "dyn-clone", + "ref-cast", + "schemars_derive", + "serde", + "serde_json", + "uuid", +] + +[[package]] +name = "schemars_derive" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d020396d1d138dc19f1165df7545479dcd58d93810dc5d646a16e55abefa80" dependencies = [ "proc-macro2", "quote", @@ -1892,6 +2042,12 @@ dependencies = [ "syn", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "sdk" version = "0.1.0" @@ -1942,6 +2098,17 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_bytes" version = "0.11.17" @@ -2283,9 +2450,21 @@ dependencies = [ "mio", "pin-project-lite", "socket2", + "tokio-macros", "windows-sys 0.52.0", ] +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio-rustls" version = "0.26.2" @@ -2379,6 +2558,30 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tsify" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ec91b85e6c6592ed28636cb1dd1fac377ecbbeb170ff1d79f97aac5e38926d" +dependencies = [ + "serde", + "serde-wasm-bindgen", + "tsify-macros", + "wasm-bindgen", +] + +[[package]] +name = "tsify-macros" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a324606929ad11628a19206d7853807481dcaecd6c08be70a235930b8241955" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn", +] + [[package]] name = "typenum" version = "1.18.0" @@ -2442,6 +2645,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.5" diff --git a/util/RustSdk/rust/Cargo.toml b/util/RustSdk/rust/Cargo.toml index 47758cee4b..88521277f3 100644 --- a/util/RustSdk/rust/Cargo.toml +++ b/util/RustSdk/rust/Cargo.toml @@ -13,8 +13,8 @@ crate-type = ["cdylib"] [dependencies] base64 = "0.22.1" -bitwarden-core = { git = "https://github.com/bitwarden/sdk-internal.git", rev = "29c6158636d50141788e41736d15f2f6c7bc7fa8" } -bitwarden-crypto = { git = "https://github.com/bitwarden/sdk-internal.git", rev = "29c6158636d50141788e41736d15f2f6c7bc7fa8" } +bitwarden-core = { git = "https://github.com/bitwarden/sdk-internal.git", rev = "1461b3ba6bb6e2d0114770eb4572a1398b4789ef" } +bitwarden-crypto = { git = "https://github.com/bitwarden/sdk-internal.git", rev = "1461b3ba6bb6e2d0114770eb4572a1398b4789ef" } serde = "=1.0.219" serde_json = "=1.0.141" diff --git a/util/RustSdk/rust/src/lib.rs b/util/RustSdk/rust/src/lib.rs index 7c7a628137..10f8d8dca4 100644 --- a/util/RustSdk/rust/src/lib.rs +++ b/util/RustSdk/rust/src/lib.rs @@ -1,10 +1,13 @@ #![allow(clippy::missing_safety_doc)] -use std::ffi::{c_char, CStr, CString}; +use std::{ + ffi::{c_char, CStr, CString}, + num::NonZeroU32, +}; use base64::{engine::general_purpose::STANDARD, Engine}; use bitwarden_crypto::{ - pbkdf2, AsymmetricCryptoKey, AsymmetricPublicCryptoKey, BitwardenLegacyKeyBytes, HashPurpose, + AsymmetricCryptoKey, AsymmetricPublicCryptoKey, BitwardenLegacyKeyBytes, HashPurpose, Kdf, KeyEncryptable, MasterKey, RsaKeyPair, SpkiPublicKeyBytes, SymmetricCryptoKey, UnsignedSharedKey, UserKey, }; @@ -17,11 +20,19 @@ pub unsafe extern "C" fn generate_user_keys( let email = CStr::from_ptr(email).to_str().unwrap(); let password = CStr::from_ptr(password).to_str().unwrap(); - let master_key = derive_master_key(password, email); + println!("Generating keys for {email}"); + println!("Password: {password}"); - let master_password_hash = master_key - .derive_master_key_hash(password.as_bytes(), HashPurpose::ServerAuthorization) - .unwrap(); + let kdf = Kdf::PBKDF2 { + iterations: NonZeroU32::new(5_000).unwrap(), + }; + + let master_key = MasterKey::derive(password, email, &kdf).unwrap(); + + let master_password_hash = + master_key.derive_master_key_hash(password.as_bytes(), HashPurpose::ServerAuthorization); + + println!("Master password hash: {}", master_password_hash); let (user_key, encrypted_user_key) = master_key.make_user_key().unwrap(); @@ -41,14 +52,6 @@ pub unsafe extern "C" fn generate_user_keys( result.into_raw() } -fn derive_master_key(email: &str, password: &str) -> MasterKey { - let mut hash = pbkdf2(password.as_bytes(), email.as_bytes(), 5000); - - let hash = hash.as_mut_slice(); - - hash.try_into().unwrap() -} - fn keypair(key: &SymmetricCryptoKey) -> RsaKeyPair { const RSA_PRIVATE_KEY: &str = "-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXRVrCX+2hfOQS @@ -82,13 +85,11 @@ XKZBokBGnjFnTnKcs7nv/O8= let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); let public_key = private_key.to_public_key().to_der().unwrap(); - let b64 = STANDARD.encode(public_key); - let p = private_key.to_der().unwrap(); RsaKeyPair { private: p.encrypt_with_key(key).unwrap(), - public: b64, + public: public_key.into(), } } diff --git a/util/Seeder/Factories/UserSeeder.cs b/util/Seeder/Factories/UserSeeder.cs index 4daf97815c..a47ffa7576 100644 --- a/util/Seeder/Factories/UserSeeder.cs +++ b/util/Seeder/Factories/UserSeeder.cs @@ -18,9 +18,7 @@ public struct UserData public int KdfIterations; } -#pragma warning disable CS9113 // Parameter is unread. -public class UserSeeder(Guid mangleId) -#pragma warning restore CS9113 // Parameter is unread. +public class UserSeeder(RustSdkService sdkService, IPasswordHasher passwordHasher) { private string MangleEmail(string email) { @@ -30,20 +28,26 @@ public class UserSeeder(Guid mangleId) public User CreateUser(string email) { - return new User + var keys = sdkService.GenerateUserKeys(email, "asdfasdfasdf"); + + var user = new User { Id = CoreHelpers.GenerateComb(), - Email = MangleEmail(email), - MasterPassword = "AQAAAAIAAYagAAAAEBATmF66OHMpHuHKc1CsGZQ1ltHUHyhYK+7e4re3bVFi16SOpLpDfzdFswnvFQs2Rg==", + Email = email, + MasterPassword = null, SecurityStamp = "4830e359-e150-4eae-be2a-996c81c5e609", - Key = "2.z/eLKFhd62qy9RzXu3UHgA==|fF6yNupiCIguFKSDTB3DoqcGR0Xu4j+9VlnMyT5F3PaWIcGhzQKIzxdB95nhslaCQv3c63M7LBnvzVo1J9SUN85RMbP/57bP1HvhhU1nvL8=|IQPtf8v7k83MFZEhazSYXSdu98BBU5rqtvC4keVWyHM=", - PublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Ww2chogqCpaAR7Uw448am4b7vDFXiM5kXjFlGfXBlrAdAqTTggEvTDlMNYqPlCo+mBM6iFmTTUY9rpZBvFskMnKvsvpJ47/fehAH2o2e3Ulv/5NFevaVCMCmpkBDtbMbO1A4a3btdRtCP8DsKWMefHauEpaoLxNTLWnOIZVfCMjsSgx2EvULHAZPTtbFwm4+UVKniM4ds4jvOsD85h4jn2aLs/jWJXFfxN8iVSqEqpC2TBvsPdyHb49xQoWWfF0Z6BiNqeNGKEU9Uos1pjL+kzhEzzSpH31PZT/ufJ/oo4+93wrUt57hb6f0jxiXhwd5yQ+9F6wVwpbfkq0IwhjOwIDAQAB", - PrivateKey = "2.yN7l00BOlUE0Sb0M//Q53w==|EwKG/BduQRQ33Izqc/ogoBROIoI5dmgrxSo82sgzgAMIBt3A2FZ9vPRMY+GWT85JiqytDitGR3TqwnFUBhKUpRRAq4x7rA6A1arHrFp5Tp1p21O3SfjtvB3quiOKbqWk6ZaU1Np9HwqwAecddFcB0YyBEiRX3VwF2pgpAdiPbSMuvo2qIgyob0CUoC/h4Bz1be7Qa7B0Xw9/fMKkB1LpOm925lzqosyMQM62YpMGkjMsbZz0uPopu32fxzDWSPr+kekNNyLt9InGhTpxLmq1go/pXR2uw5dfpXc5yuta7DB0EGBwnQ8Vl5HPdDooqOTD9I1jE0mRyuBpWTTI3FRnu3JUh3rIyGBJhUmHqGZvw2CKdqHCIrQeQkkEYqOeJRJVdBjhv5KGJifqT3BFRwX/YFJIChAQpebNQKXe/0kPivWokHWwXlDB7S7mBZzhaAPidZvnuIhalE2qmTypDwHy22FyqV58T8MGGMchcASDi/QXI6kcdpJzPXSeU9o+NC68QDlOIrMVxKFeE7w7PvVmAaxEo0YwmuAzzKy9QpdlK0aab/xEi8V4iXj4hGepqAvHkXIQd+r3FNeiLfllkb61p6WTjr5urcmDQMR94/wYoilpG5OlybHdbhsYHvIzYoLrC7fzl630gcO6t4nM24vdB6Ymg9BVpEgKRAxSbE62Tqacxqnz9AcmgItb48NiR/He3n3ydGjPYuKk/ihZMgEwAEZvSlNxYONSbYrIGDtOY+8Nbt6KiH3l06wjZW8tcmFeVlWv+tWotnTY9IqlAfvNVTjtsobqtQnvsiDjdEVtNy/s2ci5TH+NdZluca2OVEr91Wayxh70kpM6ib4UGbfdmGgCo74gtKvKSJU0rTHakQ5L9JlaSDD5FamBRyI0qfL43Ad9qOUZ8DaffDCyuaVyuqk7cz9HwmEmvWU3VQ+5t06n/5kRDXttcw8w+3qClEEdGo1KeENcnXCB32dQe3tDTFpuAIMLqwXs6FhpawfZ5kPYvLPczGWaqftIs/RXJ/EltGc0ugw2dmTLpoQhCqrcKEBDoYVk0LDZKsnzitOGdi9mOWse7Se8798ib1UsHFUjGzISEt6upestxOeupSTOh0v4+AjXbDzRUyogHww3V+Bqg71bkcMxtB+WM+pn1XNbVTyl9NR040nhP7KEf6e9ruXAtmrBC2ah5cFEpLIot77VFZ9ilLuitSz+7T8n1yAh1IEG6xxXxninAZIzi2qGbH69O5RSpOJuJTv17zTLJQIIc781JwQ2TTwTGnx5wZLbffhCasowJKd2EVcyMJyhz6ru0PvXWJ4hUdkARJs3Xu8dus9a86N8Xk6aAPzBDqzYb1vyFIfBxP0oO8xFHgd30Cgmz8UrSE3qeWRrF8ftrI6xQnFjHBGWD/JWSvd6YMcQED0aVuQkuNW9ST/DzQThPzRfPUoiL10yAmV7Ytu4fR3x2sF0Yfi87YhHFuCMpV/DsqxmUizyiJuD938eRcH8hzR/VO53Qo3UIsqOLcyXtTv6THjSlTopQ+JOLOnHm1w8dzYbLN44OG44rRsbihMUQp+wUZ6bsI8rrOnm9WErzkbQFbrfAINdoCiNa6cimYIjvvnMTaFWNymqY1vZxGztQiMiHiHYwTfwHTXrb9j0uPM=|09J28iXv9oWzYtzK2LBT6Yht4IT4MijEkk0fwFdrVQ4=", + Key = keys.EncryptedUserKey, + PublicKey = keys.PublicKey, + PrivateKey = keys.PrivateKey, ApiKey = "7gp59kKHt9kMlks0BuNC4IjNXYkljR", Kdf = KdfType.PBKDF2_SHA256, - KdfIterations = 600_000, + KdfIterations = 5_000, }; + + user.MasterPassword = passwordHasher.HashPassword(user, keys.MasterPasswordHash); + + return user; } public static User CreateUserNoMangle(string email) @@ -96,28 +100,4 @@ public class UserSeeder(Guid mangleId) return mangleMap; } - public static (User user, string userKey) CreateSdkUser(IPasswordHasher passwordHasher, string email) - { - var nativeService = RustSdkServiceFactory.CreateSingleton(); - var keys = nativeService.GenerateUserKeys(email, "asdfasdfasdf"); - - var user = new User - { - Id = Guid.NewGuid(), - Email = email, - MasterPassword = null, - SecurityStamp = "4830e359-e150-4eae-be2a-996c81c5e609", - Key = keys.EncryptedUserKey, - PublicKey = keys.PublicKey, - PrivateKey = keys.PrivateKey, - ApiKey = "7gp59kKHt9kMlks0BuNC4IjNXYkljR", - - Kdf = KdfType.PBKDF2_SHA256, - KdfIterations = 5_000, - }; - - user.MasterPassword = passwordHasher.HashPassword(user, keys.MasterPasswordHash); - - return (user, keys.Key); - } } diff --git a/util/Seeder/Recipes/SingleUserRecipe.cs b/util/Seeder/Recipes/SingleUserRecipe.cs index 49a59d2a72..3c8f63ec45 100644 --- a/util/Seeder/Recipes/SingleUserRecipe.cs +++ b/util/Seeder/Recipes/SingleUserRecipe.cs @@ -4,11 +4,10 @@ using Bit.Seeder.Factories; namespace Bit.Seeder.Recipes; -public class SingleUserRecipe(DatabaseContext db) +public class SingleUserRecipe(DatabaseContext db, UserSeeder userSeeder) { public RecipeResult Seed(string email) { - var userSeeder = new UserSeeder(Guid.NewGuid()); var user = userSeeder.CreateUser(email); db.Add(user); diff --git a/util/SeederApi/Program.cs b/util/SeederApi/Program.cs index e1356afe46..685183cee7 100644 --- a/util/SeederApi/Program.cs +++ b/util/SeederApi/Program.cs @@ -15,6 +15,15 @@ builder.Services.AddCustomDataProtectionServices(builder.Environment, globalSett // Repositories builder.Services.AddDatabaseRepositories(globalSettings); +// Identity Services +builder.Services.AddScoped, Microsoft.AspNetCore.Identity.PasswordHasher>(); + +// RustSDK Services +builder.Services.AddSingleton(); + +// Seeder Services +builder.Services.AddScoped(); + // Recipe Service builder.Services.AddScoped(); diff --git a/util/SeederApi/Properties/launchSettings.json b/util/SeederApi/Properties/launchSettings.json index 105d470068..95cd77e255 100644 --- a/util/SeederApi/Properties/launchSettings.json +++ b/util/SeederApi/Properties/launchSettings.json @@ -12,7 +12,6 @@ "SeederApi": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, "applicationUrl": "http://localhost:5047", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" @@ -21,7 +20,6 @@ "SeederApi-SelfHost": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, "applicationUrl": "http://localhost:5048", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", diff --git a/util/SeederApi/Services/RecipeService.cs b/util/SeederApi/Services/RecipeService.cs index af2ba520e9..97f73d07f6 100644 --- a/util/SeederApi/Services/RecipeService.cs +++ b/util/SeederApi/Services/RecipeService.cs @@ -10,11 +10,13 @@ public class RecipeService : IRecipeService { private readonly DatabaseContext _databaseContext; private readonly ILogger _logger; + private readonly IServiceProvider _serviceProvider; - public RecipeService(DatabaseContext databaseContext, ILogger logger) + public RecipeService(DatabaseContext databaseContext, ILogger logger, IServiceProvider serviceProvider) { _databaseContext = databaseContext; _logger = logger; + _serviceProvider = serviceProvider; } public List GetAllSeededData() @@ -95,7 +97,7 @@ public class RecipeService : IRecipeService { var recipeType = LoadRecipeType(templateName); var method = GetRecipeMethod(recipeType, templateName, methodName); - var recipeInstance = Activator.CreateInstance(recipeType, _databaseContext)!; + var recipeInstance = CreateRecipeInstance(recipeType); var methodArguments = ParseMethodArguments(method, arguments); var result = method.Invoke(recipeInstance, methodArguments); @@ -128,6 +130,35 @@ public class RecipeService : IRecipeService return method ?? throw new RecipeExecutionException($"{methodName} method not found in recipe '{templateName}'"); } + private object CreateRecipeInstance(Type recipeType) + { + var constructors = recipeType.GetConstructors(); + if (constructors.Length == 0) + { + throw new RecipeExecutionException($"No public constructors found for recipe type '{recipeType.Name}'"); + } + + var constructor = constructors[0]; + var parameters = constructor.GetParameters(); + var constructorArgs = new object[parameters.Length]; + + for (var i = 0; i < parameters.Length; i++) + { + var parameter = parameters[i]; + var service = _serviceProvider.GetService(parameter.ParameterType); + + if (service == null) + { + throw new RecipeExecutionException( + $"Unable to resolve service of type '{parameter.ParameterType.Name}' for recipe constructor"); + } + + constructorArgs[i] = service; + } + + return Activator.CreateInstance(recipeType, constructorArgs)!; + } + private static object?[] ParseMethodArguments(MethodInfo seedMethod, JsonElement? arguments) { var parameters = seedMethod.GetParameters();