1
0
mirror of https://github.com/bitwarden/server synced 2025-12-10 13:23:27 +00:00

Wire up SDK

This commit is contained in:
Hinton
2025-10-09 17:32:41 -07:00
parent 3d863c0fd1
commit 9c4c88fa34
8 changed files with 316 additions and 89 deletions

View File

@@ -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"

View File

@@ -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"

View File

@@ -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(),
}
}

View File

@@ -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<Bit.Core.Entities.User> 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<Bit.Core.Entities.User> 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);
}
}

View File

@@ -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);

View File

@@ -15,6 +15,15 @@ builder.Services.AddCustomDataProtectionServices(builder.Environment, globalSett
// Repositories
builder.Services.AddDatabaseRepositories(globalSettings);
// Identity Services
builder.Services.AddScoped<Microsoft.AspNetCore.Identity.IPasswordHasher<Bit.Core.Entities.User>, Microsoft.AspNetCore.Identity.PasswordHasher<Bit.Core.Entities.User>>();
// RustSDK Services
builder.Services.AddSingleton<Bit.RustSDK.RustSdkService>();
// Seeder Services
builder.Services.AddScoped<Bit.Seeder.Factories.UserSeeder>();
// Recipe Service
builder.Services.AddScoped<IRecipeService, RecipeService>();

View File

@@ -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",

View File

@@ -10,11 +10,13 @@ public class RecipeService : IRecipeService
{
private readonly DatabaseContext _databaseContext;
private readonly ILogger<RecipeService> _logger;
private readonly IServiceProvider _serviceProvider;
public RecipeService(DatabaseContext databaseContext, ILogger<RecipeService> logger)
public RecipeService(DatabaseContext databaseContext, ILogger<RecipeService> logger, IServiceProvider serviceProvider)
{
_databaseContext = databaseContext;
_logger = logger;
_serviceProvider = serviceProvider;
}
public List<SeededData> 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();