From 9ff37c721d1056f48c8954f70c57e76d853f8139 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Thu, 19 Oct 2023 08:39:53 -0700 Subject: [PATCH 01/30] Return a non-zero exit code when no subcommands are supplied (#296) ## Type of change - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ## Objective Return a non-zero exit code when no subcommands are supplied. This matches the behavior in many other CLIs (`bw`, `git`, `ssh`, etc.). ## Code changes - **`crates/bws/src/main.rs`:** Exit with a non-zero exit code ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --- crates/bws/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bws/src/main.rs b/crates/bws/src/main.rs index 5e6da19d8..c7a910260 100644 --- a/crates/bws/src/main.rs +++ b/crates/bws/src/main.rs @@ -247,7 +247,7 @@ async fn process_commands() -> Result<()> { let Some(command) = cli.command else { let mut cmd = Cli::command(); eprintln!("{}", cmd.render_help().ansi()); - return Ok(()); + std::process::exit(1); }; // These commands don't require authentication, so we process them first From 1601ecd43ea90ef8775346e0ad0a6d13eda77545 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 23 Oct 2023 12:05:22 +0200 Subject: [PATCH 02/30] Switch from from_str to parse (#299) --- crates/bitwarden/src/auth/login/access_token.rs | 6 ++---- crates/bitwarden/src/auth/login/api_key.rs | 6 ++---- crates/bitwarden/src/auth/login/password.rs | 7 ++----- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index 46fa35779..63fd86ebb 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use base64::Engine; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -23,13 +21,13 @@ pub(crate) async fn access_token_login( //info!("api key logging in"); //debug!("{:#?}, {:#?}", client, input); - let access_token = AccessToken::from_str(&input.access_token)?; + let access_token: AccessToken = input.access_token.parse()?; let response = request_access_token(client, &access_token).await?; if let IdentityTokenResponse::Payload(r) = &response { // Extract the encrypted payload and use the access token encryption key to decrypt it - let payload = EncString::from_str(&r.encrypted_payload)?; + let payload: EncString = r.encrypted_payload.parse()?; let decrypted_payload = payload.decrypt_with_key(&access_token.encryption_key)?; diff --git a/crates/bitwarden/src/auth/login/api_key.rs b/crates/bitwarden/src/auth/login/api_key.rs index a9fa954d7..cdbc383ba 100644 --- a/crates/bitwarden/src/auth/login/api_key.rs +++ b/crates/bitwarden/src/auth/login/api_key.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -46,8 +44,8 @@ pub(crate) async fn api_key_login( }), ); - let user_key = EncString::from_str(r.key.as_deref().unwrap()).unwrap(); - let private_key = EncString::from_str(r.private_key.as_deref().unwrap()).unwrap(); + let user_key: EncString = r.key.as_deref().unwrap().parse().unwrap(); + let private_key: EncString = r.private_key.as_deref().unwrap().parse().unwrap(); client.initialize_user_crypto(&input.password, user_key, private_key)?; } diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index 33f7ea338..c86f7019f 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -1,6 +1,3 @@ -#[cfg(feature = "internal")] -use std::str::FromStr; - #[cfg(feature = "internal")] use log::{debug, info}; use schemars::JsonSchema; @@ -49,8 +46,8 @@ pub(crate) async fn password_login( }), ); - let user_key = EncString::from_str(r.key.as_deref().unwrap()).unwrap(); - let private_key = EncString::from_str(r.private_key.as_deref().unwrap()).unwrap(); + let user_key: EncString = r.key.as_deref().unwrap().parse().unwrap(); + let private_key: EncString = r.private_key.as_deref().unwrap().parse().unwrap(); client.initialize_user_crypto(&input.password, user_key, private_key)?; } From e5d4521beb2bc0eb6b049c9a9bb05f6193c63789 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 14:10:52 +0200 Subject: [PATCH 03/30] Lock file maintenance (#302) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 118 +++++----- crates/bitwarden-napi/package-lock.json | 6 +- languages/js_webassembly/package-lock.json | 255 +++++++++++++-------- package-lock.json | 12 +- 4 files changed, 227 insertions(+), 164 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bb70fdf5..5bdbdc291 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -746,11 +746,11 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "comfy-table" -version = "7.0.1" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab77dbd8adecaf3f0db40581631b995f312a8a5ae3aa9993188bb8f23d83a5b" +checksum = "7c64043d6c7b7a4c58e39e7efccfdea7b93d885a795d0c054a69dbbf4dd52686" dependencies = [ - "crossterm 0.26.1", + "crossterm 0.27.0", "strum", "strum_macros", "unicode-width", @@ -841,9 +841,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4" dependencies = [ "libc", ] @@ -884,17 +884,14 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.26.1" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", "crossterm_winapi", "libc", - "mio", "parking_lot", - "signal-hook", - "signal-hook-mio", "winapi", ] @@ -1339,9 +1336,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" [[package]] name = "heck" @@ -1460,7 +1457,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -1482,16 +1479,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -1537,7 +1534,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" dependencies = [ "equivalent", - "hashbrown 0.14.1", + "hashbrown 0.14.2", ] [[package]] @@ -1589,9 +1586,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" @@ -1682,9 +1679,9 @@ checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -2032,9 +2029,9 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "parking" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" @@ -2048,13 +2045,13 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "smallvec", "windows-targets 0.48.5", ] @@ -2156,9 +2153,9 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "plist" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdc0001cfea3db57a2e24bc0d818e9e20e554b5f97fabb9bc231dc240269ae06" +checksum = "9a4a0cfc5fb21a09dc6af4bf834cf10d4a32fccd9e2ea468c4b1751a097487aa" dependencies = [ "base64 0.21.4", "indexmap 1.9.3", @@ -2287,9 +2284,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b9228215d82c7b61490fec1de287136b5de6f5700f6e58ea9ad61a7964ca51" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" dependencies = [ "memchr", ] @@ -2392,6 +2389,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_users" version = "0.4.3" @@ -2522,9 +2528,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.19" +version = "0.38.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" +checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" dependencies = [ "bitflags 2.4.1", "errno", @@ -2876,9 +2882,9 @@ checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -2886,9 +2892,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys 0.48.0", @@ -2930,21 +2936,21 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strum" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" [[package]] name = "strum_macros" -version = "0.24.3" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ "heck", "proc-macro2", "quote", "rustversion", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] @@ -3027,9 +3033,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.11" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tempfile" @@ -3055,18 +3061,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", @@ -3139,7 +3145,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2 0.5.4", + "socket2 0.5.5", "tokio-macros", "windows-sys 0.48.0", ] @@ -3230,9 +3236,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.39" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2ef2af84856a50c1d430afce2fdded0a4ec7eda868db86409b4543df0797f9" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", "tracing-core", @@ -3489,9 +3495,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" dependencies = [ "serde", ] @@ -3693,10 +3699,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ "windows-targets 0.48.5", ] diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 5a2945fd3..b0df11947 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -95,9 +95,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", - "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", "dev": true, "peer": true, "dependencies": { diff --git a/languages/js_webassembly/package-lock.json b/languages/js_webassembly/package-lock.json index 3c961135e..ea4d8b7f3 100644 --- a/languages/js_webassembly/package-lock.json +++ b/languages/js_webassembly/package-lock.json @@ -72,9 +72,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -88,9 +88,9 @@ "dev": true }, "node_modules/@types/body-parser": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz", - "integrity": "sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==", + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz", + "integrity": "sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==", "dev": true, "dependencies": { "@types/connect": "*", @@ -98,27 +98,27 @@ } }, "node_modules/@types/bonjour": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.11.tgz", - "integrity": "sha512-isGhjmBtLIxdHBDl2xGwUzEM8AOyOvWsADWq7rqirdi/ZQoHnLWErHvsThcEzTX8juDRiZtzp2Qkv5bgNh6mAg==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.12.tgz", + "integrity": "sha512-ky0kWSqXVxSqgqJvPIkgFkcn4C8MnRog308Ou8xBBIVo39OmUFy+jqNe0nPwLCDFxUpmT9EvT91YzOJgkDRcFg==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/connect": { - "version": "3.4.36", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", - "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", + "version": "3.4.37", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", + "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.1.tgz", - "integrity": "sha512-iaQslNbARe8fctL5Lk+DsmgWOM83lM+7FzP0eQUJs1jd3kBE8NWqBTIT2S8SqQOJjxvt2eyIjpOuYeRXq2AdMw==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.2.tgz", + "integrity": "sha512-gX2j9x+NzSh4zOhnRPSdPPmTepS4DfxES0AvIFv3jGv5QyeAJf6u6dY5/BAoAJU9Qq1uTvwOku8SSC2GnCRl6Q==", "dev": true, "dependencies": { "@types/express-serve-static-core": "*", @@ -126,9 +126,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.44.4", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.4.tgz", - "integrity": "sha512-lOzjyfY/D9QR4hY9oblZ76B90MYTB3RrQ4z2vBIJKj9ROCRqdkYl2gSUx1x1a4IWPjKJZLL4Aw1Zfay7eMnmnA==", + "version": "8.44.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.6.tgz", + "integrity": "sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==", "dev": true, "dependencies": { "@types/estree": "*", @@ -136,9 +136,9 @@ } }, "node_modules/@types/eslint-scope": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.5.tgz", - "integrity": "sha512-JNvhIEyxVW6EoMIFIvj93ZOywYFatlpu9deeH6eSx6PE3WHYvHaQtmHmQeNw7aA81bYGBPPQqdtBm6b1SsQMmA==", + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.6.tgz", + "integrity": "sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==", "dev": true, "dependencies": { "@types/eslint": "*", @@ -146,15 +146,15 @@ } }, "node_modules/@types/estree": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz", - "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", + "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==", "dev": true }, "node_modules/@types/express": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.19.tgz", - "integrity": "sha512-UtOfBtzN9OvpZPPbnnYunfjM7XCI4jyk1NvnFhTVz5krYAnW4o5DCoIekvms+8ApqhB4+9wSge1kBijdfTSmfg==", + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz", + "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==", "dev": true, "dependencies": { "@types/body-parser": "*", @@ -164,9 +164,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.37", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.37.tgz", - "integrity": "sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==", + "version": "4.17.39", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.39.tgz", + "integrity": "sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==", "dev": true, "dependencies": { "@types/node": "*", @@ -182,51 +182,51 @@ "dev": true }, "node_modules/@types/http-errors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.2.tgz", - "integrity": "sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz", + "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==", "dev": true }, "node_modules/@types/http-proxy": { - "version": "1.17.12", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.12.tgz", - "integrity": "sha512-kQtujO08dVtQ2wXAuSFfk9ASy3sug4+ogFR8Kd8UgP8PEuc1/G/8yjYRmp//PcDNJEUKOza/MrQu15bouEUCiw==", + "version": "1.17.13", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.13.tgz", + "integrity": "sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/json-schema": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", - "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", "dev": true }, "node_modules/@types/mime": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.3.tgz", - "integrity": "sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz", + "integrity": "sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==", "dev": true }, "node_modules/@types/node": { - "version": "20.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", - "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", "dev": true, "dependencies": { "undici-types": "~5.25.1" } }, "node_modules/@types/qs": { - "version": "6.9.8", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", - "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", + "version": "6.9.9", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", + "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==", "dev": true }, "node_modules/@types/range-parser": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.5.tgz", - "integrity": "sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", + "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==", "dev": true }, "node_modules/@types/retry": { @@ -236,9 +236,9 @@ "dev": true }, "node_modules/@types/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.2.tgz", - "integrity": "sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==", + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", + "integrity": "sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==", "dev": true, "dependencies": { "@types/mime": "^1", @@ -246,18 +246,18 @@ } }, "node_modules/@types/serve-index": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.2.tgz", - "integrity": "sha512-asaEIoc6J+DbBKXtO7p2shWUpKacZOoMBEGBgPG91P8xhO53ohzHWGCs4ScZo5pQMf5ukQzVT9fhX1WzpHihig==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.3.tgz", + "integrity": "sha512-4KG+yMEuvDPRrYq5fyVm/I2uqAJSAwZK9VSa+Zf+zUq9/oxSSvy3kkIqyL+jjStv6UCVi8/Aho0NHtB1Fwosrg==", "dev": true, "dependencies": { "@types/express": "*" } }, "node_modules/@types/serve-static": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.3.tgz", - "integrity": "sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==", + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz", + "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==", "dev": true, "dependencies": { "@types/http-errors": "*", @@ -266,18 +266,18 @@ } }, "node_modules/@types/sockjs": { - "version": "0.3.34", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.34.tgz", - "integrity": "sha512-R+n7qBFnm/6jinlteC9DBL5dGiDGjWAvjo4viUanpnc/dG1y7uDoacXPIQ/PQEg1fI912SMHIa014ZjRpvDw4g==", + "version": "0.3.35", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.35.tgz", + "integrity": "sha512-tIF57KB+ZvOBpAQwSaACfEu7htponHXaFzP7RfKYgsOS0NoYnn+9+jzp7bbq4fWerizI3dTB4NfAZoyeQKWJLw==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/ws": { - "version": "8.5.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.7.tgz", - "integrity": "sha512-6UrLjiDUvn40CMrAubXuIVtj2PEfKDffJS7ychvnPU44j+KVeXmdHHTgqcM/dxLUTHxlXHiFM8Skmb8ozGdTnQ==", + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.8.tgz", + "integrity": "sha512-flUksGIQCnJd6sZ1l5dqCEG/ksaoAg/eUwiLAGTJQcfgvZJKF++Ta4bJA6A5aPSJmsr+xlseHn4KLgVlNnvPTg==", "dev": true, "dependencies": { "@types/node": "*" @@ -803,13 +803,14 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -826,9 +827,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001549", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001549.tgz", - "integrity": "sha512-qRp48dPYSCYaP+KurZLhDYdVE+yEyht/3NlmcJgVQ2VMGt6JL36ndQ/7rgspdZsJuxDPFIo/OzBT2+GmIJ53BA==", + "version": "1.0.30001553", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001553.tgz", + "integrity": "sha512-N0ttd6TrFfuqKNi+pMgWJTb9qrdJu4JSpgPFLe/lrD19ugC6fZgF0pUewRowDwzdDnb9V41mFcdlYgl/PyKf4A==", "dev": true, "funding": [ { @@ -1121,6 +1122,20 @@ "node": ">= 10" } }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -1254,9 +1269,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.554", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.554.tgz", - "integrity": "sha512-Q0umzPJjfBrrj8unkONTgbKQXzXRrH7sVV7D9ea2yBV3Oaogz991yhbpfvo2LMNkJItmruXTEzVpP9cp7vaIiQ==", + "version": "1.4.563", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.563.tgz", + "integrity": "sha512-dg5gj5qOgfZNkPNeyKBZQAQitIQ/xwfIDmEQJHCbXaD9ebTZxwJXUsDYcBlAvZGZLi+/354l35J1wkmP6CqYaw==", "dev": true }, "node_modules/encodeurl": { @@ -1644,15 +1659,15 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1708,6 +1723,18 @@ "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", @@ -1720,15 +1747,6 @@ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -1738,6 +1756,18 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", @@ -1762,6 +1792,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "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", @@ -2045,12 +2087,12 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "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": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2532,9 +2574,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.0.tgz", - "integrity": "sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g==", + "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" @@ -3190,6 +3232,21 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", diff --git a/package-lock.json b/package-lock.json index ecbb207ad..0918c67ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -363,9 +363,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", - "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", "dev": true, "peer": true, "dependencies": { @@ -373,9 +373,9 @@ } }, "node_modules/@types/urijs": { - "version": "1.19.20", - "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.20.tgz", - "integrity": "sha512-77Mq/2BeHU894J364dUv9tSwxxyCLtcX228Pc8TwZpP5bvOoMns+gZoftp3LYl3FBH8vChpWbuagKGiMki2c1A==", + "version": "1.19.22", + "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.22.tgz", + "integrity": "sha512-qnYBwfN7O/+i6E1Kr8JaCKsrCLpRCiQ1XxkSxNIYuJ/5Aagt0+HlMX78DJMUrNzDULMz0eu2gcprlxJaDtACOw==", "dev": true }, "node_modules/abort-controller": { From ba49283f1cb1e888e50d88335595fee35594ffbc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 09:30:02 -0400 Subject: [PATCH 04/30] Update gh minor (#300) --- .github/workflows/build-android.yml | 10 +++++----- .github/workflows/build-cli.yml | 12 ++++++------ .github/workflows/build-dotnet.yml | 2 +- .github/workflows/build-napi.yml | 4 ++-- .github/workflows/build-rust-crates.yml | 8 ++++---- .github/workflows/build-rust-cross-platform.yml | 4 ++-- .github/workflows/cloc.yml | 2 +- .github/workflows/direct-minimal-versions.yml | 4 ++-- .github/workflows/generate_schemas.yml | 4 ++-- .github/workflows/lint.yml | 4 ++-- .github/workflows/publish-dotnet.yml | 2 +- .github/workflows/publish-rust-crates.yml | 6 +++--- .github/workflows/release-cli.yml | 6 +++--- .github/workflows/release-napi.yml | 4 ++-- .github/workflows/rust-test.yml | 8 ++++---- .github/workflows/version-bump.yml | 4 ++-- 16 files changed, 42 insertions(+), 42 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 4fd1cc975..110e3758b 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -25,7 +25,7 @@ jobs: - target: i686-linux-android steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -33,7 +33,7 @@ jobs: toolchain: 1.67.0 # https://github.com/cross-rs/cross/issues/1222 - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: ${{ matrix.settings.target }}-cargo @@ -57,14 +57,14 @@ jobs: needs: build steps: - name: Checkout repo (PR) - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 if: github.event_name == 'pull_request' with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.ref }} - name: Checkout repo (Push) - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 if: github.event_name == 'push' with: fetch-depth: 0 @@ -75,7 +75,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: cargo-combine-cache diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 624a69c4f..9aa39ab51 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -22,7 +22,7 @@ jobs: package_version: ${{ steps.retrieve-version.outputs.package_version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Get Package Version id: retrieve-version @@ -60,7 +60,7 @@ jobs: target: aarch64-unknown-linux-gnu steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -69,7 +69,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} @@ -115,7 +115,7 @@ jobs: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download x86_64-apple-darwin artifact uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 @@ -155,7 +155,7 @@ jobs: - setup steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -163,7 +163,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: cargo-cli-about diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 608e8c47d..272fec363 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout Repository - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index b55ef939f..45fab6703 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -51,7 +51,7 @@ jobs: strip *.node steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 @@ -67,7 +67,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} diff --git a/.github/workflows/build-rust-crates.yml b/.github/workflows/build-rust-crates.yml index 0b868367d..203276556 100644 --- a/.github/workflows/build-rust-crates.yml +++ b/.github/workflows/build-rust-crates.yml @@ -34,7 +34,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -43,7 +43,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Build run: cargo build -p ${{ matrix.package }} --release @@ -64,7 +64,7 @@ jobs: - build steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -73,7 +73,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Install cargo-release run: cargo install cargo-release diff --git a/.github/workflows/build-rust-cross-platform.yml b/.github/workflows/build-rust-cross-platform.yml index 007cf5d17..7cfa9b078 100644 --- a/.github/workflows/build-rust-cross-platform.yml +++ b/.github/workflows/build-rust-cross-platform.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -30,7 +30,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Add build architecture run: rustup target add ${{ matrix.settings.target }} diff --git a/.github/workflows/cloc.yml b/.github/workflows/cloc.yml index 48f72ff65..a3afad257 100644 --- a/.github/workflows/cloc.yml +++ b/.github/workflows/cloc.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Set up cloc run: | diff --git a/.github/workflows/direct-minimal-versions.yml b/.github/workflows/direct-minimal-versions.yml index 579817c49..b2085892a 100644 --- a/.github/workflows/direct-minimal-versions.yml +++ b/.github/workflows/direct-minimal-versions.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -45,7 +45,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: dmv-${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 9b2ac57c3..cac5bc2b8 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -31,7 +31,7 @@ jobs: run: npm ci - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: NPM Schemas run: npm run schemas diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 425f4e83a..a18e5064a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -25,7 +25,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Cargo fmt run: cargo fmt --check diff --git a/.github/workflows/publish-dotnet.yml b/.github/workflows/publish-dotnet.yml index 7c819986e..c86b90dd1 100644 --- a/.github/workflows/publish-dotnet.yml +++ b/.github/workflows/publish-dotnet.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout Repository - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index 2c30e0fde..1c5484a5c 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -43,7 +43,7 @@ jobs: packages_command: ${{ steps.packages-list.outputs.packages_command }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Branch check if: ${{ github.event.inputs.release_type != 'Dry Run' }} @@ -100,7 +100,7 @@ jobs: - setup steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Login to Azure uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 @@ -120,7 +120,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Install cargo-release run: cargo install cargo-release diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 234b43aed..3651e14bc 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -27,7 +27,7 @@ jobs: release-version: ${{ steps.version.outputs.version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Branch check if: ${{ github.event.inputs.release_type != 'Dry Run' }} @@ -125,7 +125,7 @@ jobs: - setup steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Login to Azure uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 @@ -145,7 +145,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Install cargo-release run: cargo install cargo-release diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index cff308754..ee0407587 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -33,7 +33,7 @@ jobs: release-version: ${{ steps.version.outputs.version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Branch check if: ${{ github.event.inputs.release_type != 'Dry Run' }} @@ -90,7 +90,7 @@ jobs: _PKG_VERSION: ${{ needs.setup.outputs.release-version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index f77cb29f6..d4177bea1 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -44,7 +44,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Test run: cargo test --all-features @@ -56,7 +56,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -65,7 +65,7 @@ jobs: targets: wasm32-unknown-unknown - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Check run: cargo check -p bitwarden-wasm --target wasm32-unknown-unknown diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index fd651e2b2..29ee28f80 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Branch - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -37,7 +37,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Install cargo-release run: cargo install cargo-edit From b2ae2722b5c7a7a34c8e1d5859524f88068b2edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 30 Oct 2023 16:39:03 +0100 Subject: [PATCH 05/30] Split Encryptable/Decryptable trait into encryption and key retrieval (#297) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective At the moment, the `Encryptable`/`Decryptable` trait handles both encryption/decryption and key retrieval. The goal of this PR is to split this trait into two parts, one part that only handles encryption/decryption (and thus will be able to be moved into a separate `bitwarden-crypto` crate, if we want), and another part that handles retrieving the corresponding encryption key for each model object. ## Code changes What was the `Encryptable`/`Decryptable` trait has been split into multiple parts: - `KeyEncryptable`/`KeyDecryptable`: This receives only the encryption key and handles encryption/decryption only. The name of the interface was chosen to match the current `EncString::decrypt_with_key`, which this replaces. - `LocateKey`, which is implemented by types that know the type of key they need. For example a `Folder` always uses the user key and a `Cipher` uses the user key or one of the organization keys depending on its `organization_id` field. - `Encryptable`/`Decryptable`, this is now a thin compatibility layer between the previously mentioned two, to keep the existing API for the moment and keep the changes in this PR to a minimum. In the future we might decide that it's not necessary. With these changes, any models should implement `KeyEncryptable`/`KeyDecryptable` only, and `LocateKey` if applicable, but never `Encryptable`/`Decryptable` directly. Some of these changes will be more fleshed out in the future to avoid cluttering this PR, so I expect this won't look perfect: - Both `LocateKey` and `Encryptable` have an interface like `enc: &EncryptionSettings, org_id: &Option`. The organization parameter is mostly superfluous now and will be removed in the future: Objects that implement `LocateKey` do not use it, while objects which don't implement it should be provided the keys directly. - `EncString` is implementing `LocateKey` now, which goes against the explanation above. This is to avoid refactoring some secrets manager code, which I'll do on a later PR. - `EncryptionSettings` will change in the future, specially the `get_key` implementation, to be more generic. It also contains an `encrypt` function that shouldn't be there, but is used in a couple of spots of the code base and I'll remove on a later PR. - `KeyEncryptable`/`KeyDecryptable` only handles `SymmetricCryptoKey`, this will be made more generic over key type. --- .../bitwarden/src/auth/login/access_token.rs | 4 +- .../src/client/encryption_settings.rs | 38 +------ crates/bitwarden/src/crypto/enc_string.rs | 57 +++++++--- crates/bitwarden/src/crypto/encryptable.rs | 47 ++++---- .../bitwarden/src/crypto/key_encryptable.rs | 69 ++++++++++++ crates/bitwarden/src/crypto/master_key.rs | 6 +- crates/bitwarden/src/crypto/mod.rs | 4 +- .../src/mobile/vault/client_sends.rs | 22 ++-- .../bitwarden/src/vault/cipher/attachment.rs | 20 ++-- crates/bitwarden/src/vault/cipher/card.rs | 36 +++--- crates/bitwarden/src/vault/cipher/cipher.rs | 99 ++++++++++------- crates/bitwarden/src/vault/cipher/field.rs | 20 ++-- crates/bitwarden/src/vault/cipher/identity.rs | 84 +++++++------- .../bitwarden/src/vault/cipher/local_data.rs | 12 +- crates/bitwarden/src/vault/cipher/login.rs | 40 ++++--- .../bitwarden/src/vault/cipher/secure_note.rs | 12 +- crates/bitwarden/src/vault/collection.rs | 19 +++- crates/bitwarden/src/vault/folder.rs | 17 +-- .../bitwarden/src/vault/password_history.rs | 22 ++-- crates/bitwarden/src/vault/send.rs | 103 ++++++++---------- 20 files changed, 398 insertions(+), 333 deletions(-) create mode 100644 crates/bitwarden/src/crypto/key_encryptable.rs diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index 63fd86ebb..e7d60951c 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -8,7 +8,7 @@ use crate::{ login::{response::two_factor::TwoFactorProviders, PasswordLoginResponse}, }, client::{AccessToken, LoginMethod, ServiceAccountLoginMethod}, - crypto::{EncString, SymmetricCryptoKey}, + crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}, error::{Error, Result}, util::{decode_token, BASE64_ENGINE}, Client, @@ -29,7 +29,7 @@ pub(crate) async fn access_token_login( // Extract the encrypted payload and use the access token encryption key to decrypt it let payload: EncString = r.encrypted_payload.parse()?; - let decrypted_payload = payload.decrypt_with_key(&access_token.encryption_key)?; + let decrypted_payload: Vec = payload.decrypt_with_key(&access_token.encryption_key)?; // Once decrypted, we have to JSON decode to extract the organization encryption key #[derive(serde::Deserialize)] diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index 9c79a1781..e6cf3e145 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -4,7 +4,7 @@ use rsa::RsaPrivateKey; use uuid::Uuid; #[cfg(feature = "internal")] use { - crate::client::UserLoginMethod, + crate::{client::UserLoginMethod, crypto::KeyDecryptable}, rsa::{pkcs8::DecodePrivateKey, Oaep}, }; @@ -46,7 +46,7 @@ impl EncryptionSettings { // Decrypt the private key with the user key let private_key = { - let dec = private_key.decrypt_with_key(&user_key)?; + let dec: Vec = private_key.decrypt_with_key(&user_key)?; Some( rsa::RsaPrivateKey::from_pkcs8_der(&dec) .map_err(|_| CryptoError::InvalidKey)?, @@ -98,7 +98,7 @@ impl EncryptionSettings { Ok(self) } - fn get_key(&self, org_id: &Option) -> Option<&SymmetricCryptoKey> { + pub(crate) fn get_key(&self, org_id: &Option) -> Option<&SymmetricCryptoKey> { // If we don't have a private key set (to decode multiple org keys), we just use the main user key if self.private_key.is_none() { return Some(&self.user_key); @@ -110,20 +110,6 @@ impl EncryptionSettings { } } - pub(crate) fn decrypt_bytes( - &self, - cipher: &EncString, - org_id: &Option, - ) -> Result> { - let key = self.get_key(org_id).ok_or(CryptoError::NoKeyForOrg)?; - cipher.decrypt_with_key(key) - } - - pub(crate) fn decrypt(&self, cipher: &EncString, org_id: &Option) -> Result { - let dec = self.decrypt_bytes(cipher, org_id)?; - String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String.into()) - } - pub(crate) fn encrypt(&self, data: &[u8], org_id: &Option) -> Result { let key = self.get_key(org_id).ok_or(CryptoError::NoKeyForOrg)?; @@ -131,21 +117,3 @@ impl EncryptionSettings { Ok(dec) } } - -#[cfg(test)] -mod tests { - use super::{EncryptionSettings, SymmetricCryptoKey}; - use crate::crypto::{Decryptable, Encryptable}; - - #[test] - fn test_encryption_settings() { - let key = SymmetricCryptoKey::generate("test"); - let settings = EncryptionSettings::new_single_key(key); - - let test_string = "encrypted_test_string".to_string(); - let cipher = test_string.clone().encrypt(&settings, &None).unwrap(); - - let decrypted_str = cipher.decrypt(&settings, &None).unwrap(); - assert_eq!(decrypted_str, test_string); - } -} diff --git a/crates/bitwarden/src/crypto/enc_string.rs b/crates/bitwarden/src/crypto/enc_string.rs index b701aaf8f..976065e60 100644 --- a/crates/bitwarden/src/crypto/enc_string.rs +++ b/crates/bitwarden/src/crypto/enc_string.rs @@ -2,15 +2,15 @@ use std::{fmt::Display, str::FromStr}; use base64::Engine; use serde::{de::Visitor, Deserialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{decrypt_aes256_hmac, Decryptable, Encryptable, SymmetricCryptoKey}, + crypto::{decrypt_aes256_hmac, SymmetricCryptoKey}, error::{CryptoError, EncStringParseError, Error, Result}, util::BASE64_ENGINE, }; +use super::{KeyDecryptable, KeyEncryptable, LocateKey}; + #[derive(Clone)] #[allow(unused, non_camel_case_types)] pub enum EncString { @@ -304,8 +304,24 @@ impl EncString { EncString::Rsa2048_OaepSha1_HmacSha256_B64 { .. } => 6, } } +} - pub fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { +fn invalid_len_error(expected: usize) -> impl Fn(Vec) -> EncStringParseError { + move |e: Vec<_>| EncStringParseError::InvalidLength { + expected, + got: e.len(), + } +} + +impl LocateKey for EncString {} +impl KeyEncryptable for &[u8] { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + super::encrypt_aes256_hmac(self, key.mac_key.ok_or(CryptoError::InvalidMac)?, key.key) + } +} + +impl KeyDecryptable> for EncString { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { match self { EncString::AesCbc256_HmacSha256_B64 { iv, mac, data } => { let mac_key = key.mac_key.ok_or(CryptoError::InvalidMac)?; @@ -317,29 +333,36 @@ impl EncString { } } -fn invalid_len_error(expected: usize) -> impl Fn(Vec) -> EncStringParseError { - move |e: Vec<_>| EncStringParseError::InvalidLength { - expected, - got: e.len(), - } -} - -impl Encryptable for String { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { - enc.encrypt(self.as_bytes(), org_id) +impl KeyEncryptable for String { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + self.as_bytes().encrypt_with_key(key) } } -impl Decryptable for EncString { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { - enc.decrypt(self, org_id) +impl KeyDecryptable for EncString { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + let dec: Vec = self.decrypt_with_key(key)?; + String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String.into()) } } #[cfg(test)] mod tests { + use crate::crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; + use super::EncString; + #[test] + fn test_enc_string_roundtrip() { + let key = SymmetricCryptoKey::generate("test"); + + let test_string = "encrypted_test_string".to_string(); + let cipher = test_string.clone().encrypt_with_key(&key).unwrap(); + + let decrypted_str: String = cipher.decrypt_with_key(&key).unwrap(); + assert_eq!(decrypted_str, test_string); + } + #[test] fn test_enc_string_serialization() { #[derive(serde::Serialize, serde::Deserialize)] diff --git a/crates/bitwarden/src/crypto/encryptable.rs b/crates/bitwarden/src/crypto/encryptable.rs index bd987060f..10dbfaac6 100644 --- a/crates/bitwarden/src/crypto/encryptable.rs +++ b/crates/bitwarden/src/crypto/encryptable.rs @@ -2,7 +2,22 @@ use std::{collections::HashMap, hash::Hash}; use uuid::Uuid; -use crate::{client::encryption_settings::EncryptionSettings, error::Result}; +use crate::{ + client::encryption_settings::EncryptionSettings, + error::{Error, Result}, +}; + +use super::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; + +pub trait LocateKey { + fn locate_key<'a>( + &self, + enc: &'a EncryptionSettings, + org_id: &Option, + ) -> Option<&'a SymmetricCryptoKey> { + enc.get_key(org_id) + } +} pub trait Encryptable { fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result; @@ -12,15 +27,17 @@ pub trait Decryptable { fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result; } -impl, Output> Encryptable> for Option { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result> { - self.map(|e| e.encrypt(enc, org_id)).transpose() +impl + LocateKey, Output> Encryptable for T { + fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { + let key = self.locate_key(enc, org_id).ok_or(Error::VaultLocked)?; + self.encrypt_with_key(key) } } -impl, Output> Decryptable> for Option { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result> { - self.as_ref().map(|e| e.decrypt(enc, org_id)).transpose() +impl + LocateKey, Output> Decryptable for T { + fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { + let key = self.locate_key(enc, org_id).ok_or(Error::VaultLocked)?; + self.decrypt_with_key(key) } } @@ -46,7 +63,7 @@ impl, Output, Id: Hash + Eq> Encryptable Result> { self.into_iter() .map(|(id, e)| Ok((id, e.encrypt(enc, org_id)?))) - .collect::>>() + .collect() } } @@ -60,18 +77,6 @@ impl, Output, Id: Hash + Eq + Copy> Decryptable Result> { self.iter() .map(|(id, e)| Ok((*id, e.decrypt(enc, org_id)?))) - .collect::>>() - } -} - -impl, Output> Encryptable for Box { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { - (*self).encrypt(enc, org_id) - } -} - -impl, Output> Decryptable for Box { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { - (**self).decrypt(enc, org_id) + .collect() } } diff --git a/crates/bitwarden/src/crypto/key_encryptable.rs b/crates/bitwarden/src/crypto/key_encryptable.rs new file mode 100644 index 000000000..99c610bb2 --- /dev/null +++ b/crates/bitwarden/src/crypto/key_encryptable.rs @@ -0,0 +1,69 @@ +use std::{collections::HashMap, hash::Hash}; + +use crate::error::Result; + +use super::SymmetricCryptoKey; + +pub trait KeyEncryptable { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result; +} + +pub trait KeyDecryptable { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result; +} + +impl, Output> KeyEncryptable> for Option { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result> { + self.map(|e| e.encrypt_with_key(key)).transpose() + } +} + +impl, Output> KeyDecryptable> for Option { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { + self.as_ref().map(|e| e.decrypt_with_key(key)).transpose() + } +} + +impl, Output> KeyEncryptable for Box { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + (*self).encrypt_with_key(key) + } +} + +impl, Output> KeyDecryptable for Box { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + (**self).decrypt_with_key(key) + } +} + +impl, Output> KeyEncryptable> for Vec { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result> { + self.into_iter().map(|e| e.encrypt_with_key(key)).collect() + } +} + +impl, Output> KeyDecryptable> for Vec { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { + self.iter().map(|e| e.decrypt_with_key(key)).collect() + } +} + +impl, Output, Id: Hash + Eq> KeyEncryptable> + for HashMap +{ + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result> { + self.into_iter() + .map(|(id, e)| Ok((id, e.encrypt_with_key(key)?))) + .collect() + } +} + +impl, Output, Id: Hash + Eq + Copy> KeyDecryptable> + for HashMap +{ + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { + self.iter() + .map(|(id, e)| Ok((*id, e.decrypt_with_key(key)?))) + .collect() + } +} diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden/src/crypto/master_key.rs index f908d5299..064336edb 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden/src/crypto/master_key.rs @@ -4,8 +4,8 @@ use rand::Rng; use sha2::Digest; use super::{ - encrypt_aes256, hkdf_expand, EncString, PbkdfSha256Hmac, SymmetricCryptoKey, UserKey, - PBKDF_SHA256_HMAC_OUT_SIZE, + encrypt_aes256, hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, SymmetricCryptoKey, + UserKey, PBKDF_SHA256_HMAC_OUT_SIZE, }; use crate::{client::kdf::Kdf, error::Result, util::BASE64_ENGINE}; @@ -53,7 +53,7 @@ impl MasterKey { pub(crate) fn decrypt_user_key(&self, user_key: EncString) -> Result { let stretched_key = stretch_master_key(self)?; - let dec = user_key.decrypt_with_key(&stretched_key)?; + let dec: Vec = user_key.decrypt_with_key(&stretched_key)?; SymmetricCryptoKey::try_from(dec.as_slice()) } } diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs index b35157981..d8a1f0557 100644 --- a/crates/bitwarden/src/crypto/mod.rs +++ b/crates/bitwarden/src/crypto/mod.rs @@ -29,7 +29,9 @@ use crate::error::{Error, Result}; mod enc_string; pub use enc_string::EncString; mod encryptable; -pub use encryptable::{Decryptable, Encryptable}; +pub use encryptable::{Decryptable, Encryptable, LocateKey}; +mod key_encryptable; +pub use key_encryptable::{KeyDecryptable, KeyEncryptable}; mod aes_ops; pub use aes_ops::{decrypt_aes256, decrypt_aes256_hmac, encrypt_aes256, encrypt_aes256_hmac}; mod symmetric_crypto_key; diff --git a/crates/bitwarden/src/mobile/vault/client_sends.rs b/crates/bitwarden/src/mobile/vault/client_sends.rs index 0adef3410..b1de05f44 100644 --- a/crates/bitwarden/src/mobile/vault/client_sends.rs +++ b/crates/bitwarden/src/mobile/vault/client_sends.rs @@ -2,8 +2,8 @@ use std::path::Path; use super::client_vault::ClientVault; use crate::{ - crypto::{Decryptable, EncString, Encryptable}, - error::Result, + crypto::{Decryptable, EncString, Encryptable, KeyDecryptable, KeyEncryptable}, + error::{Error, Result}, vault::{Send, SendListView, SendView}, Client, }; @@ -43,11 +43,11 @@ impl<'a> ClientSends<'a> { pub async fn decrypt_buffer(&self, send: Send, encrypted_buffer: &[u8]) -> Result> { let enc = self.client.get_encryption_settings()?; - let enc = Send::get_encryption(&send.key, enc, &None)?; + let key = enc.get_key(&None).ok_or(Error::VaultLocked)?; + let key = Send::get_key(&send.key, key)?; let buf = EncString::from_buffer(encrypted_buffer)?; - - enc.decrypt_bytes(&buf, &None) + buf.decrypt_with_key(&key) } pub async fn encrypt(&self, send_view: SendView) -> Result { @@ -71,10 +71,14 @@ impl<'a> ClientSends<'a> { } pub async fn encrypt_buffer(&self, send: Send, buffer: &[u8]) -> Result> { - let enc = self.client.get_encryption_settings()?; - let enc = Send::get_encryption(&send.key, enc, &None)?; - - let enc = enc.encrypt(buffer, &None)?; + let key = self + .client + .get_encryption_settings()? + .get_key(&None) + .ok_or(Error::VaultLocked)?; + let key = Send::get_key(&send.key, key)?; + + let enc = buffer.encrypt_with_key(&key)?; enc.to_buffer() } } diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index 143e2a4f9..101c8f4bc 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -1,10 +1,8 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -33,28 +31,28 @@ pub struct AttachmentView { pub key: Option, } -impl Encryptable for AttachmentView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for AttachmentView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Attachment { id: self.id, url: self.url, size: self.size, size_name: self.size_name, - file_name: self.file_name.encrypt(enc, org_id)?, - key: self.key.encrypt(enc, org_id)?, + file_name: self.file_name.encrypt_with_key(key)?, + key: self.key.encrypt_with_key(key)?, }) } } -impl Decryptable for Attachment { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Attachment { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(AttachmentView { id: self.id.clone(), url: self.url.clone(), size: self.size.clone(), size_name: self.size_name.clone(), - file_name: self.file_name.decrypt(enc, org_id)?, - key: self.key.decrypt(enc, org_id)?, + file_name: self.file_name.decrypt_with_key(key)?, + key: self.key.decrypt_with_key(key)?, }) } } diff --git a/crates/bitwarden/src/vault/cipher/card.rs b/crates/bitwarden/src/vault/cipher/card.rs index 9636ba83f..1545ad171 100644 --- a/crates/bitwarden/src/vault/cipher/card.rs +++ b/crates/bitwarden/src/vault/cipher/card.rs @@ -1,10 +1,8 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -32,28 +30,28 @@ pub struct CardView { pub number: Option, } -impl Encryptable for CardView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for CardView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Card { - cardholder_name: self.cardholder_name.encrypt(enc, org_id)?, - exp_month: self.exp_month.encrypt(enc, org_id)?, - exp_year: self.exp_year.encrypt(enc, org_id)?, - code: self.code.encrypt(enc, org_id)?, - brand: self.brand.encrypt(enc, org_id)?, - number: self.number.encrypt(enc, org_id)?, + cardholder_name: self.cardholder_name.encrypt_with_key(key)?, + exp_month: self.exp_month.encrypt_with_key(key)?, + exp_year: self.exp_year.encrypt_with_key(key)?, + code: self.code.encrypt_with_key(key)?, + brand: self.brand.encrypt_with_key(key)?, + number: self.number.encrypt_with_key(key)?, }) } } -impl Decryptable for Card { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Card { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CardView { - cardholder_name: self.cardholder_name.decrypt(enc, org_id)?, - exp_month: self.exp_month.decrypt(enc, org_id)?, - exp_year: self.exp_year.decrypt(enc, org_id)?, - code: self.code.decrypt(enc, org_id)?, - brand: self.brand.decrypt(enc, org_id)?, - number: self.number.decrypt(enc, org_id)?, + cardholder_name: self.cardholder_name.decrypt_with_key(key)?, + exp_month: self.exp_month.decrypt_with_key(key)?, + exp_year: self.exp_year.decrypt_with_key(key)?, + code: self.code.decrypt_with_key(key)?, + brand: self.brand.decrypt_with_key(key)?, + number: self.number.decrypt_with_key(key)?, }) } } diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 9bf4bbd25..b01f17136 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -11,7 +11,7 @@ use super::{ }; use crate::{ client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, error::Result, vault::password_history, }; @@ -129,30 +129,29 @@ pub struct CipherListView { pub revision_date: DateTime, } -impl Encryptable for CipherView { - fn encrypt(self, enc: &EncryptionSettings, _: &Option) -> Result { - let org_id = &self.organization_id; +impl KeyEncryptable for CipherView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Cipher { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids, - name: self.name.encrypt(enc, org_id)?, - notes: self.notes.encrypt(enc, org_id)?, + name: self.name.encrypt_with_key(key)?, + notes: self.notes.encrypt_with_key(key)?, r#type: self.r#type, - login: self.login.encrypt(enc, org_id)?, - identity: self.identity.encrypt(enc, org_id)?, - card: self.card.encrypt(enc, org_id)?, - secure_note: self.secure_note.encrypt(enc, org_id)?, + login: self.login.encrypt_with_key(key)?, + identity: self.identity.encrypt_with_key(key)?, + card: self.card.encrypt_with_key(key)?, + secure_note: self.secure_note.encrypt_with_key(key)?, favorite: self.favorite, reprompt: self.reprompt, organization_use_totp: self.organization_use_totp, edit: self.edit, view_password: self.view_password, - local_data: self.local_data.encrypt(enc, org_id)?, - attachments: self.attachments.encrypt(enc, org_id)?, - fields: self.fields.encrypt(enc, org_id)?, - password_history: self.password_history.encrypt(enc, org_id)?, + local_data: self.local_data.encrypt_with_key(key)?, + attachments: self.attachments.encrypt_with_key(key)?, + fields: self.fields.encrypt_with_key(key)?, + password_history: self.password_history.encrypt_with_key(key)?, creation_date: self.creation_date, deleted_date: self.deleted_date, revision_date: self.revision_date, @@ -160,30 +159,29 @@ impl Encryptable for CipherView { } } -impl Decryptable for Cipher { - fn decrypt(&self, enc: &EncryptionSettings, _: &Option) -> Result { - let org_id = &self.organization_id; +impl KeyDecryptable for Cipher { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CipherView { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids.clone(), - name: self.name.decrypt(enc, org_id)?, - notes: self.notes.decrypt(enc, org_id)?, + name: self.name.decrypt_with_key(key)?, + notes: self.notes.decrypt_with_key(key)?, r#type: self.r#type, - login: self.login.decrypt(enc, org_id)?, - identity: self.identity.decrypt(enc, org_id)?, - card: self.card.decrypt(enc, org_id)?, - secure_note: self.secure_note.decrypt(enc, org_id)?, + login: self.login.decrypt_with_key(key)?, + identity: self.identity.decrypt_with_key(key)?, + card: self.card.decrypt_with_key(key)?, + secure_note: self.secure_note.decrypt_with_key(key)?, favorite: self.favorite, reprompt: self.reprompt, organization_use_totp: self.organization_use_totp, edit: self.edit, view_password: self.view_password, - local_data: self.local_data.decrypt(enc, org_id)?, - attachments: self.attachments.decrypt(enc, org_id)?, - fields: self.fields.decrypt(enc, org_id)?, - password_history: self.password_history.decrypt(enc, org_id)?, + local_data: self.local_data.decrypt_with_key(key)?, + attachments: self.attachments.decrypt_with_key(key)?, + fields: self.fields.decrypt_with_key(key)?, + password_history: self.password_history.decrypt_with_key(key)?, creation_date: self.creation_date, deleted_date: self.deleted_date, revision_date: self.revision_date, @@ -192,17 +190,13 @@ impl Decryptable for Cipher { } impl Cipher { - fn get_decrypted_subtitle( - &self, - enc: &EncryptionSettings, - org_id: &Option, - ) -> Result { + fn get_decrypted_subtitle(&self, key: &SymmetricCryptoKey) -> Result { Ok(match self.r#type { CipherType::Login => { let Some(login) = &self.login else { return Ok(String::new()); }; - login.username.decrypt(enc, org_id)?.unwrap_or_default() + login.username.decrypt_with_key(key)?.unwrap_or_default() } CipherType::SecureNote => String::new(), CipherType::Card => { @@ -212,11 +206,12 @@ impl Cipher { let mut sub_title = String::new(); if let Some(brand) = &card.brand { - sub_title.push_str(&brand.decrypt(enc, org_id)?); + let brand: String = brand.decrypt_with_key(key)?; + sub_title.push_str(&brand); } if let Some(number) = &card.number { - let number = number.decrypt(enc, org_id)?; + let number: String = number.decrypt_with_key(key)?; let number_len = number.len(); if number_len > 4 { if !sub_title.is_empty() { @@ -242,14 +237,16 @@ impl Cipher { let mut sub_title = String::new(); if let Some(first_name) = &identity.first_name { - sub_title.push_str(&first_name.decrypt(enc, org_id)?); + let first_name: String = first_name.decrypt_with_key(key)?; + sub_title.push_str(&first_name); } if let Some(last_name) = &identity.last_name { if !sub_title.is_empty() { sub_title.push(' '); } - sub_title.push_str(&last_name.decrypt(enc, org_id)?); + let last_name: String = last_name.decrypt_with_key(key)?; + sub_title.push_str(&last_name); } sub_title @@ -258,16 +255,15 @@ impl Cipher { } } -impl Decryptable for Cipher { - fn decrypt(&self, enc: &EncryptionSettings, _: &Option) -> Result { - let org_id = &self.organization_id; +impl KeyDecryptable for Cipher { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CipherListView { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids.clone(), - name: self.name.decrypt(enc, org_id)?, - sub_title: self.get_decrypted_subtitle(enc, org_id)?, + name: self.name.decrypt_with_key(key)?, + sub_title: self.get_decrypted_subtitle(key)?, r#type: self.r#type, favorite: self.favorite, reprompt: self.reprompt, @@ -284,3 +280,22 @@ impl Decryptable for Cipher { }) } } + +impl LocateKey for Cipher { + fn locate_key<'a>( + &self, + enc: &'a EncryptionSettings, + _: &Option, + ) -> Option<&'a SymmetricCryptoKey> { + enc.get_key(&self.organization_id) + } +} +impl LocateKey for CipherView { + fn locate_key<'a>( + &self, + enc: &'a EncryptionSettings, + _: &Option, + ) -> Option<&'a SymmetricCryptoKey> { + enc.get_key(&self.organization_id) + } +} diff --git a/crates/bitwarden/src/vault/cipher/field.rs b/crates/bitwarden/src/vault/cipher/field.rs index 9fa05257a..13f7dc9bb 100644 --- a/crates/bitwarden/src/vault/cipher/field.rs +++ b/crates/bitwarden/src/vault/cipher/field.rs @@ -1,12 +1,10 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use uuid::Uuid; use super::linked_id::LinkedIdType; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -42,22 +40,22 @@ pub struct FieldView { linked_id: Option, } -impl Encryptable for FieldView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for FieldView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Field { - name: self.name.encrypt(enc, org_id)?, - value: self.value.encrypt(enc, org_id)?, + name: self.name.encrypt_with_key(key)?, + value: self.value.encrypt_with_key(key)?, r#type: self.r#type, linked_id: self.linked_id, }) } } -impl Decryptable for Field { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Field { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(FieldView { - name: self.name.decrypt(enc, org_id)?, - value: self.value.decrypt(enc, org_id)?, + name: self.name.decrypt_with_key(key)?, + value: self.value.decrypt_with_key(key)?, r#type: self.r#type, linked_id: self.linked_id, }) diff --git a/crates/bitwarden/src/vault/cipher/identity.rs b/crates/bitwarden/src/vault/cipher/identity.rs index aace84152..d40991866 100644 --- a/crates/bitwarden/src/vault/cipher/identity.rs +++ b/crates/bitwarden/src/vault/cipher/identity.rs @@ -1,10 +1,8 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -56,52 +54,52 @@ pub struct IdentityView { pub license_number: Option, } -impl Encryptable for IdentityView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for IdentityView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Identity { - title: self.title.encrypt(enc, org_id)?, - first_name: self.first_name.encrypt(enc, org_id)?, - middle_name: self.middle_name.encrypt(enc, org_id)?, - last_name: self.last_name.encrypt(enc, org_id)?, - address1: self.address1.encrypt(enc, org_id)?, - address2: self.address2.encrypt(enc, org_id)?, - address3: self.address3.encrypt(enc, org_id)?, - city: self.city.encrypt(enc, org_id)?, - state: self.state.encrypt(enc, org_id)?, - postal_code: self.postal_code.encrypt(enc, org_id)?, - country: self.country.encrypt(enc, org_id)?, - company: self.company.encrypt(enc, org_id)?, - email: self.email.encrypt(enc, org_id)?, - phone: self.phone.encrypt(enc, org_id)?, - ssn: self.ssn.encrypt(enc, org_id)?, - username: self.username.encrypt(enc, org_id)?, - passport_number: self.passport_number.encrypt(enc, org_id)?, - license_number: self.license_number.encrypt(enc, org_id)?, + title: self.title.encrypt_with_key(key)?, + first_name: self.first_name.encrypt_with_key(key)?, + middle_name: self.middle_name.encrypt_with_key(key)?, + last_name: self.last_name.encrypt_with_key(key)?, + address1: self.address1.encrypt_with_key(key)?, + address2: self.address2.encrypt_with_key(key)?, + address3: self.address3.encrypt_with_key(key)?, + city: self.city.encrypt_with_key(key)?, + state: self.state.encrypt_with_key(key)?, + postal_code: self.postal_code.encrypt_with_key(key)?, + country: self.country.encrypt_with_key(key)?, + company: self.company.encrypt_with_key(key)?, + email: self.email.encrypt_with_key(key)?, + phone: self.phone.encrypt_with_key(key)?, + ssn: self.ssn.encrypt_with_key(key)?, + username: self.username.encrypt_with_key(key)?, + passport_number: self.passport_number.encrypt_with_key(key)?, + license_number: self.license_number.encrypt_with_key(key)?, }) } } -impl Decryptable for Identity { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Identity { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(IdentityView { - title: self.title.decrypt(enc, org_id)?, - first_name: self.first_name.decrypt(enc, org_id)?, - middle_name: self.middle_name.decrypt(enc, org_id)?, - last_name: self.last_name.decrypt(enc, org_id)?, - address1: self.address1.decrypt(enc, org_id)?, - address2: self.address2.decrypt(enc, org_id)?, - address3: self.address3.decrypt(enc, org_id)?, - city: self.city.decrypt(enc, org_id)?, - state: self.state.decrypt(enc, org_id)?, - postal_code: self.postal_code.decrypt(enc, org_id)?, - country: self.country.decrypt(enc, org_id)?, - company: self.company.decrypt(enc, org_id)?, - email: self.email.decrypt(enc, org_id)?, - phone: self.phone.decrypt(enc, org_id)?, - ssn: self.ssn.decrypt(enc, org_id)?, - username: self.username.decrypt(enc, org_id)?, - passport_number: self.passport_number.decrypt(enc, org_id)?, - license_number: self.license_number.decrypt(enc, org_id)?, + title: self.title.decrypt_with_key(key)?, + first_name: self.first_name.decrypt_with_key(key)?, + middle_name: self.middle_name.decrypt_with_key(key)?, + last_name: self.last_name.decrypt_with_key(key)?, + address1: self.address1.decrypt_with_key(key)?, + address2: self.address2.decrypt_with_key(key)?, + address3: self.address3.decrypt_with_key(key)?, + city: self.city.decrypt_with_key(key)?, + state: self.state.decrypt_with_key(key)?, + postal_code: self.postal_code.decrypt_with_key(key)?, + country: self.country.decrypt_with_key(key)?, + company: self.company.decrypt_with_key(key)?, + email: self.email.decrypt_with_key(key)?, + phone: self.phone.decrypt_with_key(key)?, + ssn: self.ssn.decrypt_with_key(key)?, + username: self.username.decrypt_with_key(key)?, + passport_number: self.passport_number.decrypt_with_key(key)?, + license_number: self.license_number.decrypt_with_key(key)?, }) } } diff --git a/crates/bitwarden/src/vault/cipher/local_data.rs b/crates/bitwarden/src/vault/cipher/local_data.rs index 1811ffa8b..8d5fe8694 100644 --- a/crates/bitwarden/src/vault/cipher/local_data.rs +++ b/crates/bitwarden/src/vault/cipher/local_data.rs @@ -1,10 +1,8 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, Encryptable}, + crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -24,8 +22,8 @@ pub struct LocalDataView { last_launched: Option, } -impl Encryptable for LocalDataView { - fn encrypt(self, _enc: &EncryptionSettings, _org_id: &Option) -> Result { +impl KeyEncryptable for LocalDataView { + fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { Ok(LocalData { last_used_date: self.last_used_date, last_launched: self.last_launched, @@ -33,8 +31,8 @@ impl Encryptable for LocalDataView { } } -impl Decryptable for LocalData { - fn decrypt(&self, _enc: &EncryptionSettings, _org_id: &Option) -> Result { +impl KeyDecryptable for LocalData { + fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { Ok(LocalDataView { last_used_date: self.last_used_date, last_launched: self.last_launched, diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index 941aed221..7a8e18411 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -2,11 +2,9 @@ use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -65,45 +63,45 @@ pub struct LoginView { pub autofill_on_page_load: Option, } -impl Encryptable for LoginUriView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for LoginUriView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(LoginUri { - uri: self.uri.encrypt(enc, org_id)?, + uri: self.uri.encrypt_with_key(key)?, r#match: self.r#match, }) } } -impl Encryptable for LoginView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for LoginView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Login { - username: self.username.encrypt(enc, org_id)?, - password: self.password.encrypt(enc, org_id)?, + username: self.username.encrypt_with_key(key)?, + password: self.password.encrypt_with_key(key)?, password_revision_date: self.password_revision_date, - uris: self.uris.encrypt(enc, org_id)?, - totp: self.totp.encrypt(enc, org_id)?, + uris: self.uris.encrypt_with_key(key)?, + totp: self.totp.encrypt_with_key(key)?, autofill_on_page_load: self.autofill_on_page_load, }) } } -impl Decryptable for LoginUri { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for LoginUri { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(LoginUriView { - uri: self.uri.decrypt(enc, org_id)?, + uri: self.uri.decrypt_with_key(key)?, r#match: self.r#match, }) } } -impl Decryptable for Login { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Login { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(LoginView { - username: self.username.decrypt(enc, org_id)?, - password: self.password.decrypt(enc, org_id)?, + username: self.username.decrypt_with_key(key)?, + password: self.password.decrypt_with_key(key)?, password_revision_date: self.password_revision_date, - uris: self.uris.decrypt(enc, org_id)?, - totp: self.totp.decrypt(enc, org_id)?, + uris: self.uris.decrypt_with_key(key)?, + totp: self.totp.decrypt_with_key(key)?, autofill_on_page_load: self.autofill_on_page_load, }) } diff --git a/crates/bitwarden/src/vault/cipher/secure_note.rs b/crates/bitwarden/src/vault/cipher/secure_note.rs index 422a55da1..0c7b4c799 100644 --- a/crates/bitwarden/src/vault/cipher/secure_note.rs +++ b/crates/bitwarden/src/vault/cipher/secure_note.rs @@ -1,11 +1,9 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, Encryptable}, + crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -30,16 +28,16 @@ pub struct SecureNoteView { r#type: SecureNoteType, } -impl Encryptable for SecureNoteView { - fn encrypt(self, _enc: &EncryptionSettings, _org_id: &Option) -> Result { +impl KeyEncryptable for SecureNoteView { + fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { Ok(SecureNote { r#type: self.r#type, }) } } -impl Decryptable for SecureNote { - fn decrypt(&self, _enc: &EncryptionSettings, _org_id: &Option) -> Result { +impl KeyDecryptable for SecureNote { + fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { Ok(SecureNoteView { r#type: self.r#type, }) diff --git a/crates/bitwarden/src/vault/collection.rs b/crates/bitwarden/src/vault/collection.rs index 38863a946..58492ef17 100644 --- a/crates/bitwarden/src/vault/collection.rs +++ b/crates/bitwarden/src/vault/collection.rs @@ -4,7 +4,7 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString}, + crypto::{EncString, KeyDecryptable, LocateKey, SymmetricCryptoKey}, error::Result, }; @@ -36,15 +36,22 @@ pub struct CollectionView { read_only: bool, } -impl Decryptable for Collection { - fn decrypt(&self, enc: &EncryptionSettings, _: &Option) -> Result { - let org_id = Some(self.organization_id); - +impl LocateKey for Collection { + fn locate_key<'a>( + &self, + enc: &'a EncryptionSettings, + _: &Option, + ) -> Option<&'a SymmetricCryptoKey> { + enc.get_key(&Some(self.organization_id)) + } +} +impl KeyDecryptable for Collection { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CollectionView { id: self.id, organization_id: self.organization_id, - name: self.name.decrypt(enc, &org_id)?, + name: self.name.decrypt_with_key(key)?, external_id: self.external_id.clone(), hide_passwords: self.hide_passwords, diff --git a/crates/bitwarden/src/vault/folder.rs b/crates/bitwarden/src/vault/folder.rs index 97d861310..f9ae06055 100644 --- a/crates/bitwarden/src/vault/folder.rs +++ b/crates/bitwarden/src/vault/folder.rs @@ -4,8 +4,7 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, error::Result, }; @@ -27,21 +26,23 @@ pub struct FolderView { revision_date: DateTime, } -impl Encryptable for FolderView { - fn encrypt(self, enc: &EncryptionSettings, _org: &Option) -> Result { +impl LocateKey for FolderView {} +impl KeyEncryptable for FolderView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Folder { id: self.id, - name: self.name.encrypt(enc, &None)?, + name: self.name.encrypt_with_key(key)?, revision_date: self.revision_date, }) } } -impl Decryptable for Folder { - fn decrypt(&self, enc: &EncryptionSettings, _org: &Option) -> Result { +impl LocateKey for Folder {} +impl KeyDecryptable for Folder { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(FolderView { id: self.id, - name: self.name.decrypt(enc, &None)?, + name: self.name.decrypt_with_key(key)?, revision_date: self.revision_date, }) } diff --git a/crates/bitwarden/src/vault/password_history.rs b/crates/bitwarden/src/vault/password_history.rs index 8566c9870..da6a4b19e 100644 --- a/crates/bitwarden/src/vault/password_history.rs +++ b/crates/bitwarden/src/vault/password_history.rs @@ -1,11 +1,9 @@ use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, error::Result, }; @@ -25,23 +23,21 @@ pub struct PasswordHistoryView { last_used_date: DateTime, } -impl Encryptable for PasswordHistoryView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl LocateKey for PasswordHistoryView {} +impl KeyEncryptable for PasswordHistoryView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(PasswordHistory { - password: self.password.encrypt(enc, org_id)?, + password: self.password.encrypt_with_key(key)?, last_used_date: self.last_used_date, }) } } -impl Decryptable for PasswordHistory { - fn decrypt( - &self, - enc: &EncryptionSettings, - org_id: &Option, - ) -> Result { +impl LocateKey for PasswordHistory {} +impl KeyDecryptable for PasswordHistory { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(PasswordHistoryView { - password: self.password.decrypt(enc, org_id)?, + password: self.password.decrypt_with_key(key)?, last_used_date: self.last_used_date, }) } diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index 124b9dc2f..5c463a0cf 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -5,8 +5,10 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{derive_shareable_key, Decryptable, EncString, Encryptable, SymmetricCryptoKey}, + crypto::{ + derive_shareable_key, EncString, KeyDecryptable, KeyEncryptable, LocateKey, + SymmetricCryptoKey, + }, error::Result, }; @@ -126,86 +128,75 @@ pub struct SendListView { } impl Send { - fn get_key( - key: &EncString, - enc: &EncryptionSettings, - org_id: &Option, + pub(crate) fn get_key( + send_key: &EncString, + enc_key: &SymmetricCryptoKey, ) -> Result { - let key: Vec = enc.decrypt_bytes(key, org_id)?; + let key: Vec = send_key.decrypt_with_key(enc_key)?; let key = derive_shareable_key(key.try_into().unwrap(), "send", Some("send")); Ok(key) } - - pub(crate) fn get_encryption( - key: &EncString, - enc: &EncryptionSettings, - org_id: &Option, - ) -> Result { - let key = Send::get_key(key, enc, org_id)?; - Ok(EncryptionSettings::new_single_key(key)) - } } -impl Decryptable for SendText { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for SendText { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(SendTextView { - text: self.text.decrypt(enc, org_id)?, + text: self.text.decrypt_with_key(key)?, hidden: self.hidden, }) } } -impl Encryptable for SendTextView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for SendTextView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(SendText { - text: self.text.encrypt(enc, org_id)?, + text: self.text.encrypt_with_key(key)?, hidden: self.hidden, }) } } -impl Decryptable for SendFile { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for SendFile { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(SendFileView { id: self.id.clone(), - file_name: self.file_name.decrypt(enc, org_id)?, + file_name: self.file_name.decrypt_with_key(key)?, size: self.size.clone(), size_name: self.size_name.clone(), }) } } -impl Encryptable for SendFileView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for SendFileView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(SendFile { id: self.id.clone(), - file_name: self.file_name.encrypt(enc, org_id)?, + file_name: self.file_name.encrypt_with_key(key)?, size: self.size.clone(), size_name: self.size_name.clone(), }) } } -impl Decryptable for Send { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl LocateKey for Send {} +impl KeyDecryptable for Send { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size - let enc_owned = Send::get_encryption(&self.key, enc, org_id)?; - - // For the rest of the fields, we ignore the provided EncryptionSettings and use a new one with the stretched key - let enc = &enc_owned; + // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key + let key = Send::get_key(&self.key, key)?; Ok(SendView { id: self.id, access_id: self.access_id.clone(), - name: self.name.decrypt(enc, org_id)?, - notes: self.notes.decrypt(enc, org_id)?, + name: self.name.decrypt_with_key(&key)?, + notes: self.notes.decrypt_with_key(&key)?, key: self.key.clone(), password: self.password.clone(), r#type: self.r#type, - file: self.file.decrypt(enc, org_id)?, - text: self.text.decrypt(enc, org_id)?, + file: self.file.decrypt_with_key(&key)?, + text: self.text.decrypt_with_key(&key)?, max_access_count: self.max_access_count, access_count: self.access_count, @@ -219,19 +210,17 @@ impl Decryptable for Send { } } -impl Decryptable for Send { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Send { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size - let enc_owned = Send::get_encryption(&self.key, enc, org_id)?; - - // For the rest of the fields, we ignore the provided EncryptionSettings and use a new one with the stretched key - let enc = &enc_owned; + // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key + let key = Send::get_key(&self.key, key)?; Ok(SendListView { id: self.id, access_id: self.access_id.clone(), - name: self.name.decrypt(enc, org_id)?, + name: self.name.decrypt_with_key(&key)?, r#type: self.r#type, disabled: self.disabled, @@ -243,27 +232,25 @@ impl Decryptable for Send { } } -impl Encryptable for SendView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl LocateKey for SendView {} +impl KeyEncryptable for SendView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size - let key = Send::get_key(&self.key, enc, org_id)?; - let enc_owned = EncryptionSettings::new_single_key(key); - - // For the rest of the fields, we ignore the provided EncryptionSettings and use a new one with the stretched key - let enc = &enc_owned; + // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key + let key = Send::get_key(&self.key, key)?; Ok(Send { id: self.id, access_id: self.access_id, - name: self.name.encrypt(enc, org_id)?, - notes: self.notes.encrypt(enc, org_id)?, + name: self.name.encrypt_with_key(&key)?, + notes: self.notes.encrypt_with_key(&key)?, key: self.key.clone(), password: self.password.clone(), r#type: self.r#type, - file: self.file.encrypt(enc, org_id)?, - text: self.text.encrypt(enc, org_id)?, + file: self.file.encrypt_with_key(&key)?, + text: self.text.encrypt_with_key(&key)?, max_access_count: self.max_access_count, access_count: self.access_count, @@ -298,6 +285,8 @@ mod tests { "2.kmLY8NJVuiKBFJtNd/ZFpA==|qOodlRXER+9ogCe3yOibRHmUcSNvjSKhdDuztLlucs10jLiNoVVVAc+9KfNErLSpx5wmUF1hBOJM8zwVPjgQTrmnNf/wuDpwiaCxNYb/0v4FygPy7ccAHK94xP1lfqq7U9+tv+/yiZSwgcT+xF0wFpoxQeNdNRFzPTuD9o4134n8bzacD9DV/WjcrXfRjbBCzzuUGj1e78+A7BWN7/5IWLz87KWk8G7O/W4+8PtEzlwkru6Wd1xO19GYU18oArCWCNoegSmcGn7w7NDEXlwD403oY8Oa7ylnbqGE28PVJx+HLPNIdSC6YKXeIOMnVs7Mctd/wXC93zGxAWD6ooTCzHSPVV50zKJmWIG2cVVUS7j35H3rGDtUHLI+ASXMEux9REZB8CdVOZMzp2wYeiOpggebJy6MKOZqPT1R3X0fqF2dHtRFPXrNsVr1Qt6bS9qTyO4ag1/BCvXF3P1uJEsI812BFAne3cYHy5bIOxuozPfipJrTb5WH35bxhElqwT3y/o/6JWOGg3HLDun31YmiZ2HScAsUAcEkA4hhoTNnqy4O2s3yVbCcR7jF7NLsbQc0MDTbnjxTdI4VnqUIn8s2c9hIJy/j80pmO9Bjxp+LQ9a2hUkfHgFhgHxZUVaeGVth8zG2kkgGdrp5VHhxMVFfvB26Ka6q6qE/UcS2lONSv+4T8niVRJz57qwctj8MNOkA3PTEfe/DP/LKMefke31YfT0xogHsLhDkx+mS8FCc01HReTjKLktk/Jh9mXwC5oKwueWWwlxI935ecn+3I2kAuOfMsgPLkoEBlwgiREC1pM7VVX1x8WmzIQVQTHd4iwnX96QewYckGRfNYWz/zwvWnjWlfcg8kRSe+68EHOGeRtC5r27fWLqRc0HNcjwpgHkI/b6czerCe8+07TWql4keJxJxhBYj3iOH7r9ZS8ck51XnOb8tGL1isimAJXodYGzakwktqHAD7MZhS+P02O+6jrg7d+yPC2ZCuS/3TOplYOCHQIhnZtR87PXTUwr83zfOwAwCyv6KP84JUQ45+DItrXLap7nOVZKQ5QxYIlbThAO6eima6Zu5XHfqGPMNWv0bLf5+vAjIa5np5DJrSwz9no/hj6CUh0iyI+SJq4RGI60lKtypMvF6MR3nHLEHOycRUQbZIyTHWl4QQLdHzuwN9lv10ouTEvNr6sFflAX2yb6w3hlCo7oBytH3rJekjb3IIOzBpeTPIejxzVlh0N9OT5MZdh4sNKYHUoWJ8mnfjdM+L4j5Q2Kgk/XiGDgEebkUxiEOQUdVpePF5uSCE+TPav/9FIRGXGiFn6NJMaU7aBsDTFBLloffFLYDpd8/bTwoSvifkj7buwLYM+h/qcnfdy5FWau1cKav+Blq/ZC0qBpo658RTC8ZtseAFDgXoQZuksM10hpP9bzD04Bx30xTGX81QbaSTNwSEEVrOtIhbDrj9OI43KH4O6zLzK+t30QxAv5zjk10RZ4+5SAdYndIlld9Y62opCfPDzRy3ubdve4ZEchpIKWTQvIxq3T5ogOhGaWBVYnkMtM2GVqvWV//46gET5SH/MdcwhACUcZ9kCpMnWH9CyyUwYvTT3UlNyV+DlS27LMPvaw7tx7qa+GfNCoCBd8S4esZpQYK/WReiS8=|pc7qpD42wxyXemdNPuwxbh8iIaryrBPu8f/DGwYdHTw=".parse().unwrap(), ).unwrap(); + let k = enc.get_key(&None).unwrap(); + // Create a send object, the only value we really care about here is the key let send = Send { id: "d7fb1e7f-9053-43c0-a02c-b0690098685a".parse().unwrap(), @@ -330,7 +319,7 @@ mod tests { }; // Get the send key - let send_key = Send::get_key(&send.key, &enc, &None).unwrap(); + let send_key = Send::get_key(&send.key, k).unwrap(); let send_key_b64 = send_key.to_base64(); assert_eq!(send_key_b64, "IR9ImHGm6rRuIjiN7csj94bcZR5WYTJj5GtNfx33zm6tJCHUl+QZlpNPba8g2yn70KnOHsAODLcR0um6E3MAlg=="); } From a9d52f0e670a5fc732de5dbdede14f43acb41b12 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 16:39:56 +0100 Subject: [PATCH 06/30] Update Rust crate async-lock to v3 (#310) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [async-lock](https://togithub.com/smol-rs/async-lock) | dependencies | major | `2.7.0` -> `3.0.0` | --- ### Release Notes
smol-rs/async-lock (async-lock) ### [`v3.0.0`](https://togithub.com/smol-rs/async-lock/blob/HEAD/CHANGELOG.md#Version-300) [Compare Source](https://togithub.com/smol-rs/async-lock/compare/v2.8.0...v3.0.0) - **Breaking:** Add an enabled-by-default `std` feature that allows using this crate without the standard library. ([#​43](https://togithub.com/smol-rs/async-lock/issues/43)) - Support blocking and non-blocking operations on the same locks. ([#​56](https://togithub.com/smol-rs/async-lock/issues/56)) - Switch to a more efficient event notification mechanism. ([#​43](https://togithub.com/smol-rs/async-lock/issues/43)) ### [`v2.8.0`](https://togithub.com/smol-rs/async-lock/blob/HEAD/CHANGELOG.md#Version-280) [Compare Source](https://togithub.com/smol-rs/async-lock/compare/v2.7.0...v2.8.0) - Fix a bug where the `SemaphoreGuard::acquire_arc` future would busy wait under certain conditions ([#​42](https://togithub.com/smol-rs/async-lock/issues/42)). - Add a `Semaphore::add_permits()` function to increase the number of available permits on the semaphore ([#​44](https://togithub.com/smol-rs/async-lock/issues/44)). - Make `RwLockReadGuard` covariant over its lifetime ([#​45](https://togithub.com/smol-rs/async-lock/issues/45)) - Add `RwLockReadGuardArc`, `RwLockWriteGuardArc`, and other reference counted guards for the `RwLock` type ([#​47](https://togithub.com/smol-rs/async-lock/issues/47)). - Loosen the `Send`/`Sync` bounds on certain future types ([#​48](https://togithub.com/smol-rs/async-lock/issues/48)). - Fix UB caused by the `MutexGuardArc::source` function allowing the user to drop an object in a different thread than the one it was acquired in ([#​50](https://togithub.com/smol-rs/async-lock/issues/50)). This is a breaking change, but in the name of soundness. Therefore it doesn't break any valid behavior. - Fix a bug where this crate would not compile properly on `wasm64` ([#​51](https://togithub.com/smol-rs/async-lock/issues/51)).
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 31 ++++++++++++++++++++++++++---- crates/bitwarden-uniffi/Cargo.toml | 2 +- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5bdbdc291..8cd3063db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,17 +197,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 2.5.3", "futures-core", ] [[package]] name = "async-lock" -version = "2.8.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +checksum = "45e900cdcd39bb94a14487d3f7ef92ca222162e6c7c3fe7cb3550ea75fb486ed" dependencies = [ - "event-listener", + "event-listener 3.0.0", + "event-listener-strategy", + "pin-project-lite", ] [[package]] @@ -1058,6 +1060,27 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "event-listener" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29e56284f00d94c1bc7fd3c77027b4623c88c1f53d8d2394c6199f2921dea325" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" +dependencies = [ + "event-listener 3.0.0", + "pin-project-lite", +] + [[package]] name = "eyre" version = "0.6.8" diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 60228c104..759e84e19 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["lib", "staticlib", "cdylib"] bench = false [dependencies] -async-lock = "2.7.0" +async-lock = "3.0.0" chrono = { version = ">=0.4.26, <0.5", features = [ "serde", "std", From 6754c7d704c6cda65dd2dddc21e2aba1170e586c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 31 Oct 2023 15:04:24 +0100 Subject: [PATCH 07/30] Lock file maintenance (#313) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Update | Change | |---|---| | lockFileMaintenance | All locks refreshed | 🔧 This Pull Request updates lock files to use the latest dependency versions. --- ### Configuration 📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 163 ++++++++++----------- crates/bitwarden-napi/package-lock.json | 26 ++-- languages/js_webassembly/package-lock.json | 54 ++++--- package-lock.json | 26 ++-- 4 files changed, 134 insertions(+), 135 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8cd3063db..92cc6e5f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -207,7 +207,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45e900cdcd39bb94a14487d3f7ef92ca222162e6c7c3fe7cb3550ea75fb486ed" dependencies = [ - "event-listener 3.0.0", + "event-listener 3.0.1", "event-listener-strategy", "pin-project-lite", ] @@ -252,9 +252,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.4" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "base64ct" @@ -264,9 +264,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basic-toml" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bfc506e7a2370ec239e1d072507b2a80c833083699d3c6fa176fbb4de8448c6" +checksum = "2f2139706359229bfa8f19142ac1155b4b80beafb7a60471ac5dd109d4a19778" dependencies = [ "serde", ] @@ -327,7 +327,7 @@ dependencies = [ "aes", "argon2", "assert_matches", - "base64 0.21.4", + "base64 0.21.5", "bitwarden-api-api", "bitwarden-api-identity", "cbc", @@ -545,7 +545,7 @@ dependencies = [ "tempfile", "thiserror", "tokio", - "toml 0.8.2", + "toml 0.8.6", "uuid", ] @@ -654,9 +654,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", @@ -664,9 +664,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", @@ -676,18 +676,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.3" +version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ae8ba90b9d8b007efe66e55e48fb936272f5ca00349b5b0e89877520d35ea7" +checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", @@ -697,9 +697,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "clircle" @@ -843,9 +843,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -1062,9 +1062,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e56284f00d94c1bc7fd3c77027b4623c88c1f53d8d2394c6199f2921dea325" +checksum = "01cec0252c2afff729ee6f00e903d479fba81784c8e2bd77447673471fdfaea1" dependencies = [ "concurrent-queue", "parking", @@ -1077,7 +1077,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" dependencies = [ - "event-listener 3.0.0", + "event-listener 3.0.1", "pin-project-lite", ] @@ -1154,9 +1154,9 @@ checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -1169,9 +1169,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -1179,15 +1179,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -1196,9 +1196,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-lite" @@ -1217,9 +1217,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", @@ -1228,15 +1228,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-timer" @@ -1246,9 +1246,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", @@ -1764,9 +1764,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "log", @@ -2018,9 +2018,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.1.5+3.1.3" +version = "300.1.6+3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559068e4c12950d7dcaa1857a61725c0d38d4fc03ff8e070ab31a75d6e316491" +checksum = "439fac53e092cd7442a3660c85dde4643ab3b5bd39040912388dcdabf6b88085" dependencies = [ "cc", ] @@ -2180,7 +2180,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a4a0cfc5fb21a09dc6af4bf834cf10d4a32fccd9e2ea468c4b1751a097487aa" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "indexmap 1.9.3", "line-wrap", "quick-xml", @@ -2403,15 +2403,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -2473,7 +2464,7 @@ version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -2514,25 +2505,23 @@ checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0" [[package]] name = "rgb" -version = "0.8.36" +version = "0.8.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" +checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" dependencies = [ "bytemuck", ] [[package]] name = "rsa" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" +checksum = "86ef35bf3e7fe15a53c4ab08a998e42271eab13eb0db224126bc7bc4c4bad96d" dependencies = [ - "byteorder", "const-oid", "digest", "num-bigint-dig", "num-integer", - "num-iter", "num-traits", "pkcs1", "pkcs8", @@ -2551,9 +2540,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.20" +version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ "bitflags 2.4.1", "errno", @@ -2704,18 +2693,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.189" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.189" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" dependencies = [ "proc-macro2", "quote", @@ -2735,9 +2724,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -2768,9 +2757,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", @@ -2779,9 +2768,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ "serde", ] @@ -2800,9 +2789,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.25" +version = "0.9.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" +checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" dependencies = [ "indexmap 2.0.2", "itoa", @@ -3062,13 +3051,13 @@ checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tempfile" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand 2.0.1", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "rustix", "windows-sys 0.48.0", ] @@ -3196,9 +3185,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -3219,9 +3208,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.2" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +checksum = "8ff9e3abce27ee2c9a37f9ad37238c1bdd4e789c84ba37df76aa4d528f5072cc" dependencies = [ "serde", "serde_spanned", @@ -3231,18 +3220,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ "indexmap 2.0.2", "serde", @@ -3889,7 +3878,7 @@ checksum = "c6f71803d3a1c80377a06221e0530be02035d5b3e854af56c6ece7ac20ac441d" dependencies = [ "assert-json-diff", "async-trait", - "base64 0.21.4", + "base64 0.21.5", "deadpool", "futures", "futures-timer", diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index b0df11947..4a85cb304 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -95,19 +95,19 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "version": "20.8.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", + "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", "dev": true, "peer": true, "dependencies": { - "undici-types": "~5.25.1" + "undici-types": "~5.26.4" } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -117,9 +117,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", "dev": true, "engines": { "node": ">=0.4.0" @@ -209,9 +209,9 @@ } }, "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "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, "peer": true }, diff --git a/languages/js_webassembly/package-lock.json b/languages/js_webassembly/package-lock.json index ea4d8b7f3..066f862be 100644 --- a/languages/js_webassembly/package-lock.json +++ b/languages/js_webassembly/package-lock.json @@ -209,12 +209,21 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "version": "20.8.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", + "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", "dev": true, "dependencies": { - "undici-types": "~5.25.1" + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.8.tgz", + "integrity": "sha512-vGXshY9vim9CJjrpcS5raqSjEfKlJcWy2HNdgUasR66fAnVEYarrf1ULV4nfvpC1nZq/moA9qyqBcu83x+Jlrg==", + "dev": true, + "dependencies": { + "@types/node": "*" } }, "node_modules/@types/qs": { @@ -499,9 +508,9 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -827,9 +836,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001553", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001553.tgz", - "integrity": "sha512-N0ttd6TrFfuqKNi+pMgWJTb9qrdJu4JSpgPFLe/lrD19ugC6fZgF0pUewRowDwzdDnb9V41mFcdlYgl/PyKf4A==", + "version": "1.0.30001558", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001558.tgz", + "integrity": "sha512-/Et7DwLqpjS47JPEcz6VnxU9PwcIdVi0ciLXRWBQdj1XFye68pSQYpV0QtPTfUKWuOaEig+/Vez2l74eDc1tPQ==", "dev": true, "funding": [ { @@ -1269,9 +1278,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.563", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.563.tgz", - "integrity": "sha512-dg5gj5qOgfZNkPNeyKBZQAQitIQ/xwfIDmEQJHCbXaD9ebTZxwJXUsDYcBlAvZGZLi+/354l35J1wkmP6CqYaw==", + "version": "1.4.569", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.569.tgz", + "integrity": "sha512-LsrJjZ0IbVy12ApW3gpYpcmHS3iRxH4bkKOW98y1/D+3cvDUWGcbzbsFinfUS8knpcZk/PG/2p/RnkMCYN7PVg==", "dev": true }, "node_modules/encodeurl": { @@ -3089,11 +3098,12 @@ "dev": true }, "node_modules/selfsigned": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", - "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "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": { @@ -3511,9 +3521,9 @@ } }, "node_modules/terser": { - "version": "5.22.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.22.0.tgz", - "integrity": "sha512-hHZVLgRA2z4NWcN6aS5rQDc+7Dcy58HOf2zbYwmFcQ+ua3h6eEFf5lIDKTzbWwlazPyOZsFQO8V80/IjVNExEw==", + "version": "5.23.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.23.0.tgz", + "integrity": "sha512-Iyy83LN0uX9ZZLCX4Qbu5JiHiWjOCTwrmM9InWOzVeM++KNWEsqV4YgN9U9E8AlohQ6Gs42ztczlWOG/lwDAMA==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -3665,9 +3675,9 @@ } }, "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "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": { diff --git a/package-lock.json b/package-lock.json index 0918c67ba..2ee17dd0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -363,13 +363,13 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "version": "20.8.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", + "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", "dev": true, "peer": true, "dependencies": { - "undici-types": "~5.25.1" + "undici-types": "~5.26.4" } }, "node_modules/@types/urijs": { @@ -391,9 +391,9 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -403,9 +403,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", "dev": true, "engines": { "node": ">=0.4.0" @@ -1974,9 +1974,9 @@ } }, "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "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, "peer": true }, From 1c86c09e7d12b8103b7c32342b368d0f49950695 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Wed, 1 Nov 2023 12:19:04 +0100 Subject: [PATCH 08/30] Fix make_user_key which previously didn't stretch the users key (#315) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective The `make_user_key` needs to use the same key as `decrypt_user_key`, which should be the stretched users key. ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --- Cargo.lock | 1 + crates/bitwarden/Cargo.toml | 1 + crates/bitwarden/src/auth/register.rs | 6 +- crates/bitwarden/src/client/client.rs | 10 +-- crates/bitwarden/src/crypto/master_key.rs | 75 ++++++++++++++++++++--- crates/bitwarden/src/crypto/user_key.rs | 2 +- crates/bitwarden/tests/register.rs | 35 +++++++++++ 7 files changed, 111 insertions(+), 19 deletions(-) create mode 100644 crates/bitwarden/tests/register.rs diff --git a/Cargo.lock b/Cargo.lock index 92cc6e5f4..b865c9fe6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -341,6 +341,7 @@ dependencies = [ "num-traits", "pbkdf2", "rand 0.8.5", + "rand_chacha 0.3.1", "reqwest", "rsa", "schemars", diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 0090ebb0e..fcbe5b3ac 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -59,5 +59,6 @@ bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.2 bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.2" } [dev-dependencies] +rand_chacha = "0.3.1" tokio = { version = "1.28.2", features = ["rt", "macros"] } wiremock = "0.5.18" diff --git a/crates/bitwarden/src/auth/register.rs b/crates/bitwarden/src/auth/register.rs index 8336ec9c9..206c1905b 100644 --- a/crates/bitwarden/src/auth/register.rs +++ b/crates/bitwarden/src/auth/register.rs @@ -79,7 +79,7 @@ pub(super) fn make_register_keys( #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct RegisterKeyResponse { - master_password_hash: String, - encrypted_user_key: String, - keys: RsaKeyPair, + pub master_password_hash: String, + pub encrypted_user_key: String, + pub keys: RsaKeyPair, } diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index f6eb0c954..b29118fe5 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -1,5 +1,10 @@ use std::time::{Duration, Instant}; +use reqwest::header::{self}; +use uuid::Uuid; + +#[cfg(feature = "secrets")] +use crate::auth::login::{access_token_login, AccessTokenLoginRequest, AccessTokenLoginResponse}; #[cfg(feature = "internal")] use crate::{ auth::login::{ @@ -13,11 +18,6 @@ use crate::{ SecretVerificationRequest, SyncRequest, SyncResponse, UserApiKeyResponse, }, }; -use reqwest::header::{self}; -use uuid::Uuid; - -#[cfg(feature = "secrets")] -use crate::auth::login::{access_token_login, AccessTokenLoginRequest, AccessTokenLoginResponse}; use crate::{ auth::renew::renew_token, client::{ diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden/src/crypto/master_key.rs index 064336edb..b2c8e6e5f 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden/src/crypto/master_key.rs @@ -4,8 +4,8 @@ use rand::Rng; use sha2::Digest; use super::{ - encrypt_aes256, hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, SymmetricCryptoKey, - UserKey, PBKDF_SHA256_HMAC_OUT_SIZE, + encrypt_aes256_hmac, hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, + SymmetricCryptoKey, UserKey, PBKDF_SHA256_HMAC_OUT_SIZE, }; use crate::{client::kdf::Kdf, error::Result, util::BASE64_ENGINE}; @@ -41,13 +41,7 @@ impl MasterKey { } pub(crate) fn make_user_key(&self) -> Result<(UserKey, EncString)> { - let mut user_key = [0u8; 64]; - rand::thread_rng().fill(&mut user_key); - - let protected = encrypt_aes256(&user_key, self.0.key)?; - - let u: &[u8] = &user_key; - Ok((UserKey::new(SymmetricCryptoKey::try_from(u)?), protected)) + make_user_key(rand::thread_rng(), self) } pub(crate) fn decrypt_user_key(&self, user_key: EncString) -> Result { @@ -58,6 +52,22 @@ impl MasterKey { } } +/// Generate a new random user key and encrypt it with the master key. +fn make_user_key( + mut rng: impl rand::RngCore, + master_key: &MasterKey, +) -> Result<(UserKey, EncString)> { + let mut user_key = [0u8; 64]; + rng.fill(&mut user_key); + + let stretched_key = stretch_master_key(master_key)?; + let protected = + encrypt_aes256_hmac(&user_key, stretched_key.mac_key.unwrap(), stretched_key.key)?; + + let u: &[u8] = &user_key; + Ok((UserKey::new(SymmetricCryptoKey::try_from(u)?), protected)) +} + /// Derive a generic key from a secret and salt using the provided KDF. fn derive_key(secret: &[u8], salt: &[u8], kdf: &Kdf) -> Result { let hash = match kdf { @@ -112,7 +122,9 @@ fn stretch_master_key(master_key: &MasterKey) -> Result { mod tests { use std::num::NonZeroU32; - use super::{stretch_master_key, HashPurpose, MasterKey}; + use rand::SeedableRng; + + use super::{make_user_key, stretch_master_key, HashPurpose, MasterKey}; use crate::{client::kdf::Kdf, crypto::SymmetricCryptoKey}; #[test] @@ -225,4 +237,47 @@ mod tests { .unwrap(), ); } + + #[test] + fn test_make_user_key() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + + let master_key = MasterKey(SymmetricCryptoKey { + key: [ + 31, 79, 104, 226, 150, 71, 177, 90, 194, 80, 172, 209, 17, 129, 132, 81, 138, 167, + 69, 167, 254, 149, 2, 27, 39, 197, 64, 42, 22, 195, 86, 75, + ] + .into(), + mac_key: None, + }); + + let (user_key, protected) = make_user_key(&mut rng, &master_key).unwrap(); + + assert_eq!( + user_key.0.key.as_slice(), + [ + 62, 0, 239, 47, 137, 95, 64, 214, 127, 91, 184, 232, 31, 9, 165, 161, 44, 132, 14, + 195, 206, 154, 127, 59, 24, 27, 225, 136, 239, 113, 26, 30 + ] + ); + assert_eq!( + user_key.0.mac_key.unwrap().as_slice(), + [ + 152, 76, 225, 114, 185, 33, 111, 65, 159, 68, 83, 103, 69, 109, 86, 25, 49, 74, 66, + 163, 218, 134, 176, 1, 56, 123, 253, 184, 14, 12, 254, 66 + ] + ); + + // Ensure we can decrypt the key and get back the same key + let decrypted = master_key.decrypt_user_key(protected).unwrap(); + + assert_eq!( + decrypted.key, user_key.0.key, + "Decrypted key doesn't match user key" + ); + assert_eq!( + decrypted.mac_key, user_key.0.mac_key, + "Decrypted key doesn't match user key" + ); + } } diff --git a/crates/bitwarden/src/crypto/user_key.rs b/crates/bitwarden/src/crypto/user_key.rs index 0fe560665..7f5bae413 100644 --- a/crates/bitwarden/src/crypto/user_key.rs +++ b/crates/bitwarden/src/crypto/user_key.rs @@ -6,7 +6,7 @@ use crate::{ error::Result, }; -pub(crate) struct UserKey(SymmetricCryptoKey); +pub(crate) struct UserKey(pub(super) SymmetricCryptoKey); impl UserKey { pub(crate) fn new(key: SymmetricCryptoKey) -> Self { diff --git a/crates/bitwarden/tests/register.rs b/crates/bitwarden/tests/register.rs new file mode 100644 index 000000000..d4e632e55 --- /dev/null +++ b/crates/bitwarden/tests/register.rs @@ -0,0 +1,35 @@ +/// Integration test for registering a new user and unlocking the vault +#[cfg(feature = "mobile")] +#[tokio::test] +async fn test_register_initialize_crypto() { + use std::num::NonZeroU32; + + use bitwarden::{client::kdf::Kdf, mobile::crypto::InitCryptoRequest, Client}; + + let mut client = Client::new(None); + + let email = "test@bitwarden.com"; + let password = "test123"; + let kdf = Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }; + + let register_response = client + .auth() + .make_register_keys(email.to_owned(), password.to_owned(), kdf.clone()) + .unwrap(); + + // Ensure we can initialize the crypto with the new keys + client + .crypto() + .initialize_crypto(InitCryptoRequest { + kdf_params: kdf, + email: email.to_owned(), + password: password.to_owned(), + user_key: register_response.encrypted_user_key, + private_key: register_response.keys.private.to_string(), + organization_keys: Default::default(), + }) + .await + .unwrap(); +} From 4819efd70240ced59f2a12f16d0ef13f01fb9fff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Wed, 1 Nov 2023 12:45:05 +0100 Subject: [PATCH 09/30] Update Rust crate uniffi to v0.25.0 (#303) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Updated Uniffi to 0.25.0. This required some code changes: - BitwardenError now needs to implement Error. - Defining the uniffi_support types in both crates seems to be causing duplicate symbols on xcode at least, so we instead use `ffi_converter_forward!` to forward the type definitions from the `bitwarden` crate to the `bitwarden-uniffi` crate. - There is a name collision with our `Send`, and Rust's `Send`, so I've changed the imports to use `vault::Send`. - Removed the unused UDL file. --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 154 +++++++++++++++--- Cargo.toml | 12 +- crates/bitwarden-uniffi/Cargo.toml | 4 +- crates/bitwarden-uniffi/src/error.rs | 10 +- crates/bitwarden-uniffi/src/sdk.udl | 8 - crates/bitwarden-uniffi/src/uniffi_support.rs | 17 +- crates/bitwarden-uniffi/src/vault/sends.rs | 16 +- crates/bitwarden/Cargo.toml | 2 +- crates/uniffi-bindgen/Cargo.toml | 2 +- 9 files changed, 157 insertions(+), 68 deletions(-) delete mode 100644 crates/bitwarden-uniffi/src/sdk.udl diff --git a/Cargo.lock b/Cargo.lock index b865c9fe6..e4bf4f9df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -287,7 +287,7 @@ dependencies = [ "flate2", "globset", "home", - "nu-ansi-term", + "nu-ansi-term 0.49.0", "once_cell", "path_abs", "plist", @@ -1263,6 +1263,19 @@ dependencies = [ "slab", ] +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1717,6 +1730,29 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "pin-utils", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "memchr" version = "2.6.4" @@ -1870,6 +1906,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "nu-ansi-term" version = "0.49.0" @@ -1963,6 +2009,15 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "oneshot" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f6640c6bda7731b1fdbab747981a0f896dd1fedaf9f4a53fa237a04a84431f4" +dependencies = [ + "loom", +] + [[package]] name = "onig" version = "6.4.0" @@ -2045,6 +2100,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "owo-colors" version = "3.5.0" @@ -2432,10 +2493,19 @@ checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-automata", + "regex-automata 0.4.3", "regex-syntax 0.8.2", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + [[package]] name = "regex-automata" version = "0.4.3" @@ -2447,6 +2517,12 @@ dependencies = [ "regex-syntax 0.8.2", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.7.5" @@ -3254,9 +3330,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "tracing-core" version = "0.1.32" @@ -3277,15 +3365,33 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" dependencies = [ + "matchers", + "nu-ansi-term 0.46.0", + "once_cell", + "regex", "sharded-slab", + "smallvec", "thread_local", + "tracing", "tracing-core", + "tracing-log", ] [[package]] @@ -3344,8 +3450,8 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uniffi" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "anyhow", "camino", @@ -3365,8 +3471,8 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "anyhow", "askama", @@ -3380,7 +3486,6 @@ dependencies = [ "once_cell", "paste", "serde", - "serde_json", "toml 0.5.11", "uniffi_meta", "uniffi_testing", @@ -3389,8 +3494,8 @@ dependencies = [ [[package]] name = "uniffi_build" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "anyhow", "camino", @@ -3399,8 +3504,8 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "quote", "syn 2.0.38", @@ -3408,23 +3513,23 @@ dependencies = [ [[package]] name = "uniffi_core" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "anyhow", "bytes", "camino", - "cargo_metadata", "log", "once_cell", + "oneshot", "paste", "static_assertions", ] [[package]] name = "uniffi_macros" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "bincode", "camino", @@ -3441,34 +3546,31 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "anyhow", "bytes", - "serde", "siphasher", "uniffi_checksum_derive", ] [[package]] name = "uniffi_testing" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "anyhow", "camino", "cargo_metadata", "fs-err", "once_cell", - "serde", - "serde_json", ] [[package]] name = "uniffi_udl" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "anyhow", "uniffi_meta", @@ -3675,7 +3777,7 @@ dependencies = [ [[package]] name = "weedle2" version = "4.0.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "nom", ] diff --git a/Cargo.toml b/Cargo.toml index dbd4ed30f..a192c14e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,10 +22,10 @@ codegen-units = 1 # This is fine as long as we don't have any unhandled panics, but let's keep it disabled for now # strip = true -# Uniffi proc-macro support is still not part of a release, so we need to use the git version for now +# Using master until 0.25.1 is released to fix https://github.com/mozilla/uniffi-rs/issues/1798 [patch.crates-io] -uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } -uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } -uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } -uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } -uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } +uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } +uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } +uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } +uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } +uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 759e84e19..a7b774c3c 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -18,13 +18,13 @@ chrono = { version = ">=0.4.26, <0.5", features = [ "std", ], default-features = false } env_logger = "0.10.0" -uniffi = "=0.24.1" +uniffi = "=0.25.0" schemars = { version = ">=0.8, <0.9", optional = true } bitwarden = { path = "../bitwarden", features = ["mobile", "internal"] } [build-dependencies] -uniffi = { version = "=0.24.1", features = ["build"] } +uniffi = { version = "=0.25.0", features = ["build"] } [target.'cfg(any(target_os = "android", target_os = "ios"))'.dependencies] openssl = { version = "0.10", features = ["vendored"] } diff --git a/crates/bitwarden-uniffi/src/error.rs b/crates/bitwarden-uniffi/src/error.rs index 1a1e9d29a..b6175eb3b 100644 --- a/crates/bitwarden-uniffi/src/error.rs +++ b/crates/bitwarden-uniffi/src/error.rs @@ -1,7 +1,7 @@ use std::fmt::{Display, Formatter}; // Name is converted from *Error to *Exception, so we can't just name the enum Error because Exception already exists -#[derive(uniffi::Error)] +#[derive(uniffi::Error, Debug)] #[uniffi(flat_error)] pub enum BitwardenError { E(bitwarden::error::Error), @@ -21,4 +21,12 @@ impl Display for BitwardenError { } } +impl std::error::Error for BitwardenError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + BitwardenError::E(e) => Some(e), + } + } +} + pub type Result = std::result::Result; diff --git a/crates/bitwarden-uniffi/src/sdk.udl b/crates/bitwarden-uniffi/src/sdk.udl deleted file mode 100644 index 96cfb31c0..000000000 --- a/crates/bitwarden-uniffi/src/sdk.udl +++ /dev/null @@ -1,8 +0,0 @@ -interface Client { - constructor(optional string settings = ""); - string run_command(string command); -}; - -namespace bitwarden { - -}; diff --git a/crates/bitwarden-uniffi/src/uniffi_support.rs b/crates/bitwarden-uniffi/src/uniffi_support.rs index f2a0bfde6..82cd343a7 100644 --- a/crates/bitwarden-uniffi/src/uniffi_support.rs +++ b/crates/bitwarden-uniffi/src/uniffi_support.rs @@ -1,16 +1,3 @@ -use crate::UniffiCustomTypeConverter; - +// Forward the type definitions to the main bitwarden crate type DateTime = chrono::DateTime; -uniffi::custom_type!(DateTime, std::time::SystemTime); - -impl UniffiCustomTypeConverter for chrono::DateTime { - type Builtin = std::time::SystemTime; - - fn into_custom(val: Self::Builtin) -> uniffi::Result { - Ok(Self::from(val)) - } - - fn from_custom(obj: Self) -> Self::Builtin { - obj.into() - } -} +uniffi::ffi_converter_forward!(DateTime, bitwarden::UniFfiTag, crate::UniFfiTag); diff --git a/crates/bitwarden-uniffi/src/vault/sends.rs b/crates/bitwarden-uniffi/src/vault/sends.rs index 6e2f1b879..696c4a861 100644 --- a/crates/bitwarden-uniffi/src/vault/sends.rs +++ b/crates/bitwarden-uniffi/src/vault/sends.rs @@ -1,6 +1,6 @@ use std::{path::Path, sync::Arc}; -use bitwarden::vault::{Send, SendListView, SendView}; +use bitwarden::vault::{self, SendListView, SendView}; use crate::{Client, Result}; @@ -10,12 +10,12 @@ pub struct ClientSends(pub Arc); #[uniffi::export] impl ClientSends { /// Encrypt send - pub async fn encrypt(&self, send: SendView) -> Result { + pub async fn encrypt(&self, send: SendView) -> Result { Ok(self.0 .0.read().await.vault().sends().encrypt(send).await?) } /// Encrypt a send file in memory - pub async fn encrypt_buffer(&self, send: Send, buffer: Vec) -> Result> { + pub async fn encrypt_buffer(&self, send: vault::Send, buffer: Vec) -> Result> { Ok(self .0 .0 @@ -30,7 +30,7 @@ impl ClientSends { /// Encrypt a send file located in the file system pub async fn encrypt_file( &self, - send: Send, + send: vault::Send, decrypted_file_path: String, encrypted_file_path: String, ) -> Result<()> { @@ -50,12 +50,12 @@ impl ClientSends { } /// Decrypt send - pub async fn decrypt(&self, send: Send) -> Result { + pub async fn decrypt(&self, send: vault::Send) -> Result { Ok(self.0 .0.read().await.vault().sends().decrypt(send).await?) } /// Decrypt send list - pub async fn decrypt_list(&self, sends: Vec) -> Result> { + pub async fn decrypt_list(&self, sends: Vec) -> Result> { Ok(self .0 .0 @@ -68,7 +68,7 @@ impl ClientSends { } /// Decrypt a send file in memory - pub async fn decrypt_buffer(&self, send: Send, buffer: Vec) -> Result> { + pub async fn decrypt_buffer(&self, send: vault::Send, buffer: Vec) -> Result> { Ok(self .0 .0 @@ -83,7 +83,7 @@ impl ClientSends { /// Decrypt a send file located in the file system pub async fn decrypt_file( &self, - send: Send, + send: vault::Send, encrypted_file_path: String, decrypted_file_path: String, ) -> Result<()> { diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index fcbe5b3ac..65db9db7d 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -50,7 +50,7 @@ chrono = { version = ">=0.4.26, <0.5", features = [ "serde", "std", ], default-features = false } -uniffi = { version = "=0.24.1", optional = true } +uniffi = { version = "=0.25.0", optional = true } # We don't use this directly (it's used by rand), but we need it here to enable WASM support getrandom = { version = ">=0.2.9", features = ["js"] } diff --git a/crates/uniffi-bindgen/Cargo.toml b/crates/uniffi-bindgen/Cargo.toml index c9c177c84..980434e89 100644 --- a/crates/uniffi-bindgen/Cargo.toml +++ b/crates/uniffi-bindgen/Cargo.toml @@ -10,4 +10,4 @@ name = "uniffi-bindgen" path = "uniffi-bindgen.rs" [dependencies] -uniffi = { version = "=0.24.1", features = ["cli"] } +uniffi = { version = "=0.25.0", features = ["cli"] } From a0bfa3c53e626ec371dfafff839af1c49da64315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 2 Nov 2023 17:14:06 +0100 Subject: [PATCH 10/30] [PM-4270] Individual cipher key encryption (#278) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Implement individual vault item encryption and encryption. Note that at the moment it will not migrate items that don't have a key when encrypting. --- crates/bitwarden/src/vault/cipher/cipher.rs | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index b01f17136..b95a2f090 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -43,6 +43,9 @@ pub struct Cipher { pub folder_id: Option, pub collection_ids: Vec, + /// More recent ciphers uses individual encryption keys to encrypt the other fields of the Cipher. + pub key: Option, + pub name: EncString, pub notes: Option, @@ -77,6 +80,8 @@ pub struct CipherView { pub folder_id: Option, pub collection_ids: Vec, + pub key: Option, + pub name: String, pub notes: Option, @@ -131,11 +136,15 @@ pub struct CipherListView { impl KeyEncryptable for CipherView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; + let key = ciphers_key.as_ref().unwrap_or(key); + Ok(Cipher { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids, + key: self.key, name: self.name.encrypt_with_key(key)?, notes: self.notes.encrypt_with_key(key)?, r#type: self.r#type, @@ -161,11 +170,15 @@ impl KeyEncryptable for CipherView { impl KeyDecryptable for Cipher { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; + let key = ciphers_key.as_ref().unwrap_or(key); + Ok(CipherView { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids.clone(), + key: self.key.clone(), name: self.name.decrypt_with_key(key)?, notes: self.notes.decrypt_with_key(key)?, r#type: self.r#type, @@ -190,6 +203,23 @@ impl KeyDecryptable for Cipher { } impl Cipher { + /// Get the decrypted individual encryption key for this cipher. + /// Note that some ciphers do not have individual encryption keys, + /// in which case this will return Ok(None) and the key associated + /// with this cipher's user or organization must be used instead + fn get_cipher_key( + key: &SymmetricCryptoKey, + ciphers_key: &Option, + ) -> Result> { + ciphers_key + .as_ref() + .map(|k| { + let key: Vec = k.decrypt_with_key(key)?; + SymmetricCryptoKey::try_from(key.as_slice()) + }) + .transpose() + } + fn get_decrypted_subtitle(&self, key: &SymmetricCryptoKey) -> Result { Ok(match self.r#type { CipherType::Login => { @@ -257,6 +287,9 @@ impl Cipher { impl KeyDecryptable for Cipher { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; + let key = ciphers_key.as_ref().unwrap_or(key); + Ok(CipherListView { id: self.id, organization_id: self.organization_id, From eefc58b783abbfdabbe12b98834168a20ff26de9 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 2 Nov 2023 17:53:10 +0100 Subject: [PATCH 11/30] Extract JWT to it's own file (#317) --- .vscode/settings.json | 1 + crates/bitwarden/src/auth/jwt_token.rs | 71 +++++++++++++++++++ .../bitwarden/src/auth/login/access_token.rs | 5 +- crates/bitwarden/src/auth/login/api_key.rs | 4 +- crates/bitwarden/src/auth/mod.rs | 2 + crates/bitwarden/src/util.rs | 53 -------------- 6 files changed, 79 insertions(+), 57 deletions(-) create mode 100644 crates/bitwarden/src/auth/jwt_token.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index e75498e9c..d49fe884f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,6 +15,7 @@ "Pbkdf", "PKCS8", "repr", + "reqwest", "schemars", "uniffi", "wordlist" diff --git a/crates/bitwarden/src/auth/jwt_token.rs b/crates/bitwarden/src/auth/jwt_token.rs new file mode 100644 index 000000000..14cbaf84f --- /dev/null +++ b/crates/bitwarden/src/auth/jwt_token.rs @@ -0,0 +1,71 @@ +use std::str::FromStr; + +use base64::Engine; + +use crate::{error::Result, util::BASE64_ENGINE}; + +/// A Bitwarden secrets manager JWT Token. +/// +/// References: +/// - +/// - +/// +/// TODO: We need to expand this to support user based JWT tokens. +#[derive(serde::Deserialize)] +pub struct JWTToken { + pub sub: String, + pub email: Option, + pub organization: Option, + pub scope: Vec, +} + +impl FromStr for JWTToken { + type Err = crate::error::Error; + + /// Parses a JWT token from a string. + /// + /// **Note:** This function does not validate the token signature. + fn from_str(s: &str) -> Result { + let split = s.split('.').collect::>(); + if split.len() != 3 { + return Err(crate::error::Error::Internal( + "JWT token has an invalid number of parts", + )); + } + let decoded = BASE64_ENGINE.decode(split[1])?; + Ok(serde_json::from_slice(&decoded)?) + } +} + +#[cfg(test)] +mod tests { + use crate::auth::jwt_token::JWTToken; + + #[test] + fn can_decode_jwt() { + let jwt = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjMwMURENkE1MEU4NEUxRDA5MUM4MUQzQjAwQkY5MDEwQz\ + g1REJEOUFSUzI1NiIsInR5cCI6ImF0K2p3dCIsIng1dCI6Ik1CM1dwUTZFNGRDUnlCMDdBTC1RRU1oZHZabyJ9.eyJu\ + YmYiOjE2NzUxMDM1NzcsImV4cCI6MTY3NTEwNzE3NywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdCIsImNsaWVudF9pZCI\ + 6IndlYiIsInN1YiI6ImUyNWQzN2YzLWI2MDMtNDBkZS04NGJhLWFmOTYwMTJmNWE0MiIsImF1dGhfdGltZSI6MTY3NT\ + EwMzU0OSwiaWRwIjoiYml0d2FyZGVuIiwicHJlbWl1bSI6ZmFsc2UsImVtYWlsIjoidGVzdEBiaXR3YXJkZW4uY29tI\ + iwiZW1haWxfdmVyaWZpZWQiOnRydWUsInNzdGFtcCI6IkUzNElDWVhRUFRDS01EVldBREZDNktHNDJCQldJRDdJIiwi\ + bmFtZSI6IlRlc3QiLCJvcmdvd25lciI6ImY0ZTQ0YTdmLTExOTAtNDMyYS05ZDRhLWFmOTYwMTMxMjdjYiIsImRldml\ + jZSI6Ijg5Mjg5M2FiLWRkNDMtNDUwYS04NGI1LWFhOWM1YjdiYjJkOCIsImp0aSI6IkEzMkVFNjY5NDdEQzlDNUE2MT\ + IwRURBRTIwNzc5OUJFIiwiaWF0IjoxNjc1MTAzNTc3LCJzY29wZSI6WyJhcGkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhb\ + XIiOlsiQXBwbGljYXRpb24iXX0.AyDkKvjmyaSPQViQSa2sGTKIkDGrUAtDmwpE57K4DDWT0QvwDe7FMktmwiF4LH36\ + wx_FnpH21VI1pzwJeTHXtaz3niANJtQZjzGFsNAna_95vrsxZC2YizgGlt6mX4YIGmAw9DiYrmaN0BvQOEm_caV_u6f\ + a30iz9Kvjxf7cpzeZvPEysxGpB3k3TRYTkFUdV43HiXdhXMBhyyOpFU6Fk6yA41y7-8bGYc5mYGknWktmPD9Yx-1xKL\ + ftFja1SnCoLPWvDeK60lqWZQiT4tZHCYJ7m0bBNCccYHc2Kk2Bo5-UoyDxazPwsqMxeNfjlaUuj3o5N_uQ-4n_gVbeA\ + qWV2wrel5UhYjWnczMSLBtt9p0W35kkBPt3ZAnRWMtQMPNH04p-_L6cG-Xu6lDksBTwaavcmtnCKG8V91826EiQ8MrF\ + wGWQRZV6tPKTDAYCgSAZGBY3QDmPGT5BeFcg5Ag_nYYIIifKP-kv10v_N-TOcT3NeGBOUlAZ-9m7iT7Rk3vC--SDZdA\ + U5turoBFiiPL2XXfAjM7P0r7J91gfXc0FaD6I2jDxOmym5h7Yn5phLsbC2NlIXkZp54dKHICenPl4ve6ndDIJacVeS5\ + f3LEddAPV8cAFza4DjA8pZJLFrMyRvMXcL_PjKF8qPVzqVWh03lfJ4clOIxR2gOuWIc902Y5E"; + + let token: JWTToken = jwt.parse().unwrap(); + assert_eq!(token.sub, "e25d37f3-b603-40de-84ba-af96012f5a42"); + assert_eq!(token.email.as_deref(), Some("test@bitwarden.com")); + assert_eq!(token.organization.as_deref(), None); + assert_eq!(token.scope[0], "api"); + assert_eq!(token.scope[1], "offline_access"); + } +} diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index e7d60951c..d80bfda84 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -6,11 +6,12 @@ use crate::{ auth::{ api::{request::AccessTokenRequest, response::IdentityTokenResponse}, login::{response::two_factor::TwoFactorProviders, PasswordLoginResponse}, + JWTToken, }, client::{AccessToken, LoginMethod, ServiceAccountLoginMethod}, crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}, error::{Error, Result}, - util::{decode_token, BASE64_ENGINE}, + util::BASE64_ENGINE, Client, }; @@ -44,7 +45,7 @@ pub(crate) async fn access_token_login( let encryption_key = SymmetricCryptoKey::try_from(encryption_key.as_slice())?; - let access_token_obj = decode_token(&r.access_token)?; + let access_token_obj: JWTToken = r.access_token.parse()?; // This should always be Some() when logging in with an access token let organization_id = access_token_obj diff --git a/crates/bitwarden/src/auth/login/api_key.rs b/crates/bitwarden/src/auth/login/api_key.rs index cdbc383ba..8a42396af 100644 --- a/crates/bitwarden/src/auth/login/api_key.rs +++ b/crates/bitwarden/src/auth/login/api_key.rs @@ -5,11 +5,11 @@ use crate::{ auth::{ api::{request::ApiTokenRequest, response::IdentityTokenResponse}, login::{response::two_factor::TwoFactorProviders, PasswordLoginResponse}, + JWTToken, }, client::{LoginMethod, UserLoginMethod}, crypto::EncString, error::{Error, Result}, - util::decode_token, Client, }; @@ -23,7 +23,7 @@ pub(crate) async fn api_key_login( let response = request_api_identity_tokens(client, input).await?; if let IdentityTokenResponse::Authenticated(r) = &response { - let access_token_obj = decode_token(&r.access_token)?; + let access_token_obj: JWTToken = r.access_token.parse()?; // This should always be Some() when logging in with an api key let email = access_token_obj diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index f2f6a3144..89197d4bc 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -1,10 +1,12 @@ pub(super) mod api; #[cfg(feature = "internal")] pub mod client_auth; +mod jwt_token; pub mod login; #[cfg(feature = "internal")] pub mod password; pub mod renew; +pub use jwt_token::JWTToken; #[cfg(feature = "internal")] mod register; diff --git a/crates/bitwarden/src/util.rs b/crates/bitwarden/src/util.rs index fc9f30447..b6c8465ec 100644 --- a/crates/bitwarden/src/util.rs +++ b/crates/bitwarden/src/util.rs @@ -3,11 +3,8 @@ use std::num::NonZeroU32; use base64::{ alphabet, engine::{DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig}, - Engine, }; -use crate::error::Result; - pub fn default_pbkdf2_iterations() -> NonZeroU32 { NonZeroU32::new(600_000).unwrap() } @@ -24,14 +21,6 @@ pub fn default_argon2_parallelism() -> NonZeroU32 { NonZeroU32::new(4).unwrap() } -#[derive(serde::Deserialize)] -pub struct JWTToken { - pub sub: String, - pub email: Option, - pub organization: Option, - pub scope: Vec, -} - const BASE64_ENGINE_CONFIG: GeneralPurposeConfig = GeneralPurposeConfig::new() .with_encode_padding(true) .with_decode_padding_mode(DecodePaddingMode::Indifferent); @@ -39,48 +28,6 @@ const BASE64_ENGINE_CONFIG: GeneralPurposeConfig = GeneralPurposeConfig::new() pub const BASE64_ENGINE: GeneralPurpose = GeneralPurpose::new(&alphabet::STANDARD, BASE64_ENGINE_CONFIG); -pub fn decode_token(token: &str) -> Result { - let split = token.split('.').collect::>(); - if split.len() != 3 { - return Err(crate::error::Error::Internal( - "JWT token has an invalid number of parts", - )); - } - let decoded = BASE64_ENGINE.decode(split[1])?; - Ok(serde_json::from_slice(&decoded)?) -} - -#[cfg(test)] -mod tests { - #[test] - fn can_decode_jwt() { - let jwt = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjMwMURENkE1MEU4NEUxRDA5MUM4MUQzQjAwQkY5MDEwQz\ - g1REJEOUFSUzI1NiIsInR5cCI6ImF0K2p3dCIsIng1dCI6Ik1CM1dwUTZFNGRDUnlCMDdBTC1RRU1oZHZabyJ9.eyJu\ - YmYiOjE2NzUxMDM1NzcsImV4cCI6MTY3NTEwNzE3NywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdCIsImNsaWVudF9pZCI\ - 6IndlYiIsInN1YiI6ImUyNWQzN2YzLWI2MDMtNDBkZS04NGJhLWFmOTYwMTJmNWE0MiIsImF1dGhfdGltZSI6MTY3NT\ - EwMzU0OSwiaWRwIjoiYml0d2FyZGVuIiwicHJlbWl1bSI6ZmFsc2UsImVtYWlsIjoidGVzdEBiaXR3YXJkZW4uY29tI\ - iwiZW1haWxfdmVyaWZpZWQiOnRydWUsInNzdGFtcCI6IkUzNElDWVhRUFRDS01EVldBREZDNktHNDJCQldJRDdJIiwi\ - bmFtZSI6IlRlc3QiLCJvcmdvd25lciI6ImY0ZTQ0YTdmLTExOTAtNDMyYS05ZDRhLWFmOTYwMTMxMjdjYiIsImRldml\ - jZSI6Ijg5Mjg5M2FiLWRkNDMtNDUwYS04NGI1LWFhOWM1YjdiYjJkOCIsImp0aSI6IkEzMkVFNjY5NDdEQzlDNUE2MT\ - IwRURBRTIwNzc5OUJFIiwiaWF0IjoxNjc1MTAzNTc3LCJzY29wZSI6WyJhcGkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhb\ - XIiOlsiQXBwbGljYXRpb24iXX0.AyDkKvjmyaSPQViQSa2sGTKIkDGrUAtDmwpE57K4DDWT0QvwDe7FMktmwiF4LH36\ - wx_FnpH21VI1pzwJeTHXtaz3niANJtQZjzGFsNAna_95vrsxZC2YizgGlt6mX4YIGmAw9DiYrmaN0BvQOEm_caV_u6f\ - a30iz9Kvjxf7cpzeZvPEysxGpB3k3TRYTkFUdV43HiXdhXMBhyyOpFU6Fk6yA41y7-8bGYc5mYGknWktmPD9Yx-1xKL\ - ftFja1SnCoLPWvDeK60lqWZQiT4tZHCYJ7m0bBNCccYHc2Kk2Bo5-UoyDxazPwsqMxeNfjlaUuj3o5N_uQ-4n_gVbeA\ - qWV2wrel5UhYjWnczMSLBtt9p0W35kkBPt3ZAnRWMtQMPNH04p-_L6cG-Xu6lDksBTwaavcmtnCKG8V91826EiQ8MrF\ - wGWQRZV6tPKTDAYCgSAZGBY3QDmPGT5BeFcg5Ag_nYYIIifKP-kv10v_N-TOcT3NeGBOUlAZ-9m7iT7Rk3vC--SDZdA\ - U5turoBFiiPL2XXfAjM7P0r7J91gfXc0FaD6I2jDxOmym5h7Yn5phLsbC2NlIXkZp54dKHICenPl4ve6ndDIJacVeS5\ - f3LEddAPV8cAFza4DjA8pZJLFrMyRvMXcL_PjKF8qPVzqVWh03lfJ4clOIxR2gOuWIc902Y5E"; - - let token = super::decode_token(jwt).unwrap(); - assert_eq!(token.sub, "e25d37f3-b603-40de-84ba-af96012f5a42"); - assert_eq!(token.email.as_deref(), Some("test@bitwarden.com")); - assert_eq!(token.organization.as_deref(), None); - assert_eq!(token.scope[0], "api"); - assert_eq!(token.scope[1], "offline_access"); - } -} - #[cfg(test)] pub async fn start_mock(mocks: Vec) -> (wiremock::MockServer, crate::Client) { let server = wiremock::MockServer::start().await; From 1338396f4febd022162c6f0a06b2fc6dab76848e Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 2 Nov 2023 17:56:01 +0100 Subject: [PATCH 12/30] Begin documenting the crypto module (#318) --- Cargo.lock | 9 +++++ crates/bitwarden/src/crypto/aes_ops.rs | 38 ++++++++++++++++++- crates/bitwarden/src/crypto/enc_string.rs | 43 +++++++++++++++++++++- crates/bitwarden/src/crypto/encryptable.rs | 2 + crates/bitwarden/src/crypto/fingerprint.rs | 6 +++ 5 files changed, 96 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4bf4f9df..9672d26e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3813,6 +3813,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-core" version = "0.51.1" diff --git a/crates/bitwarden/src/crypto/aes_ops.rs b/crates/bitwarden/src/crypto/aes_ops.rs index 34d4021e8..87cb96029 100644 --- a/crates/bitwarden/src/crypto/aes_ops.rs +++ b/crates/bitwarden/src/crypto/aes_ops.rs @@ -1,3 +1,13 @@ +//! # AES operations +//! +//! Contains low level AES operations used by the rest of the library. +//! +//! **Warning**: Consider carefully if you have to use these functions directly, as generally we +//! expose higher level functions that are easier to use and more secure. +//! +//! In most cases you should use the [EncString] with [KeyEncryptable][super::KeyEncryptable] & +//! [KeyDecryptable][super::KeyDecryptable] instead. + use aes::cipher::{ block_padding::Pkcs7, generic_array::GenericArray, typenum::U32, BlockDecryptMut, BlockEncryptMut, KeyIvInit, @@ -10,6 +20,9 @@ use crate::{ error::{CryptoError, Result}, }; +/// Decrypt using AES-256 in CBC mode. +/// +/// Behaves similar to [decrypt_aes256_hmac], but does not validate the MAC. pub fn decrypt_aes256(iv: &[u8; 16], data: Vec, key: GenericArray) -> Result> { // Decrypt data let iv = GenericArray::from_slice(iv); @@ -18,13 +31,16 @@ pub fn decrypt_aes256(iv: &[u8; 16], data: Vec, key: GenericArray) .decrypt_padded_mut::(&mut data) .map_err(|_| CryptoError::KeyDecrypt)?; - //Data is decrypted in place and returns a subslice of the original Vec, to avoid cloning it, we truncate to the subslice length + // Data is decrypted in place and returns a subslice of the original Vec, to avoid cloning it, we truncate to the subslice length let decrypted_len = decrypted_key_slice.len(); data.truncate(decrypted_len); Ok(data) } +/// Decrypt using AES-256 in CBC mode with MAC. +/// +/// Behaves similar to [decrypt_aes256], but also validates the MAC. pub fn decrypt_aes256_hmac( iv: &[u8; 16], mac: &[u8; 32], @@ -39,12 +55,26 @@ pub fn decrypt_aes256_hmac( decrypt_aes256(iv, data, key) } +/// Encrypt using AES-256 in CBC mode. +/// +/// Behaves similar to [encrypt_aes256_hmac], but does't generate a MAC. +/// +/// ## Returns +/// +/// A AesCbc256_B64 EncString pub fn encrypt_aes256(data_dec: &[u8], key: GenericArray) -> Result { let (iv, data) = encrypt_aes256_internal(data_dec, key); Ok(EncString::AesCbc256_B64 { iv, data }) } +/// Encrypt using AES-256 in CBC mode with MAC. +/// +/// Behaves similar to [encrypt_aes256], but also generate a MAC. +/// +/// ## Returns +/// +/// A AesCbc256_HmacSha256_B64 EncString pub fn encrypt_aes256_hmac( data_dec: &[u8], mac_key: GenericArray, @@ -56,6 +86,11 @@ pub fn encrypt_aes256_hmac( Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data }) } +/// Encrypt using AES-256 in CBC mode. +/// +/// Used internally by: +/// - [encrypt_aes256] +/// - [encrypt_aes256_hmac] fn encrypt_aes256_internal(data_dec: &[u8], key: GenericArray) -> ([u8; 16], Vec) { let mut iv = [0u8; 16]; rand::thread_rng().fill_bytes(&mut iv); @@ -65,6 +100,7 @@ fn encrypt_aes256_internal(data_dec: &[u8], key: GenericArray) -> ([u8; (iv, data) } +/// Validate a MAC using HMAC-SHA256. fn validate_mac(mac_key: &[u8], iv: &[u8], data: &[u8]) -> Result<[u8; 32]> { let mut hmac = PbkdfSha256Hmac::new_from_slice(mac_key).expect("HMAC can take key of any size"); hmac.update(iv); diff --git a/crates/bitwarden/src/crypto/enc_string.rs b/crates/bitwarden/src/crypto/enc_string.rs index 976065e60..ac7f3fc6b 100644 --- a/crates/bitwarden/src/crypto/enc_string.rs +++ b/crates/bitwarden/src/crypto/enc_string.rs @@ -11,6 +11,45 @@ use crate::{ use super::{KeyDecryptable, KeyEncryptable, LocateKey}; +/// # Encrypted string primitive +/// +/// [EncString] is a Bitwarden specific primitive that represents an encrypted string. They are +/// are used together with the [KeyDecryptable] and [KeyEncryptable] traits to encrypt and decrypt +/// data using [SymmetricCryptoKey]s. +/// +/// The flexibility of the [EncString] type allows for different encryption algorithms to be used +/// which is represented by the different variants of the enum. +/// +/// ## Note +/// +/// We are currently in the progress of splitting the [EncString] into distinct AES and RSA +/// variants. To provide better control of which encryption algorithm is expected. +/// +/// For backwards compatibility we will rarely if ever be able to remove support for decrypting old +/// variants, but we should be opinionated in which variants are used for encrypting. +/// +/// ## Variants +/// - [AesCbc256_B64](EncString::AesCbc256_B64) +/// - [AesCbc128_HmacSha256_B64](EncString::AesCbc128_HmacSha256_B64) +/// - [AesCbc256_HmacSha256_B64](EncString::AesCbc256_HmacSha256_B64) +/// - [Rsa2048_OaepSha256_B64](EncString::Rsa2048_OaepSha256_B64) +/// - [Rsa2048_OaepSha1_B64](EncString::Rsa2048_OaepSha1_B64) +/// +/// ## Serialization +/// +/// [EncString] implements [Display] and [FromStr] to allow for easy serialization and uses a +/// custom scheme to represent the different variants. +/// +/// The scheme is one of the following schemes: +/// - `[type].[iv]|[data]` +/// - `[type].[iv]|[data]|[mac]` +/// - `[type].[data]` +/// +/// Where: +/// - `[type]`: is a digit number representing the variant. +/// - `[iv]`: (optional) is the initialization vector used for encryption. +/// - `[data]`: is the encrypted data. +/// - `[mac]`: (optional) is the MAC used to validate the integrity of the data. #[derive(Clone)] #[allow(unused, non_camel_case_types)] pub enum EncString { @@ -40,13 +79,14 @@ pub enum EncString { Rsa2048_OaepSha1_HmacSha256_B64 { data: Vec }, } -// We manually implement these to make sure we don't print any sensitive data +/// To avoid printing sensitive information, [EncString] debug prints to `EncString`. impl std::fmt::Debug for EncString { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("EncString").finish() } } +/// Deserializes an [EncString] from a string. impl FromStr for EncString { type Err = Error; @@ -291,6 +331,7 @@ impl serde::Serialize for EncString { } impl EncString { + /// The numerical representation of the encryption type of the [EncString]. const fn enc_type(&self) -> u8 { match self { EncString::AesCbc256_B64 { .. } => 0, diff --git a/crates/bitwarden/src/crypto/encryptable.rs b/crates/bitwarden/src/crypto/encryptable.rs index 10dbfaac6..f1bc78f15 100644 --- a/crates/bitwarden/src/crypto/encryptable.rs +++ b/crates/bitwarden/src/crypto/encryptable.rs @@ -19,10 +19,12 @@ pub trait LocateKey { } } +/// Deprecated: please use LocateKey and KeyDecryptable instead pub trait Encryptable { fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result; } +/// Deprecated: please use LocateKey and KeyDecryptable instead pub trait Decryptable { fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result; } diff --git a/crates/bitwarden/src/crypto/fingerprint.rs b/crates/bitwarden/src/crypto/fingerprint.rs index 9473a2cda..ddcf89d40 100644 --- a/crates/bitwarden/src/crypto/fingerprint.rs +++ b/crates/bitwarden/src/crypto/fingerprint.rs @@ -7,6 +7,11 @@ use crate::{ wordlist::EFF_LONG_WORD_LIST, }; +/// Computes a fingerprint of the given `fingerprint_material` using the given `public_key`. +/// +/// This is commonly used for account fingerprints. With the following arguments: +/// - `fingerprint_material`: user's id. +/// - `public_key`: user's public key. pub(crate) fn fingerprint(fingerprint_material: &str, public_key: &[u8]) -> Result { let mut h = sha2::Sha256::new(); h.update(public_key); @@ -22,6 +27,7 @@ pub(crate) fn fingerprint(fingerprint_material: &str, public_key: &[u8]) -> Resu Ok(hash_word(user_fingerprint).unwrap()) } +/// Derive a 5 word phrase from a 32 byte hash. fn hash_word(hash: [u8; 32]) -> Result { let minimum_entropy = 64; From 66480f31a922ad0bb20d71d32ef6849810bfabca Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Nov 2023 13:07:39 -0400 Subject: [PATCH 13/30] Update actions/setup-node action to v4 (#311) --- .github/workflows/build-napi.yml | 2 +- .github/workflows/generate_schemas.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/release-napi.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index 45fab6703..16f87a177 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -54,7 +54,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: node-version: 18 cache: "npm" diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index cac5bc2b8..5f5742da0 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -21,7 +21,7 @@ jobs: toolchain: stable - name: Set up Node - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: cache: "npm" cache-dependency-path: "package-lock.json" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a18e5064a..cb1fb2b67 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -31,7 +31,7 @@ jobs: run: cargo fmt --check - name: Set up Node - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: cache: "npm" cache-dependency-path: "package-lock.json" diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index ee0407587..1cee4a47e 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -93,7 +93,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: node-version: 18 cache: "npm" From 0dd1d95ee1329221e6f95f00e799e569cbaae2ff Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Nov 2023 11:07:53 -0600 Subject: [PATCH 14/30] Update bitwarden/gh-actions digest to ba6a775 (#307) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | bitwarden/gh-actions | action | digest | `c970b0f` -> `ba6a775` | --- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/publish-rust-crates.yml | 2 +- .github/workflows/release-cli.yml | 8 ++++---- .github/workflows/release-napi.yml | 12 ++++++------ .github/workflows/version-bump.yml | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index 1c5484a5c..39926d18b 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -109,7 +109,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d with: keyvault: "bitwarden-ci" secrets: "cratesio-api-token" diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 3651e14bc..bf348a291 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -58,7 +58,7 @@ jobs: - name: Download all Release artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d with: workflow: build-cli.yml path: packages @@ -67,7 +67,7 @@ jobs: - name: Dry Run - Download all artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d with: workflow: build-cli.yml path: packages @@ -75,7 +75,7 @@ jobs: branch: master - name: Get checksum files - uses: bitwarden/gh-actions/get-checksum@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/get-checksum@ba6a77541fa0732735408d10f3ca1e122221201d with: packages_dir: "packages" file_path: "packages/bws-sha256-checksums-${{ steps.version.outputs.version }}.txt" @@ -134,7 +134,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d with: keyvault: "bitwarden-ci" secrets: "cratesio-api-token" diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index 1cee4a47e..ec88803a2 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -47,7 +47,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/release-version-check@ba6a77541fa0732735408d10f3ca1e122221201d with: release-type: ${{ github.event.inputs.release_type }} project-type: ts @@ -101,7 +101,7 @@ jobs: - name: Download schemas if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d with: workflow: build-napi.yml artifacts: schemas.ts @@ -111,7 +111,7 @@ jobs: - name: Dry Run - Download schemas if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d with: workflow: build-napi.yml artifacts: schemas.ts @@ -132,14 +132,14 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d with: keyvault: "bitwarden-ci" secrets: "npm-api-key" - name: Download artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d with: workflow: build-napi.yml path: ${{ github.workspace }}/crates/bitwarden-napi/artifacts @@ -148,7 +148,7 @@ jobs: - name: Dry Run - Download artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d with: workflow: build-napi.yml path: ${{ github.workspace }}/crates/bitwarden-napi/artifacts diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 29ee28f80..e875fc663 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -49,7 +49,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d with: keyvault: "bitwarden-ci" secrets: "github-gpg-private-key, github-gpg-private-key-passphrase" From 13a195cd336bb757c7860f130c6ca7a89337b386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Fri, 3 Nov 2023 11:06:14 +0100 Subject: [PATCH 15/30] Remove encrypt from EncryptionSettings (#314) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective After #297, there were some places in the secrets manager parts of the code that used EncryptionSettings to encrypt directly, instead of dealing with the Encryptable/KeyEncryptable trait. This PR removes those uses so that all encryption opearations have to go through Encryptable/KeyEncryptable. --- .../src/client/encryption_settings.rs | 18 ++++++------------ .../src/secrets_manager/projects/create.rs | 15 ++++++++++----- .../src/secrets_manager/projects/update.rs | 15 ++++++++++----- .../src/secrets_manager/secrets/create.rs | 19 ++++++++++++------- .../src/secrets_manager/secrets/update.rs | 19 ++++++++++++------- 5 files changed, 50 insertions(+), 36 deletions(-) diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index e6cf3e145..da5398a12 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -4,14 +4,15 @@ use rsa::RsaPrivateKey; use uuid::Uuid; #[cfg(feature = "internal")] use { - crate::{client::UserLoginMethod, crypto::KeyDecryptable}, + crate::{ + client::UserLoginMethod, + crypto::{EncString, KeyDecryptable}, + error::{CryptoError, Result}, + }, rsa::{pkcs8::DecodePrivateKey, Oaep}, }; -use crate::{ - crypto::{encrypt_aes256_hmac, EncString, SymmetricCryptoKey}, - error::{CryptoError, Result}, -}; +use crate::crypto::SymmetricCryptoKey; pub struct EncryptionSettings { user_key: SymmetricCryptoKey, @@ -109,11 +110,4 @@ impl EncryptionSettings { None => Some(&self.user_key), } } - - pub(crate) fn encrypt(&self, data: &[u8], org_id: &Option) -> Result { - let key = self.get_key(org_id).ok_or(CryptoError::NoKeyForOrg)?; - - let dec = encrypt_aes256_hmac(data, key.mac_key.ok_or(CryptoError::InvalidMac)?, key.key)?; - Ok(dec) - } } diff --git a/crates/bitwarden/src/secrets_manager/projects/create.rs b/crates/bitwarden/src/secrets_manager/projects/create.rs index 3ba6ecd36..996a3463e 100644 --- a/crates/bitwarden/src/secrets_manager/projects/create.rs +++ b/crates/bitwarden/src/secrets_manager/projects/create.rs @@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::ProjectResponse; -use crate::{client::Client, error::Result}; +use crate::{ + client::Client, + crypto::KeyEncryptable, + error::{Error, Result}, +}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -19,12 +23,13 @@ pub(crate) async fn create_project( client: &mut Client, input: &ProjectCreateRequest, ) -> Result { - let enc = client.get_encryption_settings()?; - - let org_id = Some(input.organization_id); + let key = client + .get_encryption_settings()? + .get_key(&Some(input.organization_id)) + .ok_or(Error::VaultLocked)?; let project = Some(ProjectCreateRequestModel { - name: enc.encrypt(input.name.as_bytes(), &org_id)?.to_string(), + name: input.name.clone().encrypt_with_key(key)?.to_string(), }); let config = client.get_api_configurations().await; diff --git a/crates/bitwarden/src/secrets_manager/projects/update.rs b/crates/bitwarden/src/secrets_manager/projects/update.rs index b0a040c96..6a0479d88 100644 --- a/crates/bitwarden/src/secrets_manager/projects/update.rs +++ b/crates/bitwarden/src/secrets_manager/projects/update.rs @@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::ProjectResponse; -use crate::{client::Client, error::Result}; +use crate::{ + client::Client, + crypto::KeyEncryptable, + error::{Error, Result}, +}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -21,12 +25,13 @@ pub(crate) async fn update_project( client: &mut Client, input: &ProjectPutRequest, ) -> Result { - let enc = client.get_encryption_settings()?; - - let org_id = Some(input.organization_id); + let key = client + .get_encryption_settings()? + .get_key(&Some(input.organization_id)) + .ok_or(Error::VaultLocked)?; let project = Some(ProjectUpdateRequestModel { - name: enc.encrypt(input.name.as_bytes(), &org_id)?.to_string(), + name: input.name.clone().encrypt_with_key(key)?.to_string(), }); let config = client.get_api_configurations().await; diff --git a/crates/bitwarden/src/secrets_manager/secrets/create.rs b/crates/bitwarden/src/secrets_manager/secrets/create.rs index ddec3abd4..a1bb81799 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/create.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/create.rs @@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::SecretResponse; -use crate::{error::Result, Client}; +use crate::{ + crypto::KeyEncryptable, + error::{Error, Result}, + Client, +}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -24,14 +28,15 @@ pub(crate) async fn create_secret( client: &mut Client, input: &SecretCreateRequest, ) -> Result { - let enc = client.get_encryption_settings()?; - - let org_id = Some(input.organization_id); + let key = client + .get_encryption_settings()? + .get_key(&Some(input.organization_id)) + .ok_or(Error::VaultLocked)?; let secret = Some(SecretCreateRequestModel { - key: enc.encrypt(input.key.as_bytes(), &org_id)?.to_string(), - value: enc.encrypt(input.value.as_bytes(), &org_id)?.to_string(), - note: enc.encrypt(input.note.as_bytes(), &org_id)?.to_string(), + key: input.key.clone().encrypt_with_key(key)?.to_string(), + value: input.value.clone().encrypt_with_key(key)?.to_string(), + note: input.note.clone().encrypt_with_key(key)?.to_string(), project_ids: input.project_ids.clone(), }); diff --git a/crates/bitwarden/src/secrets_manager/secrets/update.rs b/crates/bitwarden/src/secrets_manager/secrets/update.rs index b1a82bad8..970812c5a 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/update.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/update.rs @@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::SecretResponse; -use crate::{client::Client, error::Result}; +use crate::{ + client::Client, + crypto::KeyEncryptable, + error::{Error, Result}, +}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -24,14 +28,15 @@ pub(crate) async fn update_secret( client: &mut Client, input: &SecretPutRequest, ) -> Result { - let enc = client.get_encryption_settings()?; - - let org_id = Some(input.organization_id); + let key = client + .get_encryption_settings()? + .get_key(&Some(input.organization_id)) + .ok_or(Error::VaultLocked)?; let secret = Some(SecretUpdateRequestModel { - key: enc.encrypt(input.key.as_bytes(), &org_id)?.to_string(), - value: enc.encrypt(input.value.as_bytes(), &org_id)?.to_string(), - note: enc.encrypt(input.note.as_bytes(), &org_id)?.to_string(), + key: input.key.clone().encrypt_with_key(key)?.to_string(), + value: input.value.clone().encrypt_with_key(key)?.to_string(), + note: input.note.clone().encrypt_with_key(key)?.to_string(), project_ids: input.project_ids.clone(), }); From 5d9e99730d8a2ff674bc98c782d833cdd0f8aa12 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 3 Nov 2023 15:52:13 +0100 Subject: [PATCH 16/30] Move login methods to auth (#319) --- crates/bitwarden-json/src/client.rs | 8 +- crates/bitwarden/CHANGELOG.md | 5 + crates/bitwarden/README.md | 2 +- crates/bitwarden/src/auth/client_auth.rs | 159 +++++++++++++++++- .../bitwarden/src/auth/login/access_token.rs | 2 +- crates/bitwarden/src/auth/login/api_key.rs | 4 +- crates/bitwarden/src/auth/login/mod.rs | 6 +- crates/bitwarden/src/auth/login/password.rs | 2 +- crates/bitwarden/src/auth/login/two_factor.rs | 2 +- crates/bitwarden/src/auth/mod.rs | 1 - crates/bitwarden/src/client/client.rs | 139 +-------------- crates/bitwarden/src/lib.rs | 2 +- crates/bw/src/auth/login.rs | 16 +- crates/bw/src/auth/mod.rs | 2 +- crates/bw/src/main.rs | 4 +- crates/bws/src/main.rs | 3 +- 16 files changed, 192 insertions(+), 165 deletions(-) diff --git a/crates/bitwarden-json/src/client.rs b/crates/bitwarden-json/src/client.rs index f771a5ce4..416067b66 100644 --- a/crates/bitwarden-json/src/client.rs +++ b/crates/bitwarden-json/src/client.rs @@ -46,13 +46,15 @@ impl Client { match cmd { #[cfg(feature = "internal")] - Command::PasswordLogin(req) => self.0.password_login(&req).await.into_string(), + Command::PasswordLogin(req) => self.0.auth().login_password(&req).await.into_string(), #[cfg(feature = "secrets")] - Command::AccessTokenLogin(req) => self.0.access_token_login(&req).await.into_string(), + Command::AccessTokenLogin(req) => { + self.0.auth().login_access_token(&req).await.into_string() + } #[cfg(feature = "internal")] Command::GetUserApiKey(req) => self.0.get_user_api_key(&req).await.into_string(), #[cfg(feature = "internal")] - Command::ApiKeyLogin(req) => self.0.api_key_login(&req).await.into_string(), + Command::ApiKeyLogin(req) => self.0.auth().login_api_key(&req).await.into_string(), #[cfg(feature = "internal")] Command::Sync(req) => self.0.sync(&req).await.into_string(), #[cfg(feature = "internal")] diff --git a/crates/bitwarden/CHANGELOG.md b/crates/bitwarden/CHANGELOG.md index 5569ebd7b..8bb18ff72 100644 --- a/crates/bitwarden/CHANGELOG.md +++ b/crates/bitwarden/CHANGELOG.md @@ -7,6 +7,11 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Deprecated + +- `client.access_token_login()` is now deprecated and will be removed in a future release. Please + use `client.auth().login_access_token()` instead. (#319) + ## [0.3.1] - 2023-10-13 ### Changed diff --git a/crates/bitwarden/README.md b/crates/bitwarden/README.md index a0708b7e6..67c347583 100644 --- a/crates/bitwarden/README.md +++ b/crates/bitwarden/README.md @@ -42,7 +42,7 @@ async fn test() -> Result<()> { // Before we operate, we need to authenticate with a token let token = AccessTokenLoginRequest { access_token: String::from("") }; - client.access_token_login(&token).await.unwrap(); + client.auth().login_access_token(&token).await.unwrap(); let org_id = SecretIdentifiersRequest { organization_id: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap() }; println!("Stored secrets: {:#?}", client.secrets().list(&org_id).await.unwrap()); diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index 8ffca0a44..aa1615c3b 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -1,14 +1,40 @@ -use super::{ - password::{password_strength, satisfies_policy, MasterPasswordPolicyOptions}, - register::{make_register_keys, register}, - RegisterKeyResponse, RegisterRequest, +#[cfg(feature = "secrets")] +use crate::auth::login::{login_access_token, AccessTokenLoginRequest, AccessTokenLoginResponse}; +use crate::{auth::renew::renew_token, error::Result, Client}; +#[cfg(feature = "internal")] +use crate::{ + auth::{ + login::{ + login_api_key, login_password, send_two_factor_email, ApiKeyLoginRequest, + ApiKeyLoginResponse, PasswordLoginRequest, PasswordLoginResponse, + TwoFactorEmailRequest, + }, + password::{password_strength, satisfies_policy, MasterPasswordPolicyOptions}, + register::{make_register_keys, register}, + RegisterKeyResponse, RegisterRequest, + }, + client::kdf::Kdf, }; -use crate::{client::kdf::Kdf, error::Result, Client}; pub struct ClientAuth<'a> { pub(crate) client: &'a mut crate::Client, } +impl<'a> ClientAuth<'a> { + pub async fn renew_token(&mut self) -> Result<()> { + renew_token(self.client).await + } + + #[cfg(feature = "secrets")] + pub async fn login_access_token( + &mut self, + input: &AccessTokenLoginRequest, + ) -> Result { + login_access_token(self.client, input).await + } +} + +#[cfg(feature = "internal")] impl<'a> ClientAuth<'a> { pub async fn password_strength( &self, @@ -37,10 +63,33 @@ impl<'a> ClientAuth<'a> { make_register_keys(email, password, kdf) } - #[cfg(feature = "internal")] pub async fn register(&mut self, input: &RegisterRequest) -> Result<()> { register(self.client, input).await } + + pub async fn prelogin(&mut self, email: String) -> Result { + use crate::auth::login::request_prelogin; + + request_prelogin(self.client, email).await?.try_into() + } + + pub async fn login_password( + &mut self, + input: &PasswordLoginRequest, + ) -> Result { + login_password(self.client, input).await + } + + pub async fn login_api_key( + &mut self, + input: &ApiKeyLoginRequest, + ) -> Result { + login_api_key(self.client, input).await + } + + pub async fn send_two_factor_email(&mut self, tf: &TwoFactorEmailRequest) -> Result<()> { + send_two_factor_email(self.client, tf).await + } } impl<'a> Client { @@ -48,3 +97,101 @@ impl<'a> Client { ClientAuth { client: self } } } + +#[cfg(test)] +mod tests { + + #[cfg(feature = "secrets")] + #[tokio::test] + async fn test_access_token_login() { + use wiremock::{matchers, Mock, ResponseTemplate}; + + use crate::{auth::login::AccessTokenLoginRequest, secrets_manager::secrets::*}; + + // Create the mock server with the necessary routes for this test + let (_server, mut client) = crate::util::start_mock(vec![ + Mock::given(matchers::path("/identity/connect/token")) + .respond_with(ResponseTemplate::new(200).set_body_json( + serde_json::json!({ + "access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjMwMURENkE1MEU4NEUxRDA5MUM4MUQzQjAwQkY5MDEwQzg1REJEOUFSUzI1NiIsInR5cCI6\ + ImF0K2p3dCIsIng1dCI6Ik1CM1dwUTZFNGRDUnlCMDdBTC1RRU1oZHZabyJ9.eyJuYmYiOjE2NzUxMDM3ODEsImV4cCI6MTY3NTEwNzM4MSwiaXNzIjo\ + iaHR0cDovL2xvY2FsaG9zdCIsImNsaWVudF9pZCI6ImVjMmMxZDQ2LTZhNGItNDc1MS1hMzEwLWFmOTYwMTMxN2YyZCIsInN1YiI6ImQzNDgwNGNhLTR\ + mNmMtNDM5Mi04NmI3LWFmOTYwMTMxNzVkMCIsIm9yZ2FuaXphdGlvbiI6ImY0ZTQ0YTdmLTExOTAtNDMyYS05ZDRhLWFmOTYwMTMxMjdjYiIsImp0aSI\ + 6IjU3QUU0NzQ0MzIwNzk1RThGQkQ4MUIxNDA2RDQyNTQyIiwiaWF0IjoxNjc1MTAzNzgxLCJzY29wZSI6WyJhcGkuc2VjcmV0cyJdfQ.GRKYzqgJZHEE\ + ZHsJkhVZH8zjYhY3hUvM4rhdV3FU10WlCteZdKHrPIadCUh-Oz9DxIAA2HfALLhj1chL4JgwPmZgPcVS2G8gk8XeBmZXowpVWJ11TXS1gYrM9syXbv9j\ + 0JUCdpeshH7e56WnlpVynyUwIum9hmYGZ_XJUfmGtlKLuNjYnawTwLEeR005uEjxq3qI1kti-WFnw8ciL4a6HLNulgiFw1dAvs4c7J0souShMfrnFO3g\ + SOHff5kKD3hBB9ynDBnJQSFYJ7dFWHIjhqs0Vj-9h0yXXCcHvu7dVGpaiNjNPxbh6YeXnY6UWcmHLDtFYsG2BWcNvVD4-VgGxXt3cMhrn7l3fSYuo32Z\ + Yk4Wop73XuxqF2fmfmBdZqGI1BafhENCcZw_bpPSfK2uHipfztrgYnrzwvzedz0rjFKbhDyrjzuRauX5dqVJ4ntPeT9g_I5n71gLxiP7eClyAx5RxdF6\ + He87NwC8i-hLBhugIvLTiDj-Sk9HvMth6zaD0ebxd56wDjq8-CMG_WcgusDqNzKFHqWNDHBXt8MLeTgZAR2rQMIMFZqFgsJlRflbig8YewmNUA9wAU74\ + TfxLY1foO7Xpg49vceB7C-PlvGi1VtX6F2i0tc_67lA5kWXnnKBPBUyspoIrmAUCwfms5nTTqA9xXAojMhRHAos_OdM", + "expires_in":3600, + "token_type":"Bearer", + "scope":"api.secrets", + "encrypted_payload":"2.E9fE8+M/VWMfhhim1KlCbQ==|eLsHR484S/tJbIkM6spnG/HP65tj9A6Tba7kAAvUp+rYuQmGLixiOCfMsqt5OvBctDfvvr/Aes\ + Bu7cZimPLyOEhqEAjn52jF0eaI38XZfeOG2VJl0LOf60Wkfh3ryAMvfvLj3G4ZCNYU8sNgoC2+IQ==|lNApuCQ4Pyakfo/wwuuajWNaEX/2MW8/3rjXB/V7n+k="}) + )), + Mock::given(matchers::path("/api/organizations/f4e44a7f-1190-432a-9d4a-af96013127cb/secrets")) + .respond_with(ResponseTemplate::new(200).set_body_json( + serde_json::json!({ + "secrets":[{ + "id":"15744a66-341a-4c62-af50-af960166b6bc", + "organizationId":"f4e44a7f-1190-432a-9d4a-af96013127cb", + "key":"2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8=", + "creationDate":"2023-01-26T21:46:02.2182556Z", + "revisionDate":"2023-01-26T21:46:02.2182557Z" + }], + "projects":[], + "object":"SecretsWithProjectsList" + }) + )), + Mock::given(matchers::path("/api/secrets/15744a66-341a-4c62-af50-af960166b6bc")) + .respond_with(ResponseTemplate::new(200).set_body_json( + serde_json::json!({ + "id":"15744a66-341a-4c62-af50-af960166b6bc", + "organizationId":"f4e44a7f-1190-432a-9d4a-af96013127cb", + "key":"2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8=", + "value":"2.Gl34n9JYABC7V21qHcBzHg==|c1Ds244pob7i+8+MXe4++w==|Shimz/qKMYZmzSFWdeBzFb9dFz7oF6Uv9oqkws7rEe0=", + "note":"2.Cn9ABJy7+WfR4uUHwdYepg==|+nbJyU/6hSknoa5dcEJEUg==|1DTp/ZbwGO3L3RN+VMsCHz8XDr8egn/M5iSitGGysPA=", + "creationDate":"2023-01-26T21:46:02.2182556Z", + "revisionDate":"2023-01-26T21:46:02.2182557Z", + "object":"secret" + }) + )) + ]).await; + + // Test the login is correct and we store the returned organization ID correctly + let res = client + .auth() + .login_access_token(&AccessTokenLoginRequest { + access_token: "0.ec2c1d46-6a4b-4751-a310-af9601317f2d.C2IgxjjLF7qSshsbwe8JGcbM075YXw:X8vbvA0bduihIDe/qrzIQQ==".into(), + }) + .await + .unwrap(); + assert!(res.authenticated); + let organization_id = client.get_access_token_organization().unwrap(); + assert_eq!( + organization_id.to_string(), + "f4e44a7f-1190-432a-9d4a-af96013127cb" + ); + + // Test that we can retrieve the list of secrets correctly + let mut res = client + .secrets() + .list(&SecretIdentifiersRequest { organization_id }) + .await + .unwrap(); + assert_eq!(res.data.len(), 1); + + // Test that given a secret ID we can get it's data + let res = client + .secrets() + .get(&SecretGetRequest { + id: res.data.remove(0).id, + }) + .await + .unwrap(); + assert_eq!(res.key, "TEST"); + assert_eq!(res.note, "TEST"); + assert_eq!(res.value, "TEST"); + } +} diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index d80bfda84..1ec8c8b34 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -15,7 +15,7 @@ use crate::{ Client, }; -pub(crate) async fn access_token_login( +pub(crate) async fn login_access_token( client: &mut Client, input: &AccessTokenLoginRequest, ) -> Result { diff --git a/crates/bitwarden/src/auth/login/api_key.rs b/crates/bitwarden/src/auth/login/api_key.rs index 8a42396af..db5cbe01d 100644 --- a/crates/bitwarden/src/auth/login/api_key.rs +++ b/crates/bitwarden/src/auth/login/api_key.rs @@ -13,7 +13,7 @@ use crate::{ Client, }; -pub(crate) async fn api_key_login( +pub(crate) async fn login_api_key( client: &mut Client, input: &ApiKeyLoginRequest, ) -> Result { @@ -30,7 +30,7 @@ pub(crate) async fn api_key_login( .email .ok_or(Error::Internal("Access token doesn't contain email"))?; - let kdf = client.prelogin(email.clone()).await?; + let kdf = client.auth().prelogin(email.clone()).await?; client.set_tokens( r.access_token.clone(), diff --git a/crates/bitwarden/src/auth/login/mod.rs b/crates/bitwarden/src/auth/login/mod.rs index 9e1dbb818..4ec9d1b49 100644 --- a/crates/bitwarden/src/auth/login/mod.rs +++ b/crates/bitwarden/src/auth/login/mod.rs @@ -14,7 +14,7 @@ pub mod response; mod password; #[cfg(feature = "internal")] -pub(crate) use password::password_login; +pub(crate) use password::login_password; #[cfg(feature = "internal")] pub use password::PasswordLoginRequest; pub use password::PasswordLoginResponse; @@ -28,14 +28,14 @@ pub use two_factor::{TwoFactorEmailRequest, TwoFactorProvider, TwoFactorRequest} #[cfg(feature = "internal")] mod api_key; #[cfg(feature = "internal")] -pub(crate) use api_key::api_key_login; +pub(crate) use api_key::login_api_key; #[cfg(feature = "internal")] pub use api_key::{ApiKeyLoginRequest, ApiKeyLoginResponse}; #[cfg(feature = "secrets")] mod access_token; #[cfg(feature = "secrets")] -pub(crate) use access_token::access_token_login; +pub(super) use access_token::login_access_token; #[cfg(feature = "secrets")] pub use access_token::{AccessTokenLoginRequest, AccessTokenLoginResponse}; diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index c86f7019f..a320131ea 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -22,7 +22,7 @@ use crate::{ }; #[cfg(feature = "internal")] -pub(crate) async fn password_login( +pub(crate) async fn login_password( client: &mut Client, input: &PasswordLoginRequest, ) -> Result { diff --git a/crates/bitwarden/src/auth/login/two_factor.rs b/crates/bitwarden/src/auth/login/two_factor.rs index 04c411349..d8ede2473 100644 --- a/crates/bitwarden/src/auth/login/two_factor.rs +++ b/crates/bitwarden/src/auth/login/two_factor.rs @@ -20,7 +20,7 @@ pub(crate) async fn send_two_factor_email( input: &TwoFactorEmailRequest, ) -> Result<()> { // TODO: This should be resolved from the client - let kdf = client.prelogin(input.email.clone()).await?; + let kdf = client.auth().prelogin(input.email.clone()).await?; let password_hash = determine_password_hash(&input.email, &kdf, &input.password).await?; diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index 89197d4bc..023f3270b 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -1,5 +1,4 @@ pub(super) mod api; -#[cfg(feature = "internal")] pub mod client_auth; mod jwt_token; pub mod login; diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index b29118fe5..213a12fb2 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -4,13 +4,9 @@ use reqwest::header::{self}; use uuid::Uuid; #[cfg(feature = "secrets")] -use crate::auth::login::{access_token_login, AccessTokenLoginRequest, AccessTokenLoginResponse}; +use crate::auth::login::{AccessTokenLoginRequest, AccessTokenLoginResponse}; #[cfg(feature = "internal")] use crate::{ - auth::login::{ - api_key_login, password_login, send_two_factor_email, ApiKeyLoginRequest, - ApiKeyLoginResponse, PasswordLoginRequest, PasswordLoginResponse, TwoFactorEmailRequest, - }, client::kdf::Kdf, crypto::EncString, platform::{ @@ -19,7 +15,6 @@ use crate::{ }, }; use crate::{ - auth::renew::renew_token, client::{ client_settings::{ClientSettings, DeviceType}, encryption_settings::EncryptionSettings, @@ -133,39 +128,17 @@ impl Client { pub(crate) async fn get_api_configurations(&mut self) -> &ApiConfigurations { // At the moment we ignore the error result from the token renewal, if it fails, // the token will end up expiring and the next operation is going to fail anyway. - self.renew_token().await.ok(); + self.auth().renew_token().await.ok(); &self.__api_configurations } - #[cfg(feature = "internal")] - pub async fn prelogin(&mut self, email: String) -> Result { - use crate::auth::login::request_prelogin; - - request_prelogin(self, email).await?.try_into() - } - - #[cfg(feature = "internal")] - pub async fn password_login( - &mut self, - input: &PasswordLoginRequest, - ) -> Result { - password_login(self, input).await - } - - #[cfg(feature = "internal")] - pub async fn api_key_login( - &mut self, - input: &ApiKeyLoginRequest, - ) -> Result { - api_key_login(self, input).await - } - #[cfg(feature = "secrets")] + #[deprecated(note = "Use auth().login_access_token() instead")] pub async fn access_token_login( &mut self, input: &AccessTokenLoginRequest, ) -> Result { - access_token_login(self, input).await + self.auth().login_access_token(input).await } #[cfg(feature = "internal")] @@ -223,10 +196,6 @@ impl Client { self.__api_configurations.api.oauth_access_token = Some(token); } - pub async fn renew_token(&mut self) -> Result<()> { - renew_token(self).await - } - #[cfg(feature = "internal")] pub fn is_authed(&self) -> bool { self.token.is_some() || self.login_method.is_some() @@ -279,104 +248,4 @@ impl Client { pub fn fingerprint(&mut self, input: &FingerprintRequest) -> Result { generate_fingerprint(input) } - - #[cfg(feature = "internal")] - pub async fn send_two_factor_email(&mut self, tf: &TwoFactorEmailRequest) -> Result<()> { - send_two_factor_email(self, tf).await - } -} - -#[cfg(test)] -mod tests { - use wiremock::{matchers, Mock, ResponseTemplate}; - - use crate::{auth::login::AccessTokenLoginRequest, secrets_manager::secrets::*}; - - #[tokio::test] - async fn test_access_token_login() { - // Create the mock server with the necessary routes for this test - let (_server, mut client) = crate::util::start_mock(vec![ - Mock::given(matchers::path("/identity/connect/token")) - .respond_with(ResponseTemplate::new(200).set_body_json( - serde_json::json!({ - "access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjMwMURENkE1MEU4NEUxRDA5MUM4MUQzQjAwQkY5MDEwQzg1REJEOUFSUzI1NiIsInR5cCI6\ - ImF0K2p3dCIsIng1dCI6Ik1CM1dwUTZFNGRDUnlCMDdBTC1RRU1oZHZabyJ9.eyJuYmYiOjE2NzUxMDM3ODEsImV4cCI6MTY3NTEwNzM4MSwiaXNzIjo\ - iaHR0cDovL2xvY2FsaG9zdCIsImNsaWVudF9pZCI6ImVjMmMxZDQ2LTZhNGItNDc1MS1hMzEwLWFmOTYwMTMxN2YyZCIsInN1YiI6ImQzNDgwNGNhLTR\ - mNmMtNDM5Mi04NmI3LWFmOTYwMTMxNzVkMCIsIm9yZ2FuaXphdGlvbiI6ImY0ZTQ0YTdmLTExOTAtNDMyYS05ZDRhLWFmOTYwMTMxMjdjYiIsImp0aSI\ - 6IjU3QUU0NzQ0MzIwNzk1RThGQkQ4MUIxNDA2RDQyNTQyIiwiaWF0IjoxNjc1MTAzNzgxLCJzY29wZSI6WyJhcGkuc2VjcmV0cyJdfQ.GRKYzqgJZHEE\ - ZHsJkhVZH8zjYhY3hUvM4rhdV3FU10WlCteZdKHrPIadCUh-Oz9DxIAA2HfALLhj1chL4JgwPmZgPcVS2G8gk8XeBmZXowpVWJ11TXS1gYrM9syXbv9j\ - 0JUCdpeshH7e56WnlpVynyUwIum9hmYGZ_XJUfmGtlKLuNjYnawTwLEeR005uEjxq3qI1kti-WFnw8ciL4a6HLNulgiFw1dAvs4c7J0souShMfrnFO3g\ - SOHff5kKD3hBB9ynDBnJQSFYJ7dFWHIjhqs0Vj-9h0yXXCcHvu7dVGpaiNjNPxbh6YeXnY6UWcmHLDtFYsG2BWcNvVD4-VgGxXt3cMhrn7l3fSYuo32Z\ - Yk4Wop73XuxqF2fmfmBdZqGI1BafhENCcZw_bpPSfK2uHipfztrgYnrzwvzedz0rjFKbhDyrjzuRauX5dqVJ4ntPeT9g_I5n71gLxiP7eClyAx5RxdF6\ - He87NwC8i-hLBhugIvLTiDj-Sk9HvMth6zaD0ebxd56wDjq8-CMG_WcgusDqNzKFHqWNDHBXt8MLeTgZAR2rQMIMFZqFgsJlRflbig8YewmNUA9wAU74\ - TfxLY1foO7Xpg49vceB7C-PlvGi1VtX6F2i0tc_67lA5kWXnnKBPBUyspoIrmAUCwfms5nTTqA9xXAojMhRHAos_OdM", - "expires_in":3600, - "token_type":"Bearer", - "scope":"api.secrets", - "encrypted_payload":"2.E9fE8+M/VWMfhhim1KlCbQ==|eLsHR484S/tJbIkM6spnG/HP65tj9A6Tba7kAAvUp+rYuQmGLixiOCfMsqt5OvBctDfvvr/Aes\ - Bu7cZimPLyOEhqEAjn52jF0eaI38XZfeOG2VJl0LOf60Wkfh3ryAMvfvLj3G4ZCNYU8sNgoC2+IQ==|lNApuCQ4Pyakfo/wwuuajWNaEX/2MW8/3rjXB/V7n+k="}) - )), - Mock::given(matchers::path("/api/organizations/f4e44a7f-1190-432a-9d4a-af96013127cb/secrets")) - .respond_with(ResponseTemplate::new(200).set_body_json( - serde_json::json!({ - "secrets":[{ - "id":"15744a66-341a-4c62-af50-af960166b6bc", - "organizationId":"f4e44a7f-1190-432a-9d4a-af96013127cb", - "key":"2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8=", - "creationDate":"2023-01-26T21:46:02.2182556Z", - "revisionDate":"2023-01-26T21:46:02.2182557Z" - }], - "projects":[], - "object":"SecretsWithProjectsList" - }) - )), - Mock::given(matchers::path("/api/secrets/15744a66-341a-4c62-af50-af960166b6bc")) - .respond_with(ResponseTemplate::new(200).set_body_json( - serde_json::json!({ - "id":"15744a66-341a-4c62-af50-af960166b6bc", - "organizationId":"f4e44a7f-1190-432a-9d4a-af96013127cb", - "key":"2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8=", - "value":"2.Gl34n9JYABC7V21qHcBzHg==|c1Ds244pob7i+8+MXe4++w==|Shimz/qKMYZmzSFWdeBzFb9dFz7oF6Uv9oqkws7rEe0=", - "note":"2.Cn9ABJy7+WfR4uUHwdYepg==|+nbJyU/6hSknoa5dcEJEUg==|1DTp/ZbwGO3L3RN+VMsCHz8XDr8egn/M5iSitGGysPA=", - "creationDate":"2023-01-26T21:46:02.2182556Z", - "revisionDate":"2023-01-26T21:46:02.2182557Z", - "object":"secret" - }) - )) - ]).await; - - // Test the login is correct and we store the returned organization ID correctly - let res = client - .access_token_login(&AccessTokenLoginRequest { - access_token: "0.ec2c1d46-6a4b-4751-a310-af9601317f2d.C2IgxjjLF7qSshsbwe8JGcbM075YXw:X8vbvA0bduihIDe/qrzIQQ==".into(), - }) - .await - .unwrap(); - assert!(res.authenticated); - let organization_id = client.get_access_token_organization().unwrap(); - assert_eq!( - organization_id.to_string(), - "f4e44a7f-1190-432a-9d4a-af96013127cb" - ); - - // Test that we can retrieve the list of secrets correctly - let mut res = client - .secrets() - .list(&SecretIdentifiersRequest { organization_id }) - .await - .unwrap(); - assert_eq!(res.data.len(), 1); - - // Test that given a secret ID we can get it's data - let res = client - .secrets() - .get(&SecretGetRequest { - id: res.data.remove(0).id, - }) - .await - .unwrap(); - assert_eq!(res.key, "TEST"); - assert_eq!(res.note, "TEST"); - assert_eq!(res.value, "TEST"); - } } diff --git a/crates/bitwarden/src/lib.rs b/crates/bitwarden/src/lib.rs index a61857992..20e36d237 100644 --- a/crates/bitwarden/src/lib.rs +++ b/crates/bitwarden/src/lib.rs @@ -39,7 +39,7 @@ //! //! // Before we operate, we need to authenticate with a token //! let token = AccessTokenLoginRequest { access_token: String::from("") }; -//! client.access_token_login(&token).await.unwrap(); +//! client.auth().login_access_token(&token).await.unwrap(); //! //! let org_id = SecretIdentifiersRequest { organization_id: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap() }; //! println!("Stored secrets: {:#?}", client.secrets().list(&org_id).await.unwrap()); diff --git a/crates/bw/src/auth/login.rs b/crates/bw/src/auth/login.rs index 1c169817f..1fcd15414 100644 --- a/crates/bw/src/auth/login.rs +++ b/crates/bw/src/auth/login.rs @@ -10,15 +10,16 @@ use color_eyre::eyre::{bail, Result}; use inquire::{Password, Text}; use log::{debug, error, info}; -pub(crate) async fn password_login(mut client: Client, email: Option) -> Result<()> { +pub(crate) async fn login_password(mut client: Client, email: Option) -> Result<()> { let email = text_prompt_when_none("Email", email)?; let password = Password::new("Password").without_confirmation().prompt()?; - let kdf = client.prelogin(email.clone()).await?; + let kdf = client.auth().prelogin(email.clone()).await?; let result = client - .password_login(&PasswordLoginRequest { + .auth() + .login_password(&PasswordLoginRequest { email: email.clone(), password: password.clone(), two_factor: None, @@ -45,6 +46,7 @@ pub(crate) async fn password_login(mut client: Client, email: Option) -> } else if let Some(tf) = two_factor.email { // Send token client + .auth() .send_two_factor_email(&TwoFactorEmailRequest { email: email.clone(), password: password.clone(), @@ -64,7 +66,8 @@ pub(crate) async fn password_login(mut client: Client, email: Option) -> }; let result = client - .password_login(&PasswordLoginRequest { + .auth() + .login_password(&PasswordLoginRequest { email, password, two_factor, @@ -80,7 +83,7 @@ pub(crate) async fn password_login(mut client: Client, email: Option) -> Ok(()) } -pub(crate) async fn api_key_login( +pub(crate) async fn login_api_key( mut client: Client, client_id: Option, client_secret: Option, @@ -91,7 +94,8 @@ pub(crate) async fn api_key_login( let password = Password::new("Password").without_confirmation().prompt()?; let result = client - .api_key_login(&ApiKeyLoginRequest { + .auth() + .login_api_key(&ApiKeyLoginRequest { client_id, client_secret, password, diff --git a/crates/bw/src/auth/mod.rs b/crates/bw/src/auth/mod.rs index a745a70f0..a4c7e2ed5 100644 --- a/crates/bw/src/auth/mod.rs +++ b/crates/bw/src/auth/mod.rs @@ -1,2 +1,2 @@ mod login; -pub(crate) use login::{api_key_login, password_login}; +pub(crate) use login::{login_api_key, login_password}; diff --git a/crates/bw/src/main.rs b/crates/bw/src/main.rs index 73e64a4aa..609650ab1 100644 --- a/crates/bw/src/main.rs +++ b/crates/bw/src/main.rs @@ -143,12 +143,12 @@ async fn process_commands() -> Result<()> { match args.command { // FIXME: Rust CLI will not support password login! LoginCommands::Password { email } => { - auth::password_login(client, email).await?; + auth::login_password(client, email).await?; } LoginCommands::ApiKey { client_id, client_secret, - } => auth::api_key_login(client, client_id, client_secret).await?, + } => auth::login_api_key(client, client_id, client_secret).await?, } return Ok(()); } diff --git a/crates/bws/src/main.rs b/crates/bws/src/main.rs index c7a910260..6f27a0e4d 100644 --- a/crates/bws/src/main.rs +++ b/crates/bws/src/main.rs @@ -324,7 +324,8 @@ async fn process_commands() -> Result<()> { // Load session or return if no session exists let _ = client - .access_token_login(&AccessTokenLoginRequest { access_token }) + .auth() + .login_access_token(&AccessTokenLoginRequest { access_token }) .await?; let organization_id = match client.get_access_token_organization() { From a19c45293e2557020e70c187f26497abdee298ee Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 3 Nov 2023 16:03:11 +0100 Subject: [PATCH 17/30] Exclude snapshots from the GH artifact cleanup job (#321) --- .github/workflows/delete-old-packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/delete-old-packages.yml b/.github/workflows/delete-old-packages.yml index 517560ede..323a9a0a2 100644 --- a/.github/workflows/delete-old-packages.yml +++ b/.github/workflows/delete-old-packages.yml @@ -22,4 +22,4 @@ jobs: min-versions-to-keep: 25 # Ignore versions only containing version numbers - ignore-versions: '^\\d*\\.\\d*\\.\\d*$' + ignore-versions: '^\\d*\\.\\d*\\.\\d*(-SNAPSHOT)?$' From ab3c4c12312a347e2fcad8875796ad0a60889d08 Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Thu, 9 Nov 2023 10:22:29 -0500 Subject: [PATCH 18/30] All workflows - Update 'master' to 'main' for any actions in the gh-actions repository (#328) --- .github/workflows/publish-rust-crates.yml | 2 +- .github/workflows/release-cli.yml | 8 ++++---- .github/workflows/release-napi.yml | 12 ++++++------ .github/workflows/version-bump.yml | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index 39926d18b..468570cd8 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -109,7 +109,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "cratesio-api-token" diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index bf348a291..4c52529e8 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -58,7 +58,7 @@ jobs: - name: Download all Release artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-cli.yml path: packages @@ -67,7 +67,7 @@ jobs: - name: Dry Run - Download all artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-cli.yml path: packages @@ -75,7 +75,7 @@ jobs: branch: master - name: Get checksum files - uses: bitwarden/gh-actions/get-checksum@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/get-checksum@main with: packages_dir: "packages" file_path: "packages/bws-sha256-checksums-${{ steps.version.outputs.version }}.txt" @@ -134,7 +134,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "cratesio-api-token" diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index ec88803a2..daa450c0b 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -47,7 +47,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/release-version-check@main with: release-type: ${{ github.event.inputs.release_type }} project-type: ts @@ -101,7 +101,7 @@ jobs: - name: Download schemas if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-napi.yml artifacts: schemas.ts @@ -111,7 +111,7 @@ jobs: - name: Dry Run - Download schemas if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-napi.yml artifacts: schemas.ts @@ -132,14 +132,14 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "npm-api-key" - name: Download artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-napi.yml path: ${{ github.workspace }}/crates/bitwarden-napi/artifacts @@ -148,7 +148,7 @@ jobs: - name: Dry Run - Download artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-napi.yml path: ${{ github.workspace }}/crates/bitwarden-napi/artifacts diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index e875fc663..d902c5700 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -49,7 +49,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "github-gpg-private-key, github-gpg-private-key-passphrase" From 5268e78b0f15ae1c40488b3b32b1e443d40abd60 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 13:27:35 +0100 Subject: [PATCH 19/30] Update npm minor (#323) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate logo banner](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [@napi-rs/cli](https://togithub.com/napi-rs/napi-rs) | [`2.16.3` -> `2.16.5`](https://renovatebot.com/diffs/npm/@napi-rs%2fcli/2.16.3/2.16.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@napi-rs%2fcli/2.16.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@napi-rs%2fcli/2.16.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@napi-rs%2fcli/2.16.3/2.16.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@napi-rs%2fcli/2.16.3/2.16.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [prettier](https://prettier.io) ([source](https://togithub.com/prettier/prettier)) | [`3.0.3` -> `3.1.0`](https://renovatebot.com/diffs/npm/prettier/3.0.3/3.1.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/prettier/3.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prettier/3.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prettier/3.0.3/3.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prettier/3.0.3/3.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [quicktype-core](https://togithub.com/quicktype/quicktype) | [`23.0.76` -> `23.0.77`](https://renovatebot.com/diffs/npm/quicktype-core/23.0.76/23.0.77) | [![age](https://developer.mend.io/api/mc/badges/age/npm/quicktype-core/23.0.77?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/quicktype-core/23.0.77?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/quicktype-core/23.0.76/23.0.77?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/quicktype-core/23.0.76/23.0.77?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
napi-rs/napi-rs (@​napi-rs/cli) ### [`v2.16.5`](https://togithub.com/napi-rs/napi-rs/releases/tag/%40napi-rs/cli%402.16.5) [Compare Source](https://togithub.com/napi-rs/napi-rs/compare/@napi-rs/cli@2.16.4...@napi-rs/cli@2.16.5) #### What's Changed - fix(cli): switch name parsing to allow periods in name by [@​RaphaelDarley](https://togithub.com/RaphaelDarley) [https://github.com/napi-rs/napi-rs/pull/1716](https://togithub.com/napi-rs/napi-rs/pull/1716) #### New Contributors - [@​RaphaelDarley](https://togithub.com/RaphaelDarley) made their first contribution in [https://github.com/napi-rs/napi-rs/pull/1716](https://togithub.com/napi-rs/napi-rs/pull/1716) **Full Changelog**: https://github.com/napi-rs/napi-rs/compare/[@​napi-rs/cli](https://togithub.com/napi-rs/cli)[@​2](https://togithub.com/2).16.4...[@​napi-rs/cli](https://togithub.com/napi-rs/cli)[@​2](https://togithub.com/2).16.5 ### [`v2.16.4`](https://togithub.com/napi-rs/napi-rs/releases/tag/%40napi-rs/cli%402.16.4) [Compare Source](https://togithub.com/napi-rs/napi-rs/compare/@napi-rs/cli@2.16.3...@napi-rs/cli@2.16.4) #### What's Changed - chore(cli): update ci template by [@​Brooooooklyn](https://togithub.com/Brooooooklyn) in [https://github.com/napi-rs/napi-rs/pull/1770](https://togithub.com/napi-rs/napi-rs/pull/1770) **Full Changelog**: https://github.com/napi-rs/napi-rs/compare/[@​napi-rs/cli](https://togithub.com/napi-rs/cli)[@​2](https://togithub.com/2).16.3...[@​napi-rs/cli](https://togithub.com/napi-rs/cli)[@​2](https://togithub.com/2).16.4
prettier/prettier (prettier) ### [`v3.1.0`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#310) [Compare Source](https://togithub.com/prettier/prettier/compare/3.0.3...3.1.0) [diff](https://togithub.com/prettier/prettier/compare/3.0.3...3.1.0) 🔗 [Release Notes](https://prettier.io/blog/2023/11/13/3.1.0.html)
quicktype/quicktype (quicktype-core) ### [`v23.0.77`](https://togithub.com/quicktype/quicktype/compare/fb0ee714b89e65f288789ce2f2e3e33b41107405...55dc6a7912715b7db45419958bf89d00637cd4cd) [Compare Source](https://togithub.com/quicktype/quicktype/compare/fb0ee714b89e65f288789ce2f2e3e33b41107405...55dc6a7912715b7db45419958bf89d00637cd4cd)
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bitwarden-napi/package-lock.json | 6 +++--- package-lock.json | 16 ++++++++-------- package.json | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 4a85cb304..65266d1e4 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -55,9 +55,9 @@ } }, "node_modules/@napi-rs/cli": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.16.3.tgz", - "integrity": "sha512-3mLNPlbbOhpbIUKicLrJtIearlHXUuXL3UeueYyRRplpVMNkdn8xCyzY6PcYZi3JXR8bmCOiWgkVmLnrSL7DKw==", + "version": "2.16.5", + "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.16.5.tgz", + "integrity": "sha512-mFEzwrg4IOLngGd2/P6yeqIWgwQNn59Z08n1rndu6kLDq1gg954NH9cM1O9Da0RJuybt46p43lqgSsnAY2mxqA==", "dev": true, "bin": { "napi": "scripts/index.js" diff --git a/package-lock.json b/package-lock.json index 2ee17dd0a..7791b3b69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,8 @@ "devDependencies": { "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", - "prettier": "3.0.3", - "quicktype-core": "23.0.76", + "prettier": "3.1.0", + "quicktype-core": "23.0.77", "rimraf": "5.0.5", "ts-node": "10.9.1", "typescript": "5.2.2" @@ -1470,9 +1470,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -1494,9 +1494,9 @@ } }, "node_modules/quicktype-core": { - "version": "23.0.76", - "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.76.tgz", - "integrity": "sha512-QinZRNovSTQcFuhRKxeHb22eFmyucbG96EPaQDSbz9qvIPxUhs1BZviNc8HAkHWYFqTSET/xZcEoHpm1DeDbRg==", + "version": "23.0.77", + "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.77.tgz", + "integrity": "sha512-QABFgMHVsyW7CAcLGWvIQXgjZ7ehPnebfV/3x9c5HtuJVXgYLrEG/+zyQd1O+OPWpQrhbwU97doJTZRw+acA6A==", "dev": true, "dependencies": { "@glideapps/ts-necessities": "2.1.3", diff --git a/package.json b/package.json index fdeb8fe58..ad38f3a10 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "devDependencies": { "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", - "prettier": "3.0.3", - "quicktype-core": "23.0.76", + "prettier": "3.1.0", + "quicktype-core": "23.0.77", "rimraf": "5.0.5", "ts-node": "10.9.1", "typescript": "5.2.2" From ee33be94e55463b2c0417a8887b7636e01c75eb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 13 Nov 2023 13:48:20 +0100 Subject: [PATCH 20/30] Update uniffi to solve Send conflict (#326) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Update uniffi to solve the conflict between our `Send` and Rust's `Send` --- Cargo.lock | 20 ++++++++++---------- Cargo.toml | 10 +++++----- crates/bitwarden-uniffi/src/vault/sends.rs | 16 ++++++++-------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9672d26e9..184066772 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3451,7 +3451,7 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uniffi" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "camino", @@ -3472,7 +3472,7 @@ dependencies = [ [[package]] name = "uniffi_bindgen" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "askama", @@ -3495,7 +3495,7 @@ dependencies = [ [[package]] name = "uniffi_build" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "camino", @@ -3505,7 +3505,7 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "quote", "syn 2.0.38", @@ -3514,7 +3514,7 @@ dependencies = [ [[package]] name = "uniffi_core" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "bytes", @@ -3529,7 +3529,7 @@ dependencies = [ [[package]] name = "uniffi_macros" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "bincode", "camino", @@ -3547,7 +3547,7 @@ dependencies = [ [[package]] name = "uniffi_meta" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "bytes", @@ -3558,7 +3558,7 @@ dependencies = [ [[package]] name = "uniffi_testing" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "camino", @@ -3570,7 +3570,7 @@ dependencies = [ [[package]] name = "uniffi_udl" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "uniffi_meta", @@ -3777,7 +3777,7 @@ dependencies = [ [[package]] name = "weedle2" version = "4.0.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "nom", ] diff --git a/Cargo.toml b/Cargo.toml index a192c14e5..da8805342 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,8 +24,8 @@ codegen-units = 1 # Using master until 0.25.1 is released to fix https://github.com/mozilla/uniffi-rs/issues/1798 [patch.crates-io] -uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } -uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } -uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } -uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } -uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } +uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } +uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } +uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } +uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } +uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } diff --git a/crates/bitwarden-uniffi/src/vault/sends.rs b/crates/bitwarden-uniffi/src/vault/sends.rs index 696c4a861..6e2f1b879 100644 --- a/crates/bitwarden-uniffi/src/vault/sends.rs +++ b/crates/bitwarden-uniffi/src/vault/sends.rs @@ -1,6 +1,6 @@ use std::{path::Path, sync::Arc}; -use bitwarden::vault::{self, SendListView, SendView}; +use bitwarden::vault::{Send, SendListView, SendView}; use crate::{Client, Result}; @@ -10,12 +10,12 @@ pub struct ClientSends(pub Arc); #[uniffi::export] impl ClientSends { /// Encrypt send - pub async fn encrypt(&self, send: SendView) -> Result { + pub async fn encrypt(&self, send: SendView) -> Result { Ok(self.0 .0.read().await.vault().sends().encrypt(send).await?) } /// Encrypt a send file in memory - pub async fn encrypt_buffer(&self, send: vault::Send, buffer: Vec) -> Result> { + pub async fn encrypt_buffer(&self, send: Send, buffer: Vec) -> Result> { Ok(self .0 .0 @@ -30,7 +30,7 @@ impl ClientSends { /// Encrypt a send file located in the file system pub async fn encrypt_file( &self, - send: vault::Send, + send: Send, decrypted_file_path: String, encrypted_file_path: String, ) -> Result<()> { @@ -50,12 +50,12 @@ impl ClientSends { } /// Decrypt send - pub async fn decrypt(&self, send: vault::Send) -> Result { + pub async fn decrypt(&self, send: Send) -> Result { Ok(self.0 .0.read().await.vault().sends().decrypt(send).await?) } /// Decrypt send list - pub async fn decrypt_list(&self, sends: Vec) -> Result> { + pub async fn decrypt_list(&self, sends: Vec) -> Result> { Ok(self .0 .0 @@ -68,7 +68,7 @@ impl ClientSends { } /// Decrypt a send file in memory - pub async fn decrypt_buffer(&self, send: vault::Send, buffer: Vec) -> Result> { + pub async fn decrypt_buffer(&self, send: Send, buffer: Vec) -> Result> { Ok(self .0 .0 @@ -83,7 +83,7 @@ impl ClientSends { /// Decrypt a send file located in the file system pub async fn decrypt_file( &self, - send: vault::Send, + send: Send, encrypted_file_path: String, decrypted_file_path: String, ) -> Result<()> { From 39891e0adb9049dd5852028d110ff8f2be0b6855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 13 Nov 2023 14:09:14 +0100 Subject: [PATCH 21/30] Update public modules to get correct documentation (#325) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective All the functions in `Client` that return `Client*` were inside private modules, which make them accessible for use, but `cargo doc` will not document them. By making them public, the cargo docs generate the correct documentation. Also made `aes_ops` private as it's not used outside the crypto module anymore. --- crates/bitwarden/src/crypto/aes_ops.rs | 1 + crates/bitwarden/src/crypto/mod.rs | 2 +- crates/bitwarden/src/mobile/mod.rs | 7 +++++-- crates/bitwarden/src/mobile/vault/mod.rs | 7 +++++++ crates/bitwarden/src/secrets_manager/mod.rs | 3 +++ crates/bitwarden/src/tool/exporters/mod.rs | 1 + crates/bitwarden/src/tool/generators/mod.rs | 1 + crates/bitwarden/src/tool/mod.rs | 4 ++-- 8 files changed, 21 insertions(+), 5 deletions(-) diff --git a/crates/bitwarden/src/crypto/aes_ops.rs b/crates/bitwarden/src/crypto/aes_ops.rs index 87cb96029..132718349 100644 --- a/crates/bitwarden/src/crypto/aes_ops.rs +++ b/crates/bitwarden/src/crypto/aes_ops.rs @@ -62,6 +62,7 @@ pub fn decrypt_aes256_hmac( /// ## Returns /// /// A AesCbc256_B64 EncString +#[allow(unused)] pub fn encrypt_aes256(data_dec: &[u8], key: GenericArray) -> Result { let (iv, data) = encrypt_aes256_internal(data_dec, key); diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs index d8a1f0557..b030a5107 100644 --- a/crates/bitwarden/src/crypto/mod.rs +++ b/crates/bitwarden/src/crypto/mod.rs @@ -33,7 +33,7 @@ pub use encryptable::{Decryptable, Encryptable, LocateKey}; mod key_encryptable; pub use key_encryptable::{KeyDecryptable, KeyEncryptable}; mod aes_ops; -pub use aes_ops::{decrypt_aes256, decrypt_aes256_hmac, encrypt_aes256, encrypt_aes256_hmac}; +use aes_ops::{decrypt_aes256_hmac, encrypt_aes256_hmac}; mod symmetric_crypto_key; pub use symmetric_crypto_key::SymmetricCryptoKey; mod shareable_key; diff --git a/crates/bitwarden/src/mobile/mod.rs b/crates/bitwarden/src/mobile/mod.rs index ad2d794af..fe3083aa8 100644 --- a/crates/bitwarden/src/mobile/mod.rs +++ b/crates/bitwarden/src/mobile/mod.rs @@ -3,8 +3,11 @@ pub mod crypto; pub mod kdf; pub mod vault; -pub(crate) mod client_crypto; -pub(crate) mod client_kdf; +mod client_crypto; +mod client_kdf; + +pub use client_crypto::ClientCrypto; +pub use client_kdf::ClientKdf; // Usually we wouldn't want to expose EncStrings in the API or the schemas, // but we need them in the mobile API, so define it here to limit the scope diff --git a/crates/bitwarden/src/mobile/vault/mod.rs b/crates/bitwarden/src/mobile/vault/mod.rs index f22f004ce..97f9556af 100644 --- a/crates/bitwarden/src/mobile/vault/mod.rs +++ b/crates/bitwarden/src/mobile/vault/mod.rs @@ -5,3 +5,10 @@ mod client_password_history; mod client_sends; mod client_totp; mod client_vault; + +pub use client_ciphers::ClientCiphers; +pub use client_collection::ClientCollections; +pub use client_folders::ClientFolders; +pub use client_password_history::ClientPasswordHistory; +pub use client_sends::ClientSends; +pub use client_vault::ClientVault; diff --git a/crates/bitwarden/src/secrets_manager/mod.rs b/crates/bitwarden/src/secrets_manager/mod.rs index 0afbfe38c..27b84121e 100644 --- a/crates/bitwarden/src/secrets_manager/mod.rs +++ b/crates/bitwarden/src/secrets_manager/mod.rs @@ -3,3 +3,6 @@ pub mod secrets; mod client_projects; mod client_secrets; + +pub use client_projects::ClientProjects; +pub use client_secrets::ClientSecrets; diff --git a/crates/bitwarden/src/tool/exporters/mod.rs b/crates/bitwarden/src/tool/exporters/mod.rs index 508aae8fb..1170dbd38 100644 --- a/crates/bitwarden/src/tool/exporters/mod.rs +++ b/crates/bitwarden/src/tool/exporters/mod.rs @@ -6,6 +6,7 @@ use crate::{ }; mod client_exporter; +pub use client_exporter::ClientExporters; #[derive(JsonSchema)] #[cfg_attr(feature = "mobile", derive(uniffi::Enum))] diff --git a/crates/bitwarden/src/tool/generators/mod.rs b/crates/bitwarden/src/tool/generators/mod.rs index bdc0fb260..4d991b765 100644 --- a/crates/bitwarden/src/tool/generators/mod.rs +++ b/crates/bitwarden/src/tool/generators/mod.rs @@ -1,4 +1,5 @@ mod client_generator; mod password; +pub use client_generator::ClientGenerator; pub use password::{PassphraseGeneratorRequest, PasswordGeneratorRequest}; diff --git a/crates/bitwarden/src/tool/mod.rs b/crates/bitwarden/src/tool/mod.rs index 2130a6b0c..212ce4bf7 100644 --- a/crates/bitwarden/src/tool/mod.rs +++ b/crates/bitwarden/src/tool/mod.rs @@ -1,5 +1,5 @@ mod exporters; mod generators; -pub use exporters::ExportFormat; -pub use generators::{PassphraseGeneratorRequest, PasswordGeneratorRequest}; +pub use exporters::{ClientExporters, ExportFormat}; +pub use generators::{ClientGenerator, PassphraseGeneratorRequest, PasswordGeneratorRequest}; From a55c2d7733be6ac49b259950301b4b423f3cb4c2 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Thu, 16 Nov 2023 12:25:30 -0800 Subject: [PATCH 22/30] [BEEEP] SM-1005 - Add env output option (#320) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Type of change - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ## Objective Add an env output option to `bws`. This allows for easier command-line usage in scripts, particularly where a JSON or YAML parser is not desirable or available. Basic usage examples in Bash: - `source <(bws secret get ec9e0489-244e-4b3f-8782-b0a800fe562f -o env)` - `bws secret list -o env > .env` ## Code changes - **`crates/bws/src/render.rs`:** Output secrets in `key="value"` format ## Screenshots ![image](https://github.com/bitwarden/sdk/assets/5676771/72201357-dc4c-471e-b1f0-011297dbb978) ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --------- Co-authored-by: Daniel García --- Cargo.lock | 1 + crates/bws/Cargo.toml | 1 + crates/bws/src/render.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 184066772..6a02ad594 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -539,6 +539,7 @@ dependencies = [ "env_logger", "log", "openssl", + "regex", "serde", "serde_json", "serde_yaml", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 00ec40da7..9ccd5c546 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -37,6 +37,7 @@ thiserror = "1.0.40" tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } toml = "0.8.0" uuid = { version = "^1.3.3", features = ["serde"] } +regex = { version = "1.10.2", features=["std", "perf"], default-features=false } bitwarden = { path = "../bitwarden", version = "0.3.1", features = ["secrets"] } diff --git a/crates/bws/src/render.rs b/crates/bws/src/render.rs index 4f2a32e9a..83c5cd532 100644 --- a/crates/bws/src/render.rs +++ b/crates/bws/src/render.rs @@ -9,6 +9,7 @@ use serde::Serialize; pub(crate) enum Output { JSON, YAML, + Env, Table, TSV, None, @@ -49,6 +50,31 @@ pub(crate) fn serialize_response, const N: usiz let text = serde_yaml::to_string(&data).unwrap(); pretty_print("yaml", &text, color); } + Output::Env => { + let valid_key_regex = regex::Regex::new("^[a-zA-Z_][a-zA-Z0-9_]*$").unwrap(); + + let mut commented_out = false; + let mut text: Vec = data + .get_values() + .into_iter() + .map(|row| { + if valid_key_regex.is_match(&row[1]) { + format!("{}=\"{}\"", row[1], row[2]) + } else { + commented_out = true; + format!("# {}=\"{}\"", row[1], row[2].replace('\n', "\n# ")) + } + }) + .collect(); + + if commented_out { + text.push(String::from( + "\n# one or more secrets have been commented-out due to a problematic key name", + )); + } + + pretty_print("sh", &format!("{}\n", text.join("\n")), color); + } Output::Table => { let mut table = Table::new(); table From c4b041197652a67e52fafc9dbf772f043e5b393f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 10:30:53 +0100 Subject: [PATCH 23/30] Update npm minor (#336) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate logo banner](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [quicktype-core](https://togithub.com/quicktype/quicktype) | [`23.0.77` -> `23.0.79`](https://renovatebot.com/diffs/npm/quicktype-core/23.0.77/23.0.79) | [![age](https://developer.mend.io/api/mc/badges/age/npm/quicktype-core/23.0.79?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/quicktype-core/23.0.79?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/quicktype-core/23.0.77/23.0.79?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/quicktype-core/23.0.77/23.0.79?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [ts-loader](https://togithub.com/TypeStrong/ts-loader) | [`9.5.0` -> `9.5.1`](https://renovatebot.com/diffs/npm/ts-loader/9.5.0/9.5.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/ts-loader/9.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/ts-loader/9.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/ts-loader/9.5.0/9.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/ts-loader/9.5.0/9.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
quicktype/quicktype (quicktype-core) ### [`v23.0.79`](https://togithub.com/quicktype/quicktype/compare/317deefa6a0c8ba0201b9b2b50d00c7e93c41d78...958d199d74b507175d9a49871c5d3770eaaf7873) [Compare Source](https://togithub.com/quicktype/quicktype/compare/317deefa6a0c8ba0201b9b2b50d00c7e93c41d78...958d199d74b507175d9a49871c5d3770eaaf7873) ### [`v23.0.78`](https://togithub.com/quicktype/quicktype/compare/55dc6a7912715b7db45419958bf89d00637cd4cd...317deefa6a0c8ba0201b9b2b50d00c7e93c41d78) [Compare Source](https://togithub.com/quicktype/quicktype/compare/55dc6a7912715b7db45419958bf89d00637cd4cd...317deefa6a0c8ba0201b9b2b50d00c7e93c41d78)
TypeStrong/ts-loader (ts-loader) ### [`v9.5.1`](https://togithub.com/TypeStrong/ts-loader/blob/HEAD/CHANGELOG.md#951) [Compare Source](https://togithub.com/TypeStrong/ts-loader/compare/v9.5.0...v9.5.1) - [fix: inputSourceMap can be null](https://togithub.com/TypeStrong/ts-loader/pull/1639) \[[#​1638](https://togithub.com/TypeStrong/ts-loader/issues/1638)] - thanks [@​johnnyreilly](https://togithub.com/johnnyreilly) and [@​michaeltford](https://togithub.com/michaeltford)
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- languages/js_webassembly/package-lock.json | 8 ++++---- languages/js_webassembly/package.json | 2 +- package-lock.json | 8 ++++---- package.json | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/languages/js_webassembly/package-lock.json b/languages/js_webassembly/package-lock.json index 066f862be..e3e20e9aa 100644 --- a/languages/js_webassembly/package-lock.json +++ b/languages/js_webassembly/package-lock.json @@ -7,7 +7,7 @@ "devDependencies": { "html-webpack-plugin": "5.5.3", "text-encoding": "0.7.0", - "ts-loader": "9.5.0", + "ts-loader": "9.5.1", "wasm-pack": "0.12.1", "webpack": "5.89.0", "webpack-cli": "5.1.4", @@ -3613,9 +3613,9 @@ } }, "node_modules/ts-loader": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.0.tgz", - "integrity": "sha512-LLlB/pkB4q9mW2yLdFMnK3dEHbrBjeZTYguaaIfusyojBgAGf5kF+O6KcWqiGzWqHk0LBsoolrp4VftEURhybg==", + "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", diff --git a/languages/js_webassembly/package.json b/languages/js_webassembly/package.json index 95d7002a5..d5d7342df 100644 --- a/languages/js_webassembly/package.json +++ b/languages/js_webassembly/package.json @@ -6,7 +6,7 @@ "devDependencies": { "html-webpack-plugin": "5.5.3", "text-encoding": "0.7.0", - "ts-loader": "9.5.0", + "ts-loader": "9.5.1", "wasm-pack": "0.12.1", "webpack": "5.89.0", "webpack-cli": "5.1.4", diff --git a/package-lock.json b/package-lock.json index 7791b3b69..ac70b185d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", "prettier": "3.1.0", - "quicktype-core": "23.0.77", + "quicktype-core": "23.0.79", "rimraf": "5.0.5", "ts-node": "10.9.1", "typescript": "5.2.2" @@ -1494,9 +1494,9 @@ } }, "node_modules/quicktype-core": { - "version": "23.0.77", - "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.77.tgz", - "integrity": "sha512-QABFgMHVsyW7CAcLGWvIQXgjZ7ehPnebfV/3x9c5HtuJVXgYLrEG/+zyQd1O+OPWpQrhbwU97doJTZRw+acA6A==", + "version": "23.0.79", + "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.79.tgz", + "integrity": "sha512-Auzy8AhorFt6YGeB53/dzUSINmKKassAyCsr2wpNgG9XoC3i6oUoLuySNUzYIkyCFCGmKdBRBQeyAqPOVteoYw==", "dev": true, "dependencies": { "@glideapps/ts-necessities": "2.1.3", diff --git a/package.json b/package.json index ad38f3a10..97f08c571 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", "prettier": "3.1.0", - "quicktype-core": "23.0.77", + "quicktype-core": "23.0.79", "rimraf": "5.0.5", "ts-node": "10.9.1", "typescript": "5.2.2" From 9fab1fa4ddbdcae7b597bbb674da4e2fd11fd287 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 10:58:19 +0100 Subject: [PATCH 24/30] Update Rust crate itertools to 0.12.0 (#338) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate logo banner](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [itertools](https://togithub.com/rust-itertools/itertools) | dependencies | minor | `0.11.0` -> `0.12.0` | --- ### Release Notes
rust-itertools/itertools (itertools) ### [`v0.12.0`](https://togithub.com/rust-itertools/itertools/blob/HEAD/CHANGELOG.md#0120) [Compare Source](https://togithub.com/rust-itertools/itertools/compare/v0.11.0...v0.12.0) ##### Breaking - Made `take_while_inclusive` consume iterator by value ([#​709](https://togithub.com/rust-itertools/itertools/issues/709)) - Added `Clone` bound to `Unique` ([#​777](https://togithub.com/rust-itertools/itertools/issues/777)) ##### Added - Added `Itertools::try_len` ([#​723](https://togithub.com/rust-itertools/itertools/issues/723)) - Added free function `sort_unstable` ([#​796](https://togithub.com/rust-itertools/itertools/issues/796)) - Added `GroupMap::fold_with` ([#​778](https://togithub.com/rust-itertools/itertools/issues/778), [#​785](https://togithub.com/rust-itertools/itertools/issues/785)) - Added `PeekNth::{peek_mut, peek_nth_mut}` ([#​716](https://togithub.com/rust-itertools/itertools/issues/716)) - Added `PeekNth::{next_if, next_if_eq}` ([#​734](https://togithub.com/rust-itertools/itertools/issues/734)) - Added conversion into `(Option,Option)` to `EitherOrBoth` ([#​713](https://togithub.com/rust-itertools/itertools/issues/713)) - Added conversion from `Either` to `EitherOrBoth` ([#​715](https://togithub.com/rust-itertools/itertools/issues/715)) - Implemented `ExactSizeIterator` for `Tuples` ([#​761](https://togithub.com/rust-itertools/itertools/issues/761)) - Implemented `ExactSizeIterator` for `(Circular)TupleWindows` ([#​752](https://togithub.com/rust-itertools/itertools/issues/752)) - Made `EitherOrBoth` a shorthand for `EitherOrBoth` ([#​719](https://togithub.com/rust-itertools/itertools/issues/719)) ##### Changed - Added missing `#[must_use]` annotations on iterator adaptors ([#​794](https://togithub.com/rust-itertools/itertools/issues/794)) - Made `Combinations` lazy ([#​795](https://togithub.com/rust-itertools/itertools/issues/795)) - Made `Intersperse(With)` lazy ([#​797](https://togithub.com/rust-itertools/itertools/issues/797)) - Made `Permutations` lazy ([#​793](https://togithub.com/rust-itertools/itertools/issues/793)) - Made `Product` lazy ([#​800](https://togithub.com/rust-itertools/itertools/issues/800)) - Made `TupleWindows` lazy ([#​602](https://togithub.com/rust-itertools/itertools/issues/602)) - Specialized `Combinations::{count, size_hint}` ([#​729](https://togithub.com/rust-itertools/itertools/issues/729)) - Specialized `CombinationsWithReplacement::{count, size_hint}` ([#​737](https://togithub.com/rust-itertools/itertools/issues/737)) - Specialized `Powerset::fold` ([#​765](https://togithub.com/rust-itertools/itertools/issues/765)) - Specialized `Powerset::count` ([#​735](https://togithub.com/rust-itertools/itertools/issues/735)) - Specialized `TupleCombinations::{count, size_hint}` ([#​763](https://togithub.com/rust-itertools/itertools/issues/763)) - Specialized `TupleCombinations::fold` ([#​775](https://togithub.com/rust-itertools/itertools/issues/775)) - Specialized `WhileSome::fold` ([#​780](https://togithub.com/rust-itertools/itertools/issues/780)) - Specialized `WithPosition::fold` ([#​772](https://togithub.com/rust-itertools/itertools/issues/772)) - Specialized `ZipLongest::fold` ([#​774](https://togithub.com/rust-itertools/itertools/issues/774)) - Changed `{min, max}_set*` operations require `alloc` feature, instead of `std` ([#​760](https://togithub.com/rust-itertools/itertools/issues/760)) - Improved documentation of `tree_fold1` ([#​787](https://togithub.com/rust-itertools/itertools/issues/787)) - Improved documentation of `permutations` ([#​724](https://togithub.com/rust-itertools/itertools/issues/724)) - Fixed typo in documentation of `multiunzip` ([#​770](https://togithub.com/rust-itertools/itertools/issues/770)) ##### Notable Internal Changes - Improved specialization tests ([#​799](https://togithub.com/rust-itertools/itertools/issues/799), [#​786](https://togithub.com/rust-itertools/itertools/issues/786), [#​782](https://togithub.com/rust-itertools/itertools/issues/782)) - Simplified implementation of `Permutations` ([#​739](https://togithub.com/rust-itertools/itertools/issues/739), [#​748](https://togithub.com/rust-itertools/itertools/issues/748), [#​790](https://togithub.com/rust-itertools/itertools/issues/790)) - Combined `Merge`/`MergeBy`/`MergeJoinBy` implementations ([#​736](https://togithub.com/rust-itertools/itertools/issues/736)) - Simplified `Permutations::size_hint` ([#​739](https://togithub.com/rust-itertools/itertools/issues/739)) - Fix wrapping arithmetic in benchmarks ([#​770](https://togithub.com/rust-itertools/itertools/issues/770)) - Enforced `rustfmt` in CI ([#​751](https://togithub.com/rust-itertools/itertools/issues/751)) - Disallowed compile warnings in CI ([#​720](https://togithub.com/rust-itertools/itertools/issues/720)) - Used `cargo hack` to check MSRV ([#​754](https://togithub.com/rust-itertools/itertools/issues/754))
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/sdk-schemas/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6a02ad594..7ca15b625 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1647,9 +1647,9 @@ checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" [[package]] name = "itertools" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" dependencies = [ "either", ] diff --git a/crates/sdk-schemas/Cargo.toml b/crates/sdk-schemas/Cargo.toml index c6de9eaca..64ce34274 100644 --- a/crates/sdk-schemas/Cargo.toml +++ b/crates/sdk-schemas/Cargo.toml @@ -15,7 +15,7 @@ internal = [ schemars = { version = "0.8.12", features = ["preserve_order"] } serde_json = "1.0.96" anyhow = "1.0.71" -itertools = "0.11.0" +itertools = "0.12.0" bitwarden = { path = "../bitwarden" } bitwarden-json = { path = "../bitwarden-json" } From 8788f184750fef3045d0fc38666ddf82627d34b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 20 Nov 2023 11:03:45 +0100 Subject: [PATCH 25/30] Split initializeCrypto (#329) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Split initializeCrypto into separate user and organization methods, so clients won't need to hold on to the master password until after sync is done to initialize the organization keys. --- crates/bitwarden-uniffi/README.md | 1 + crates/bitwarden-uniffi/src/crypto.rs | 35 +++++++ crates/bitwarden-uniffi/src/docs.rs | 5 +- crates/bitwarden-uniffi/src/lib.rs | 22 +---- .../src/client/encryption_settings.rs | 4 + crates/bitwarden/src/mobile/client_crypto.rs | 13 ++- crates/bitwarden/src/mobile/crypto.rs | 57 +++++++---- crates/bitwarden/tests/register.rs | 16 ++- .../bitwarden/myapplication/MainActivity.kt | 21 ++-- languages/kotlin/doc.md | 99 +++++++++++++++---- languages/swift/iOS/App/ContentView.swift | 14 ++- 11 files changed, 212 insertions(+), 75 deletions(-) create mode 100644 crates/bitwarden-uniffi/src/crypto.rs diff --git a/crates/bitwarden-uniffi/README.md b/crates/bitwarden-uniffi/README.md index 7dff0b291..1be7706bb 100644 --- a/crates/bitwarden-uniffi/README.md +++ b/crates/bitwarden-uniffi/README.md @@ -5,6 +5,7 @@ ```bash cargo +nightly rustdoc -p bitwarden -- -Zunstable-options --output-format json cargo +nightly rustdoc -p bitwarden-uniffi -- -Zunstable-options --output-format json +npm run schemas npx ts-node ./support/docs/docs.ts > languages/kotlin/doc.md ``` diff --git a/crates/bitwarden-uniffi/src/crypto.rs b/crates/bitwarden-uniffi/src/crypto.rs new file mode 100644 index 000000000..1792a5bbc --- /dev/null +++ b/crates/bitwarden-uniffi/src/crypto.rs @@ -0,0 +1,35 @@ +use std::sync::Arc; + +use bitwarden::mobile::crypto::{InitOrgCryptoRequest, InitUserCryptoRequest}; + +use crate::{error::Result, Client}; + +#[derive(uniffi::Object)] +pub struct ClientCrypto(pub(crate) Arc); + +#[uniffi::export] +impl ClientCrypto { + /// Initialization method for the user crypto. Needs to be called before any other crypto operations. + pub async fn initialize_user_crypto(&self, req: InitUserCryptoRequest) -> Result<()> { + Ok(self + .0 + .0 + .write() + .await + .crypto() + .initialize_user_crypto(req) + .await?) + } + + /// Initialization method for the organization crypto. Needs to be called after `initialize_user_crypto` but before any other crypto operations. + pub async fn initialize_org_crypto(&self, req: InitOrgCryptoRequest) -> Result<()> { + Ok(self + .0 + .0 + .write() + .await + .crypto() + .initialize_org_crypto(req) + .await?) + } +} diff --git a/crates/bitwarden-uniffi/src/docs.rs b/crates/bitwarden-uniffi/src/docs.rs index bc47a19c3..45fabb0b7 100644 --- a/crates/bitwarden-uniffi/src/docs.rs +++ b/crates/bitwarden-uniffi/src/docs.rs @@ -1,7 +1,7 @@ use bitwarden::{ auth::password::MasterPasswordPolicyOptions, client::kdf::Kdf, - mobile::crypto::InitCryptoRequest, + mobile::crypto::{InitOrgCryptoRequest, InitUserCryptoRequest}, tool::{ExportFormat, PassphraseGeneratorRequest, PasswordGeneratorRequest}, vault::{ Cipher, CipherView, Collection, Folder, FolderView, Send, SendListView, SendView, @@ -24,7 +24,8 @@ pub enum DocRef { SendListView(SendListView), // Crypto - InitCryptoRequest(InitCryptoRequest), + InitUserCryptoRequest(InitUserCryptoRequest), + InitOrgCryptoRequest(InitOrgCryptoRequest), // Generators PasswordGeneratorRequest(PasswordGeneratorRequest), diff --git a/crates/bitwarden-uniffi/src/lib.rs b/crates/bitwarden-uniffi/src/lib.rs index 6e5415d38..5035f22b9 100644 --- a/crates/bitwarden-uniffi/src/lib.rs +++ b/crates/bitwarden-uniffi/src/lib.rs @@ -4,9 +4,10 @@ use std::sync::Arc; use async_lock::RwLock; use auth::ClientAuth; -use bitwarden::{client::client_settings::ClientSettings, mobile::crypto::InitCryptoRequest}; +use bitwarden::client::client_settings::ClientSettings; pub mod auth; +pub mod crypto; mod error; pub mod tool; mod uniffi_support; @@ -15,6 +16,7 @@ pub mod vault; #[cfg(feature = "docs")] pub mod docs; +use crypto::ClientCrypto; use error::Result; use tool::ClientGenerators; use vault::ClientVault; @@ -22,9 +24,6 @@ use vault::ClientVault; #[derive(uniffi::Object)] pub struct Client(RwLock); -#[derive(uniffi::Object)] -pub struct ClientCrypto(Arc); - #[uniffi::export] impl Client { /// Initialize a new instance of the SDK client @@ -58,18 +57,3 @@ impl Client { msg } } - -#[uniffi::export] -impl ClientCrypto { - /// Initialization method for the crypto. Needs to be called before any other crypto operations. - pub async fn initialize_crypto(&self, req: InitCryptoRequest) -> Result<()> { - Ok(self - .0 - .0 - .write() - .await - .crypto() - .initialize_crypto(req) - .await?) - } -} diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index da5398a12..6533c7d2e 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -80,6 +80,10 @@ impl EncryptionSettings { let private_key = self.private_key.as_ref().ok_or(Error::VaultLocked)?; + // Make sure we only keep the keys given in the arguments and not any of the previous + // ones, which might be from organizations that the user is no longer a part of anymore + self.org_keys.clear(); + // Decrypt the org keys with the private key for (org_id, org_enc_key) in org_enc_keys { let data = match org_enc_key { diff --git a/crates/bitwarden/src/mobile/client_crypto.rs b/crates/bitwarden/src/mobile/client_crypto.rs index 67f69d8f1..c0edb1982 100644 --- a/crates/bitwarden/src/mobile/client_crypto.rs +++ b/crates/bitwarden/src/mobile/client_crypto.rs @@ -2,7 +2,9 @@ use crate::Client; #[cfg(feature = "internal")] use crate::{ error::Result, - mobile::crypto::{initialize_crypto, InitCryptoRequest}, + mobile::crypto::{ + initialize_org_crypto, initialize_user_crypto, InitOrgCryptoRequest, InitUserCryptoRequest, + }, }; pub struct ClientCrypto<'a> { @@ -11,8 +13,13 @@ pub struct ClientCrypto<'a> { impl<'a> ClientCrypto<'a> { #[cfg(feature = "internal")] - pub async fn initialize_crypto(&mut self, req: InitCryptoRequest) -> Result<()> { - initialize_crypto(self.client, req).await + pub async fn initialize_user_crypto(&mut self, req: InitUserCryptoRequest) -> Result<()> { + initialize_user_crypto(self.client, req).await + } + + #[cfg(feature = "internal")] + pub async fn initialize_org_crypto(&mut self, req: InitOrgCryptoRequest) -> Result<()> { + initialize_org_crypto(self.client, req).await } } diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index f4d26dc6c..2cf850279 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -9,23 +9,32 @@ use crate::{client::kdf::Kdf, crypto::EncString, error::Result, Client}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] -pub struct InitCryptoRequest { +pub struct InitUserCryptoRequest { /// The user's KDF parameters, as received from the prelogin request pub kdf_params: Kdf, /// The user's email address pub email: String, - /// The user's master password - pub password: String, - /// The user's encrypted symmetric crypto key - pub user_key: String, - /// The user's encryptred private key + /// The user's encrypted private key pub private_key: String, - /// The encryption keys for all the organizations the user is a part of - pub organization_keys: HashMap, + /// The initialization method to use + pub method: InitUserCryptoMethod, } #[cfg(feature = "internal")] -pub async fn initialize_crypto(client: &mut Client, req: InitCryptoRequest) -> Result<()> { +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Enum))] +pub enum InitUserCryptoMethod { + Password { + /// The user's master password + password: String, + /// The user's encrypted symmetric crypto key + user_key: String, + }, +} + +#[cfg(feature = "internal")] +pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequest) -> Result<()> { let login_method = crate::client::LoginMethod::User(crate::client::UserLoginMethod::Username { client_id: "".to_string(), email: req.email, @@ -33,18 +42,30 @@ pub async fn initialize_crypto(client: &mut Client, req: InitCryptoRequest) -> R }); client.set_login_method(login_method); - let user_key = req.user_key.parse::()?; - let private_key = req.private_key.parse::()?; + let private_key: EncString = req.private_key.parse()?; - client.initialize_user_crypto(&req.password, user_key, private_key)?; + match req.method { + InitUserCryptoMethod::Password { password, user_key } => { + let user_key: EncString = user_key.parse()?; + client.initialize_user_crypto(&password, user_key, private_key)?; + } + } - let organization_keys = req - .organization_keys - .into_iter() - .map(|(k, v)| Ok((k, v.parse::()?))) - .collect::>>()?; + Ok(()) +} - client.initialize_org_crypto(organization_keys)?; +#[cfg(feature = "internal")] +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] +pub struct InitOrgCryptoRequest { + /// The encryption keys for all the organizations the user is a part of + pub organization_keys: HashMap, +} +#[cfg(feature = "internal")] +pub async fn initialize_org_crypto(client: &mut Client, req: InitOrgCryptoRequest) -> Result<()> { + let organization_keys = req.organization_keys.into_iter().collect(); + client.initialize_org_crypto(organization_keys)?; Ok(()) } diff --git a/crates/bitwarden/tests/register.rs b/crates/bitwarden/tests/register.rs index d4e632e55..956fe86ce 100644 --- a/crates/bitwarden/tests/register.rs +++ b/crates/bitwarden/tests/register.rs @@ -4,7 +4,11 @@ async fn test_register_initialize_crypto() { use std::num::NonZeroU32; - use bitwarden::{client::kdf::Kdf, mobile::crypto::InitCryptoRequest, Client}; + use bitwarden::{ + client::kdf::Kdf, + mobile::crypto::{InitUserCryptoMethod, InitUserCryptoRequest}, + Client, + }; let mut client = Client::new(None); @@ -22,13 +26,15 @@ async fn test_register_initialize_crypto() { // Ensure we can initialize the crypto with the new keys client .crypto() - .initialize_crypto(InitCryptoRequest { + .initialize_user_crypto(InitUserCryptoRequest { kdf_params: kdf, email: email.to_owned(), - password: password.to_owned(), - user_key: register_response.encrypted_user_key, private_key: register_response.keys.private.to_string(), - organization_keys: Default::default(), + + method: InitUserCryptoMethod::Password { + password: password.to_owned(), + user_key: register_response.encrypted_user_key, + }, }) .await .unwrap(); diff --git a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt index 2d204e075..13dec7d0e 100644 --- a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt +++ b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt @@ -12,7 +12,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import com.bitwarden.core.DateTime import com.bitwarden.core.Folder -import com.bitwarden.core.InitCryptoRequest +import com.bitwarden.core.InitOrgCryptoRequest +import com.bitwarden.core.InitUserCryptoMethod +import com.bitwarden.core.InitUserCryptoRequest import com.bitwarden.core.Kdf import com.bitwarden.core.Uuid import com.bitwarden.myapplication.ui.theme.MyApplicationTheme @@ -117,7 +119,7 @@ class MainActivity : ComponentActivity() { }.body() val folders = (syncBody["folders"] as JsonArray).map { - val o = it as JsonObject; + val o = it as JsonObject Folder( (o["id"] as JsonPrimitive).content, (o["name"] as JsonPrimitive).content, @@ -136,13 +138,20 @@ class MainActivity : ComponentActivity() { orgKeys[(o["id"] as JsonPrimitive).content] = (o["key"] as JsonPrimitive).content } - client.crypto().initializeCrypto( - InitCryptoRequest( + client.crypto().initializeUserCrypto( + InitUserCryptoRequest( kdfParams = kdf, email = EMAIL, - password = PASSWORD, - userKey = loginBody.Key, privateKey = loginBody.PrivateKey, + method = InitUserCryptoMethod.Password( + password = PASSWORD, + userKey = loginBody.Key + ) + ) + ) + + client.crypto().initializeOrgCrypto( + InitOrgCryptoRequest( organizationKeys = orgKeys ) ) diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index 6174df750..70446bd8f 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -182,14 +182,26 @@ Decrypt collection list ## ClientCrypto -### `initialize_crypto` +### `initialize_user_crypto` -Initialization method for the crypto. Needs to be called before any other crypto operations. +Initialization method for the user crypto. Needs to be called before any other crypto operations. **Arguments**: - self: -- req: [InitCryptoRequest](#initcryptorequest) +- req: [InitUserCryptoRequest](#initusercryptorequest) + +**Output**: std::result::Result<,BitwardenError> + +### `initialize_org_crypto` + +Initialization method for the organization crypto. Needs to be called after +`initialize_user_crypto` but before any other crypto operations. + +**Arguments**: + +- self: +- req: [InitOrgCryptoRequest](#initorgcryptorequest) **Output**: std::result::Result<,BitwardenError> @@ -492,6 +504,11 @@ implementations. array + + key + + More recent ciphers uses individual encryption keys to encrypt the other fields of the Cipher. + name @@ -617,6 +634,11 @@ implementations. array + + key + + + name string @@ -835,7 +857,7 @@ implementations. -## `InitCryptoRequest` +## `InitOrgCryptoRequest` @@ -844,34 +866,75 @@ implementations. - - - + + + +
Description
kdfParamsThe user's KDF parameters, as received from the prelogin requestorganizationKeysobjectThe encryption keys for all the organizations the user is a part of
+ +## `InitUserCryptoMethod` + + - - - + + + - - + + + + + + +
emailstringThe user's email addressKeyTypeDescription
passwordstringThe user's master passwordobject
+ + + + + + + + + + + + + + + + +
KeyTypeDescription
passwordstringThe user's master password
user_keystringThe user's encrypted symmetric crypto key
+
+ +## `InitUserCryptoRequest` + + + + + + + + + + + - + - + - + - - - + + +
KeyTypeDescription
kdfParamsThe user's KDF parameters, as received from the prelogin request
userKeyemail stringThe user's encrypted symmetric crypto keyThe user's email address
privateKey stringThe user's encryptred private keyThe user's encrypted private key
organizationKeysobjectThe encryption keys for all the organizations the user is a part ofmethodThe initialization method to use
diff --git a/languages/swift/iOS/App/ContentView.swift b/languages/swift/iOS/App/ContentView.swift index 4b3555403..484caf14f 100644 --- a/languages/swift/iOS/App/ContentView.swift +++ b/languages/swift/iOS/App/ContentView.swift @@ -136,13 +136,19 @@ struct ContentView: View { ///////////////////////////// Initialize crypto ///////////////////////////// - try await client.crypto().initializeCrypto( - req: InitCryptoRequest( + try await client.crypto().initializeUserCrypto( + req: InitUserCryptoRequest( kdfParams: kdf, email: EMAIL, - password: PASSWORD, - userKey: loginData.Key, privateKey: loginData.PrivateKey, + method: InitUserCryptoMethod.password( + password: PASSWORD, + userKey: loginData.Key + ) + )) + + try await client.crypto().initializeOrgCrypto( + req: InitOrgCryptoRequest( organizationKeys: Dictionary.init( uniqueKeysWithValues: syncData.profile.organizations.map { ($0.id, $0.key) } ) From 4c68256820e65572313d209c5c09e07f0f2d29e1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 11:38:19 +0100 Subject: [PATCH 26/30] Update pyo3 non-major (#289) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate logo banner](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [pyo3](https://togithub.com/pyo3/pyo3) | dependencies | minor | `0.19.1` -> `0.20.0` | | [pyo3-asyncio](https://togithub.com/awestlake87/pyo3-asyncio) | dependencies | minor | `0.19.0` -> `0.20.0` | | [pyo3-build-config](https://togithub.com/pyo3/pyo3) | build-dependencies | minor | `0.19.1` -> `0.20.0` | | [pyo3-log](https://togithub.com/vorner/pyo3-log) | dependencies | minor | `0.8.3` -> `0.9.0` | --- ### Release Notes
pyo3/pyo3 (pyo3) ### [`v0.20.0`](https://togithub.com/pyo3/pyo3/blob/HEAD/CHANGELOG.md#0200---2023-10-11) [Compare Source](https://togithub.com/pyo3/pyo3/compare/v0.19.2...v0.20.0) ##### Packaging - Dual-license PyO3 under either the Apache 2.0 OR the MIT license. This makes the project GPLv2 compatible. [#​3108](https://togithub.com/PyO3/pyo3/pull/3108) - Update MSRV to Rust 1.56. [#​3208](https://togithub.com/PyO3/pyo3/pull/3208) - Bump `indoc` dependency to 2.0 and `unindent` dependency to 0.2. [#​3237](https://togithub.com/PyO3/pyo3/pull/3237) - Bump `syn` dependency to 2.0. [#​3239](https://togithub.com/PyO3/pyo3/pull/3239) - Drop support for debug builds of Python 3.7. [#​3387](https://togithub.com/PyO3/pyo3/pull/3387) - Bump `chrono` optional dependency to require 0.4.25 or newer. [#​3427](https://togithub.com/PyO3/pyo3/pull/3427) - Support Python 3.12. [#​3488](https://togithub.com/PyO3/pyo3/pull/3488) ##### Added - Support `__lt__`, `__le__`, `__eq__`, `__ne__`, `__gt__` and `__ge__` in `#[pymethods]`. [#​3203](https://togithub.com/PyO3/pyo3/pull/3203) - Add FFI definition `Py_GETENV`. [#​3336](https://togithub.com/PyO3/pyo3/pull/3336) - Add `as_ptr` and `into_ptr` inherent methods for `Py`, `PyAny`, `PyRef`, and `PyRefMut`. [#​3359](https://togithub.com/PyO3/pyo3/pull/3359) - Implement `DoubleEndedIterator` for `PyTupleIterator` and `PyListIterator`. [#​3366](https://togithub.com/PyO3/pyo3/pull/3366) - Add `#[pyclass(rename_all = "...")]` option: this allows renaming all getters and setters of a struct, or all variants of an enum. Available renaming rules are: `"camelCase"`, `"kebab-case"`, `"lowercase"`, `"PascalCase"`, `"SCREAMING-KEBAB-CASE"`, `"SCREAMING_SNAKE_CASE"`, `"snake_case"`, `"UPPERCASE"`. [#​3384](https://togithub.com/PyO3/pyo3/pull/3384) - Add FFI definitions `PyObject_GC_IsTracked` and `PyObject_GC_IsFinalized` on Python 3.9 and up (PyPy 3.10 and up). [#​3403](https://togithub.com/PyO3/pyo3/pull/3403) - Add types for `None`, `Ellipsis`, and `NotImplemented`. [#​3408](https://togithub.com/PyO3/pyo3/pull/3408) - Add FFI definitions for the `Py_mod_multiple_interpreters` constant and its possible values. [#​3494](https://togithub.com/PyO3/pyo3/pull/3494) - Add FFI definitions for `PyInterpreterConfig` struct, its constants and `Py_NewInterpreterFromConfig`. [#​3502](https://togithub.com/PyO3/pyo3/pull/3502) ##### Changed - Change `PySet::discard` to return `PyResult` (previously returned nothing). [#​3281](https://togithub.com/PyO3/pyo3/pull/3281) - Optimize implmentation of `IntoPy` for Rust tuples to Python tuples. [#​3321](https://togithub.com/PyO3/pyo3/pull/3321) - Change `PyDict::get_item` to no longer suppress arbitrary exceptions (the return type is now `PyResult>` instead of `Option<&PyAny>`), and deprecate `PyDict::get_item_with_error`. [#​3330](https://togithub.com/PyO3/pyo3/pull/3330) - Deprecate FFI definitions which are deprecated in Python 3.12. [#​3336](https://togithub.com/PyO3/pyo3/pull/3336) - `AsPyPointer` is now an `unsafe trait`. [#​3358](https://togithub.com/PyO3/pyo3/pull/3358) - Accept all `os.PathLike` values in implementation of `FromPyObject` for `PathBuf`. [#​3374](https://togithub.com/PyO3/pyo3/pull/3374) - Add `__builtins__` to globals in `py.run()` and `py.eval()` if they're missing. [#​3378](https://togithub.com/PyO3/pyo3/pull/3378) - Optimize implementation of `FromPyObject` for `BigInt` and `BigUint`. [#​3379](https://togithub.com/PyO3/pyo3/pull/3379) - `PyIterator::from_object` and `PyByteArray::from` now take a single argument of type `&PyAny` (previously took two arguments `Python` and `AsPyPointer`). [#​3389](https://togithub.com/PyO3/pyo3/pull/3389) - Replace `AsPyPointer` with `AsRef` as a bound in the blanket implementation of `From<&T> for PyObject`. [#​3391](https://togithub.com/PyO3/pyo3/pull/3391) - Replace blanket `impl IntoPy for &T where T: AsPyPointer` with implementations of `impl IntoPy` for `&PyAny`, `&T where T: AsRef`, and `&Py`. [#​3393](https://togithub.com/PyO3/pyo3/pull/3393) - Preserve `std::io::Error` kind in implementation of `From` for `PyErr` [#​3396](https://togithub.com/PyO3/pyo3/pull/3396) - Try to select a relevant `ErrorKind` in implementation of `From` for `OSError` subclass. [#​3397](https://togithub.com/PyO3/pyo3/pull/3397) - Retrieve the original `PyErr` in implementation of `From` for `PyErr` if the `std::io::Error` has been built using a Python exception (previously would create a new exception wrapping the `std::io::Error`). [#​3402](https://togithub.com/PyO3/pyo3/pull/3402) - `#[pymodule]` will now return the same module object on repeated import by the same Python interpreter, on Python 3.9 and up. [#​3446](https://togithub.com/PyO3/pyo3/pull/3446) - Truncate leap-seconds and warn when converting `chrono` types to Python `datetime` types (`datetime` cannot represent leap-seconds). [#​3458](https://togithub.com/PyO3/pyo3/pull/3458) - `Err` returned from `#[pyfunction]` will now have a non-None `__context__` if called from inside a `catch` block. [#​3455](https://togithub.com/PyO3/pyo3/pull/3455) - Deprecate undocumented `#[__new__]` form of `#[new]` attribute. [#​3505](https://togithub.com/PyO3/pyo3/pull/3505) ##### Removed - Remove all functionality deprecated in PyO3 0.18, including `#[args]` attribute for `#[pymethods]`. [#​3232](https://togithub.com/PyO3/pyo3/pull/3232) - Remove `IntoPyPointer` trait in favour of `into_ptr` inherent methods. [#​3385](https://togithub.com/PyO3/pyo3/pull/3385) ##### Fixed - Handle exceptions properly in `PySet::discard`. [#​3281](https://togithub.com/PyO3/pyo3/pull/3281) - The `PyTupleIterator` type returned by `PyTuple::iter` is now public and hence can be named by downstream crates. [#​3366](https://togithub.com/PyO3/pyo3/pull/3366) - Linking of `PyOS_FSPath` on PyPy. [#​3374](https://togithub.com/PyO3/pyo3/pull/3374) - Fix memory leak in `PyTypeBuilder::build`. [#​3401](https://togithub.com/PyO3/pyo3/pull/3401) - Disable removed FFI definitions `_Py_GetAllocatedBlocks`, `_PyObject_GC_Malloc`, and `_PyObject_GC_Calloc` on Python 3.11 and up. [#​3403](https://togithub.com/PyO3/pyo3/pull/3403) - Fix `ResourceWarning` and crashes related to GC when running with debug builds of CPython. [#​3404](https://togithub.com/PyO3/pyo3/pull/3404) - Some-wrapping of `Option` default arguments will no longer re-wrap `Some(T)` or expressions evaluating to `None`. [#​3461](https://togithub.com/PyO3/pyo3/pull/3461) - Fix `IterNextOutput::Return` not returning a value on PyPy. [#​3471](https://togithub.com/PyO3/pyo3/pull/3471) - Emit compile errors instead of ignoring macro invocations inside `#[pymethods]` blocks. [#​3491](https://togithub.com/PyO3/pyo3/pull/3491) - Emit error on invalid arguments to `#[new]`, `#[classmethod]`, `#[staticmethod]`, and `#[classattr]`. [#​3484](https://togithub.com/PyO3/pyo3/pull/3484) - Disable `PyMarshal_WriteObjectToString` from `PyMarshal_ReadObjectFromString` with the `abi3` feature. [#​3490](https://togithub.com/PyO3/pyo3/pull/3490) - Fix FFI definitions for `_PyFrameEvalFunction` on Python 3.11 and up (it now receives a `_PyInterpreterFrame` opaque struct). [#​3500](https://togithub.com/PyO3/pyo3/pull/3500) ### [`v0.19.2`](https://togithub.com/pyo3/pyo3/blob/HEAD/CHANGELOG.md#0192---2023-08-01) [Compare Source](https://togithub.com/pyo3/pyo3/compare/v0.19.1...v0.19.2) ##### Added - Add FFI definitions `PyState_AddModule`, `PyState_RemoveModule` and `PyState_FindModule` for PyPy 3.9 and up. [#​3295](https://togithub.com/PyO3/pyo3/pull/3295) - Add FFI definitions `_PyObject_CallFunction_SizeT` and `_PyObject_CallMethod_SizeT`. [#​3297](https://togithub.com/PyO3/pyo3/pull/3297) - Add a "performance" section to the guide collecting performance-related tricks and problems. [#​3304](https://togithub.com/PyO3/pyo3/pull/3304) - Add `PyErr::Display` for all Python versions, and FFI symbol `PyErr_DisplayException` for Python 3.12. [#​3334](https://togithub.com/PyO3/pyo3/pull/3334) - Add FFI definition `PyType_GetDict()` for Python 3.12. [#​3339](https://togithub.com/PyO3/pyo3/pull/3339) - Add `PyAny::downcast_exact`. [#​3346](https://togithub.com/PyO3/pyo3/pull/3346) - Add `PySlice::full()` to construct a full slice (`::`). [#​3353](https://togithub.com/PyO3/pyo3/pull/3353) ##### Changed - Update `PyErr` for 3.12 betas to avoid deprecated ffi methods. [#​3306](https://togithub.com/PyO3/pyo3/pull/3306) - Update FFI definitions of `object.h` for Python 3.12.0b4. [#​3335](https://togithub.com/PyO3/pyo3/pull/3335) - Update `pyo3::ffi` struct definitions to be compatible with 3.12.0b4. [#​3342](https://togithub.com/PyO3/pyo3/pull/3342) - Optimize conversion of `float` to `f64` (and `PyFloat::value`) on non-abi3 builds. [#​3345](https://togithub.com/PyO3/pyo3/pull/3345) ##### Fixed - Fix timezone conversion bug for FixedOffset datetimes that were being incorrectly converted to and from UTC. [#​3269](https://togithub.com/PyO3/pyo3/pull/3269) - Fix `SystemError` raised in `PyUnicodeDecodeError_Create` on PyPy 3.10. [#​3297](https://togithub.com/PyO3/pyo3/pull/3297) - Correct FFI definition `Py_EnterRecursiveCall` to return `c_int` (was incorrectly returning `()`). [#​3300](https://togithub.com/PyO3/pyo3/pull/3300) - Fix case where `PyErr::matches` and `PyErr::is_instance` returned results inconsistent with `PyErr::get_type`. [#​3313](https://togithub.com/PyO3/pyo3/pull/3313) - Fix loss of panic message in `PanicException` when unwinding after the exception was "normalized". [#​3326](https://togithub.com/PyO3/pyo3/pull/3326) - Fix `PyErr::from_value` and `PyErr::into_value` losing traceback on conversion. [#​3328](https://togithub.com/PyO3/pyo3/pull/3328) - Fix reference counting of immortal objects on Python 3.12.0b4. [#​3335](https://togithub.com/PyO3/pyo3/pull/3335)
vorner/pyo3-log (pyo3-log) ### [`v0.9.0`](https://togithub.com/vorner/pyo3-log/blob/HEAD/CHANGELOG.md#090) [Compare Source](https://togithub.com/vorner/pyo3-log/compare/v0.8.4...v0.9.0) - Bump lowest allowed version of pyo3 to 0.15 ‒ this prevents linking multiple pyo3 versions together. ### [`v0.8.4`](https://togithub.com/vorner/pyo3-log/blob/HEAD/CHANGELOG.md#084) [Compare Source](https://togithub.com/vorner/pyo3-log/compare/v0.8.3...v0.8.4) - Allow pyo3 0.20.
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 45 +++++++++++++++++----------------- crates/bitwarden-py/Cargo.toml | 8 +++--- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ca15b625..e4ad7e61e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1577,9 +1577,9 @@ dependencies = [ [[package]] name = "indoc" -version = "1.0.9" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" +checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" [[package]] name = "infer" @@ -2274,9 +2274,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e681a6cfdc4adcc93b4d3cf993749a4552018ee0a9b65fc0ccfad74352c72a38" +checksum = "04e8453b658fe480c3e70c8ed4e3d3ec33eb74988bd186561b0cc66b85c3bc4b" dependencies = [ "cfg-if", "indoc", @@ -2291,9 +2291,9 @@ dependencies = [ [[package]] name = "pyo3-asyncio" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2cc34c1f907ca090d7add03dc523acdd91f3a4dab12286604951e2f5152edad" +checksum = "6ea6b68e93db3622f3bb3bf363246cf948ed5375afe7abff98ccbdd50b184995" dependencies = [ "futures", "once_cell", @@ -2305,9 +2305,9 @@ dependencies = [ [[package]] name = "pyo3-asyncio-macros" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4045f06429547179e4596f5c0b13c82efc8b04296016780133653ed69ce26b3" +checksum = "56c467178e1da6252c95c29ecf898b133f742e9181dca5def15dc24e19d45a39" dependencies = [ "proc-macro2", "quote", @@ -2316,9 +2316,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076c73d0bc438f7a4ef6fdd0c3bb4732149136abd952b110ac93e4edb13a6ba5" +checksum = "a96fe70b176a89cff78f2fa7b3c930081e163d5379b4dcdf993e3ae29ca662e5" dependencies = [ "once_cell", "target-lexicon", @@ -2326,9 +2326,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53cee42e77ebe256066ba8aa77eff722b3bb91f3419177cf4cd0f304d3284d9" +checksum = "214929900fd25e6604661ed9cf349727c8920d47deff196c4e28165a6ef2a96b" dependencies = [ "libc", "pyo3-build-config", @@ -2336,9 +2336,9 @@ dependencies = [ [[package]] name = "pyo3-log" -version = "0.8.4" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c09c2b349b6538d8a73d436ca606dab6ce0aaab4dad9e6b7bdd57a4f556c3bc3" +checksum = "4c10808ee7250403bedb24bc30c32493e93875fef7ba3e4292226fe924f398bd" dependencies = [ "arc-swap", "log", @@ -2347,25 +2347,26 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfeb4c99597e136528c6dd7d5e3de5434d1ceaf487436a3f03b2d56b6fc9efd1" +checksum = "dac53072f717aa1bfa4db832b39de8c875b7c7af4f4a6fe93cdbf9264cf8383b" dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] name = "pyo3-macros-backend" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "947dc12175c254889edc0c02e399476c2f652b4b9ebd123aa655c224de259536" +checksum = "7774b5a8282bd4f25f803b1f0d945120be959a36c72e08e7cd031c792fdfd424" dependencies = [ + "heck", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] @@ -3581,9 +3582,9 @@ dependencies = [ [[package]] name = "unindent" -version = "0.1.11" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" +checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" [[package]] name = "unsafe-libyaml" diff --git a/crates/bitwarden-py/Cargo.toml b/crates/bitwarden-py/Cargo.toml index 5d8d95575..613203c84 100644 --- a/crates/bitwarden-py/Cargo.toml +++ b/crates/bitwarden-py/Cargo.toml @@ -10,17 +10,17 @@ name = "bitwarden_py" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.19.1", features = ["extension-module"] } -pyo3-log = "0.8.3" +pyo3 = { version = "0.20.0", features = ["extension-module"] } +pyo3-log = "0.9.0" bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } [build-dependencies] -pyo3-build-config = { version = "0.19.1" } +pyo3-build-config = { version = "0.20.0" } [target.'cfg(not(target_arch="wasm32"))'.dependencies] tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } -pyo3-asyncio = { version = "0.19.0", features = [ +pyo3-asyncio = { version = "0.20.0", features = [ "attributes", "tokio-runtime", ] } From d64782e7bf4937eb50500556057a70b686ac57ff Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:32:10 +0100 Subject: [PATCH 27/30] Lock file maintenance (#324) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate logo banner](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Update | Change | |---|---| | lockFileMaintenance | All locks refreshed | 🔧 This Pull Request updates lock files to use the latest dependency versions. --- ### Configuration 📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Daniel García --- Cargo.lock | 283 +++++++++++---------- crates/bitwarden-napi/package-lock.json | 6 +- crates/bitwarden-napi/src/client.rs | 1 - crates/bitwarden-wasm/Cargo.toml | 2 +- languages/js_webassembly/package-lock.json | 168 ++++++------ package-lock.json | 30 +-- 6 files changed, 247 insertions(+), 243 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4ad7e61e..f9fbba7e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,7 +156,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -203,11 +203,11 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e900cdcd39bb94a14487d3f7ef92ca222162e6c7c3fe7cb3550ea75fb486ed" +checksum = "655b9c7fe787d3b25cc0f804a1a8401790f0c5bc395beb5a64dc77d8de079105" dependencies = [ - "event-listener 3.0.1", + "event-listener 3.1.0", "event-listener-strategy", "pin-project-lite", ] @@ -220,7 +220,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -332,7 +332,7 @@ dependencies = [ "bitwarden-api-identity", "cbc", "chrono", - "getrandom 0.2.10", + "getrandom 0.2.11", "hkdf", "hmac", "lazy_static", @@ -495,9 +495,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" +checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" dependencies = [ "memchr", "serde", @@ -547,7 +547,7 @@ dependencies = [ "tempfile", "thiserror", "tokio", - "toml 0.8.6", + "toml 0.8.8", "uuid", ] @@ -586,9 +586,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" +checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff" dependencies = [ "serde", ] @@ -656,9 +656,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.7" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", "clap_derive", @@ -666,9 +666,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.7" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" dependencies = [ "anstream", "anstyle", @@ -694,7 +694,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -732,9 +732,9 @@ dependencies = [ [[package]] name = "color-spantrace" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" dependencies = [ "once_cell", "owo-colors", @@ -925,7 +925,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37e366bff8cd32dd8754b0991fb66b279dc48f598c3a18914852a6673deef583" dependencies = [ "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -1002,9 +1002,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" [[package]] name = "either" @@ -1029,9 +1029,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" dependencies = [ "humantime", "is-terminal", @@ -1048,9 +1048,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" dependencies = [ "libc", "windows-sys 0.48.0", @@ -1064,9 +1064,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "3.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cec0252c2afff729ee6f00e903d479fba81784c8e2bd77447673471fdfaea1" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" dependencies = [ "concurrent-queue", "parking", @@ -1079,15 +1079,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" dependencies = [ - "event-listener 3.0.1", + "event-listener 3.1.0", "pin-project-lite", ] [[package]] name = "eyre" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "80f656be11ddf91bd709454d15d5bd896fbaf4cc3314e69349e4d1569f5b46cd" dependencies = [ "indenter", "once_cell", @@ -1150,9 +1150,12 @@ dependencies = [ [[package]] name = "fs-err" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" +checksum = "fb5fd9bcbe8b1087cbd395b51498c01bc997cef73e778a80b77a811af5e2d29f" +dependencies = [ + "autocfg", +] [[package]] name = "futures" @@ -1225,7 +1228,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -1300,9 +1303,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "js-sys", @@ -1349,9 +1352,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.21" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" dependencies = [ "bytes", "fnv", @@ -1359,7 +1362,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.1.0", "slab", "tokio", "tokio-util", @@ -1419,9 +1422,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -1567,9 +1570,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", "hashbrown 0.14.2", @@ -1680,18 +1683,18 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -1700,6 +1703,17 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] + [[package]] name = "line-wrap" version = "0.1.1" @@ -1711,9 +1725,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "lock_api" @@ -1814,9 +1828,9 @@ dependencies = [ [[package]] name = "napi" -version = "2.13.3" +version = "2.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd063c93b900149304e3ba96ce5bf210cd4f81ef5eb80ded0d100df3e85a3ac0" +checksum = "1133249c46e92da921bafc8aba4912bf84d6c475f7625183772ed2d0844dc3a7" dependencies = [ "bitflags 2.4.1", "ctor", @@ -1828,15 +1842,15 @@ dependencies = [ [[package]] name = "napi-build" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882a73d9ef23e8dc2ebbffb6a6ae2ef467c0f18ac10711e4cc59c5485d41df0e" +checksum = "d4b4532cf86bfef556348ac65e561e3123879f0e7566cca6d43a6ff5326f13df" [[package]] name = "napi-derive" -version = "2.13.0" +version = "2.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da1c6a8fa84d549aa8708fcd062372bf8ec6e849de39016ab921067d21bde367" +checksum = "a0cca5738c6e81eb5ffd2c8ff2b4f05ece9c4c60c7e2b36cec6524492cf7f330" dependencies = [ "cfg-if", "convert_case", @@ -1848,9 +1862,9 @@ dependencies = [ [[package]] name = "napi-derive-backend" -version = "1.0.52" +version = "1.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20bbc7c69168d06a848f925ec5f0e0997f98e8c8d4f2cc30157f0da51c009e17" +checksum = "35960e5f33228192a9b661447d0dfe8f5a3790ff5b4058c4d67680ded4f65b91" dependencies = [ "convert_case", "once_cell", @@ -1863,9 +1877,9 @@ dependencies = [ [[package]] name = "napi-sys" -version = "2.2.3" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "166b5ef52a3ab5575047a9fe8d4a030cdd0f63c96f071cd6907674453b07bae3" +checksum = "2503fa6af34dc83fb74888df8b22afe933b58d37daf7d80424b1c60c68196b8b" dependencies = [ "libloading", ] @@ -2043,9 +2057,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.57" +version = "0.10.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -2064,7 +2078,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2084,9 +2098,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.93" +version = "0.9.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" +checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" dependencies = [ "cc", "libc", @@ -2137,7 +2151,7 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall", "smallvec", "windows-targets 0.48.5", ] @@ -2239,12 +2253,12 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "plist" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a4a0cfc5fb21a09dc6af4bf834cf10d4a32fccd9e2ea468c4b1751a097487aa" +checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" dependencies = [ "base64 0.21.5", - "indexmap 1.9.3", + "indexmap 2.1.0", "line-wrap", "quick-xml", "serde", @@ -2354,7 +2368,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2366,14 +2380,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "quick-xml" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" dependencies = [ "memchr", ] @@ -2446,7 +2460,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", ] [[package]] @@ -2458,15 +2472,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -2478,12 +2483,12 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.10", - "redox_syscall 0.2.16", + "getrandom 0.2.11", + "libredox", "thiserror", ] @@ -2619,9 +2624,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ "bitflags 2.4.1", "errno", @@ -2668,9 +2673,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" dependencies = [ "chrono", "dyn-clone", @@ -2683,9 +2688,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" dependencies = [ "proc-macro2", "quote", @@ -2722,7 +2727,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2772,22 +2777,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.190" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.190" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2842,7 +2847,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2872,7 +2877,7 @@ version = "0.9.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.1.0", "itoa", "ryu", "serde", @@ -2942,9 +2947,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", "rand_core 0.6.4", @@ -2967,9 +2972,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "socket2" @@ -3041,7 +3046,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3073,9 +3078,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -3136,16 +3141,16 @@ checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand 2.0.1", - "redox_syscall 0.4.1", + "redox_syscall", "rustix", "windows-sys 0.48.0", ] [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" dependencies = [ "winapi-util", ] @@ -3167,7 +3172,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3226,9 +3231,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.33.0" +version = "1.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" dependencies = [ "backtrace", "bytes", @@ -3243,13 +3248,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3287,9 +3292,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ff9e3abce27ee2c9a37f9ad37238c1bdd4e789c84ba37df76aa4d528f5072cc" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" dependencies = [ "serde", "serde_spanned", @@ -3308,11 +3313,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.20.7" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", @@ -3344,7 +3349,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3369,20 +3374,20 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term 0.46.0", @@ -3510,7 +3515,7 @@ version = "0.25.0" source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3540,7 +3545,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.38", + "syn 2.0.39", "toml 0.5.11", "uniffi_build", "uniffi_meta", @@ -3612,9 +3617,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" +checksum = "c58fe91d841bc04822c9801002db4ea904b9e4b8e6bbad25127b46eff8dc516b" dependencies = [ "serde", ] @@ -3697,7 +3702,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", "wasm-bindgen-shared", ] @@ -3731,7 +3736,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3967,9 +3972,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.17" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" dependencies = [ "memchr", ] @@ -3986,9 +3991,9 @@ dependencies = [ [[package]] name = "wiremock" -version = "0.5.19" +version = "0.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f71803d3a1c80377a06221e0530be02035d5b3e854af56c6ece7ac20ac441d" +checksum = "079aee011e8a8e625d16df9e785de30a6b77f80a6126092d76a57375f96448da" dependencies = [ "assert-json-diff", "async-trait", @@ -4008,6 +4013,6 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 65266d1e4..3ccf3a7cb 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -95,9 +95,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", - "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", + "version": "20.9.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", + "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", "dev": true, "peer": true, "dependencies": { diff --git a/crates/bitwarden-napi/src/client.rs b/crates/bitwarden-napi/src/client.rs index 840fd2533..d794b18f4 100644 --- a/crates/bitwarden-napi/src/client.rs +++ b/crates/bitwarden-napi/src/client.rs @@ -1,7 +1,6 @@ extern crate log; use bitwarden_json::client::Client as JsonClient; -use napi::bindgen_prelude::*; use napi_derive::napi; #[napi] diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index 6055388fb..add03f0f3 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] js-sys = "0.3.63" serde = {version = "1.0.163", features = ["derive"] } -wasm-bindgen = { version = "0.2.86", features = ["serde-serialize"] } +wasm-bindgen = { version = "=0.2.87", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4.36" console_error_panic_hook = "0.1.7" console_log = { version = "1.0.0", features = ["color"] } diff --git a/languages/js_webassembly/package-lock.json b/languages/js_webassembly/package-lock.json index e3e20e9aa..d5345c00a 100644 --- a/languages/js_webassembly/package-lock.json +++ b/languages/js_webassembly/package-lock.json @@ -88,9 +88,9 @@ "dev": true }, "node_modules/@types/body-parser": { - "version": "1.19.4", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz", - "integrity": "sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==", + "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": "*", @@ -98,27 +98,27 @@ } }, "node_modules/@types/bonjour": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.12.tgz", - "integrity": "sha512-ky0kWSqXVxSqgqJvPIkgFkcn4C8MnRog308Ou8xBBIVo39OmUFy+jqNe0nPwLCDFxUpmT9EvT91YzOJgkDRcFg==", + "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.37", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", - "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==", + "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.2", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.2.tgz", - "integrity": "sha512-gX2j9x+NzSh4zOhnRPSdPPmTepS4DfxES0AvIFv3jGv5QyeAJf6u6dY5/BAoAJU9Qq1uTvwOku8SSC2GnCRl6Q==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.3.tgz", + "integrity": "sha512-6mfQ6iNvhSKCZJoY6sIG3m0pKkdUcweVNOLuBBKvoWGzl2yRxOJcYOTRyLKt3nxXvBLJWa6QkW//tgbIwJehmA==", "dev": true, "dependencies": { "@types/express-serve-static-core": "*", @@ -126,9 +126,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.44.6", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.6.tgz", - "integrity": "sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==", + "version": "8.44.7", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.7.tgz", + "integrity": "sha512-f5ORu2hcBbKei97U73mf+l9t4zTGl74IqZ0GQk4oVea/VS8tQZYkUveSYojk+frraAVYId0V2WC9O4PTNru2FQ==", "dev": true, "dependencies": { "@types/estree": "*", @@ -136,9 +136,9 @@ } }, "node_modules/@types/eslint-scope": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.6.tgz", - "integrity": "sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==", + "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": "*", @@ -146,15 +146,15 @@ } }, "node_modules/@types/estree": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", - "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==", + "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.20", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz", - "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==", + "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": "*", @@ -164,9 +164,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.39", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.39.tgz", - "integrity": "sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==", + "version": "4.17.41", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", + "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", "dev": true, "dependencies": { "@types/node": "*", @@ -182,60 +182,60 @@ "dev": true }, "node_modules/@types/http-errors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz", - "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==", + "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.13", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.13.tgz", - "integrity": "sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==", + "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.14", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", - "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", + "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.4", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz", - "integrity": "sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==", + "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.8.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", - "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", + "version": "20.9.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", + "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, "node_modules/@types/node-forge": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.8.tgz", - "integrity": "sha512-vGXshY9vim9CJjrpcS5raqSjEfKlJcWy2HNdgUasR66fAnVEYarrf1ULV4nfvpC1nZq/moA9qyqBcu83x+Jlrg==", + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.9.tgz", + "integrity": "sha512-meK88cx/sTalPSLSoCzkiUB4VPIFHmxtXm5FaaqRDqBX2i/Sy8bJ4odsan0b20RBjPh06dAQ+OTTdnyQyhJZyQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/qs": { - "version": "6.9.9", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", - "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==", + "version": "6.9.10", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", + "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==", "dev": true }, "node_modules/@types/range-parser": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", - "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==", + "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": { @@ -245,9 +245,9 @@ "dev": true }, "node_modules/@types/send": { - "version": "0.17.3", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", - "integrity": "sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==", + "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", @@ -255,18 +255,18 @@ } }, "node_modules/@types/serve-index": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.3.tgz", - "integrity": "sha512-4KG+yMEuvDPRrYq5fyVm/I2uqAJSAwZK9VSa+Zf+zUq9/oxSSvy3kkIqyL+jjStv6UCVi8/Aho0NHtB1Fwosrg==", + "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.4", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz", - "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==", + "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": "*", @@ -275,18 +275,18 @@ } }, "node_modules/@types/sockjs": { - "version": "0.3.35", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.35.tgz", - "integrity": "sha512-tIF57KB+ZvOBpAQwSaACfEu7htponHXaFzP7RfKYgsOS0NoYnn+9+jzp7bbq4fWerizI3dTB4NfAZoyeQKWJLw==", + "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.8", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.8.tgz", - "integrity": "sha512-flUksGIQCnJd6sZ1l5dqCEG/ksaoAg/eUwiLAGTJQcfgvZJKF++Ta4bJA6A5aPSJmsr+xlseHn4KLgVlNnvPTg==", + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.9.tgz", + "integrity": "sha512-jbdrY0a8lxfdTp/+r7Z4CkycbOFN8WX+IOchLJr3juT/xzbJ8URyTVSJ/hvNdadTgM1mnedb47n+Y31GsFnQlg==", "dev": true, "dependencies": { "@types/node": "*" @@ -836,9 +836,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001558", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001558.tgz", - "integrity": "sha512-/Et7DwLqpjS47JPEcz6VnxU9PwcIdVi0ciLXRWBQdj1XFye68pSQYpV0QtPTfUKWuOaEig+/Vez2l74eDc1tPQ==", + "version": "1.0.30001563", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", + "integrity": "sha512-na2WUmOxnwIZtwnFI2CZ/3er0wdNzU7hN+cPYz/z2ajHThnkWjNBOpEPP4n+4r2WPM847JaMotaJE3bnfzjyKw==", "dev": true, "funding": [ { @@ -1278,9 +1278,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.569", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.569.tgz", - "integrity": "sha512-LsrJjZ0IbVy12ApW3gpYpcmHS3iRxH4bkKOW98y1/D+3cvDUWGcbzbsFinfUS8knpcZk/PG/2p/RnkMCYN7PVg==", + "version": "1.4.588", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.588.tgz", + "integrity": "sha512-soytjxwbgcCu7nh5Pf4S2/4wa6UIu+A3p03U2yVr53qGxi1/VTR3ENI+p50v+UxqqZAfl48j3z55ud7VHIOr9w==", "dev": true }, "node_modules/encodeurl": { @@ -1315,9 +1315,9 @@ } }, "node_modules/envinfo": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz", - "integrity": "sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", + "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", "dev": true, "bin": { "envinfo": "dist/cli.js" @@ -1327,9 +1327,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", - "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", + "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": { @@ -2845,9 +2845,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "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" @@ -3521,9 +3521,9 @@ } }, "node_modules/terser": { - "version": "5.23.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.23.0.tgz", - "integrity": "sha512-Iyy83LN0uX9ZZLCX4Qbu5JiHiWjOCTwrmM9InWOzVeM++KNWEsqV4YgN9U9E8AlohQ6Gs42ztczlWOG/lwDAMA==", + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", + "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", diff --git a/package-lock.json b/package-lock.json index ac70b185d..6ee8982ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -363,9 +363,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", - "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", + "version": "20.9.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", + "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", "dev": true, "peer": true, "dependencies": { @@ -373,9 +373,9 @@ } }, "node_modules/@types/urijs": { - "version": "1.19.22", - "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.22.tgz", - "integrity": "sha512-qnYBwfN7O/+i6E1Kr8JaCKsrCLpRCiQ1XxkSxNIYuJ/5Aagt0+HlMX78DJMUrNzDULMz0eu2gcprlxJaDtACOw==", + "version": "1.19.23", + "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.23.tgz", + "integrity": "sha512-3Zbk6RzmIpvKTNEHO2RcPOGHM++BQEITMqBRR1Ju32WbruhV/pygYgxiP3xA0b1B88zjzs0Izzjxsbj768+IjA==", "dev": true }, "node_modules/abort-controller": { @@ -1252,9 +1252,9 @@ } }, "node_modules/lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.3.tgz", + "integrity": "sha512-B7gr+F6MkqB3uzINHXNctGieGsRTMwIBgxkp0yq/5BwcuDzD4A8wQpHQW6vDAm1uKSLQghmRdD9sKqf2vJ1cEg==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -2007,9 +2007,9 @@ "dev": true }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "engines": { "node": ">= 10.0.0" @@ -2130,9 +2130,9 @@ } }, "node_modules/yaml": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", - "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "dev": true, "engines": { "node": ">= 14" From 27045bf2c33c1906685742e230841e6fe33e9cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 20 Nov 2023 15:32:38 +0100 Subject: [PATCH 28/30] Generate immutable records in uniffi bindings (#332) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Update the uniffi code generation to output immutable structs. I've pointed the dependencies to my fork until this is included in the main uniffi repo, but it should be enough to let the mobile devs test if the solution is appropiate for them. --- Cargo.lock | 38 ++++++++++++++--------------- Cargo.toml | 12 ++++----- crates/bitwarden-uniffi/Cargo.toml | 4 +-- crates/bitwarden-uniffi/uniffi.toml | 2 ++ crates/bitwarden/Cargo.toml | 2 +- crates/bitwarden/uniffi.toml | 2 ++ crates/uniffi-bindgen/Cargo.toml | 2 +- 7 files changed, 33 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f9fbba7e7..c040eb279 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3457,8 +3457,8 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uniffi" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "anyhow", "camino", @@ -3478,8 +3478,8 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "anyhow", "askama", @@ -3501,8 +3501,8 @@ dependencies = [ [[package]] name = "uniffi_build" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "anyhow", "camino", @@ -3511,8 +3511,8 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "quote", "syn 2.0.39", @@ -3520,8 +3520,8 @@ dependencies = [ [[package]] name = "uniffi_core" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "anyhow", "bytes", @@ -3535,8 +3535,8 @@ dependencies = [ [[package]] name = "uniffi_macros" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "bincode", "camino", @@ -3553,8 +3553,8 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "anyhow", "bytes", @@ -3564,8 +3564,8 @@ dependencies = [ [[package]] name = "uniffi_testing" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "anyhow", "camino", @@ -3576,8 +3576,8 @@ dependencies = [ [[package]] name = "uniffi_udl" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "anyhow", "uniffi_meta", @@ -3784,7 +3784,7 @@ dependencies = [ [[package]] name = "weedle2" version = "4.0.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "nom", ] diff --git a/Cargo.toml b/Cargo.toml index da8805342..c7c2906dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,10 +22,10 @@ codegen-units = 1 # This is fine as long as we don't have any unhandled panics, but let's keep it disabled for now # strip = true -# Using master until 0.25.1 is released to fix https://github.com/mozilla/uniffi-rs/issues/1798 +# Using git dependency temporarily to add support for immutable records in generated code [patch.crates-io] -uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } -uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } -uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } -uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } -uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } +uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } +uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } +uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } +uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } +uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index a7b774c3c..53da0eb8d 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -18,13 +18,13 @@ chrono = { version = ">=0.4.26, <0.5", features = [ "std", ], default-features = false } env_logger = "0.10.0" -uniffi = "=0.25.0" +uniffi = "=0.25.1" schemars = { version = ">=0.8, <0.9", optional = true } bitwarden = { path = "../bitwarden", features = ["mobile", "internal"] } [build-dependencies] -uniffi = { version = "=0.25.0", features = ["build"] } +uniffi = { version = "=0.25.1", features = ["build"] } [target.'cfg(any(target_os = "android", target_os = "ios"))'.dependencies] openssl = { version = "0.10", features = ["vendored"] } diff --git a/crates/bitwarden-uniffi/uniffi.toml b/crates/bitwarden-uniffi/uniffi.toml index 456a3676e..c9cb0899c 100644 --- a/crates/bitwarden-uniffi/uniffi.toml +++ b/crates/bitwarden-uniffi/uniffi.toml @@ -1,7 +1,9 @@ [bindings.kotlin] package_name = "com.bitwarden.sdk" cdylib_name = "bitwarden_uniffi" +generate_immutable_records = true [bindings.swift] ffi_module_name = "BitwardenFFI" module_name = "BitwardenSDK" +generate_immutable_records = true diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 65db9db7d..fea9a2fd7 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -50,7 +50,7 @@ chrono = { version = ">=0.4.26, <0.5", features = [ "serde", "std", ], default-features = false } -uniffi = { version = "=0.25.0", optional = true } +uniffi = { version = "=0.25.1", optional = true } # We don't use this directly (it's used by rand), but we need it here to enable WASM support getrandom = { version = ">=0.2.9", features = ["js"] } diff --git a/crates/bitwarden/uniffi.toml b/crates/bitwarden/uniffi.toml index 5c66e5382..bc4a9d9ec 100644 --- a/crates/bitwarden/uniffi.toml +++ b/crates/bitwarden/uniffi.toml @@ -1,6 +1,8 @@ [bindings.kotlin] package_name = "com.bitwarden.core" +generate_immutable_records = true [bindings.swift] ffi_module_name = "BitwardenCoreFFI" module_name = "BitwardenCore" +generate_immutable_records = true diff --git a/crates/uniffi-bindgen/Cargo.toml b/crates/uniffi-bindgen/Cargo.toml index 980434e89..825f923e3 100644 --- a/crates/uniffi-bindgen/Cargo.toml +++ b/crates/uniffi-bindgen/Cargo.toml @@ -10,4 +10,4 @@ name = "uniffi-bindgen" path = "uniffi-bindgen.rs" [dependencies] -uniffi = { version = "=0.25.0", features = ["cli"] } +uniffi = { version = "=0.25.1", features = ["cli"] } From bebf731307d4a93ef4dba8c80373b3de22be60ca Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 21 Nov 2023 14:03:25 +0100 Subject: [PATCH 29/30] AES tests (#340) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daniel García --- crates/bitwarden/src/crypto/aes_ops.rs | 100 +++++++++++++++++++--- crates/bitwarden/src/crypto/enc_string.rs | 12 ++- crates/bitwarden/src/crypto/master_key.rs | 11 ++- crates/bitwarden/src/crypto/rsa.rs | 4 +- 4 files changed, 110 insertions(+), 17 deletions(-) diff --git a/crates/bitwarden/src/crypto/aes_ops.rs b/crates/bitwarden/src/crypto/aes_ops.rs index 132718349..3deedabd8 100644 --- a/crates/bitwarden/src/crypto/aes_ops.rs +++ b/crates/bitwarden/src/crypto/aes_ops.rs @@ -13,10 +13,9 @@ use aes::cipher::{ BlockEncryptMut, KeyIvInit, }; use hmac::Mac; -use rand::RngCore; use crate::{ - crypto::{EncString, PbkdfSha256Hmac, PBKDF_SHA256_HMAC_OUT_SIZE}, + crypto::{PbkdfSha256Hmac, PBKDF_SHA256_HMAC_OUT_SIZE}, error::{CryptoError, Result}, }; @@ -63,10 +62,11 @@ pub fn decrypt_aes256_hmac( /// /// A AesCbc256_B64 EncString #[allow(unused)] -pub fn encrypt_aes256(data_dec: &[u8], key: GenericArray) -> Result { - let (iv, data) = encrypt_aes256_internal(data_dec, key); +pub fn encrypt_aes256(data_dec: &[u8], key: GenericArray) -> ([u8; 16], Vec) { + let rng = rand::thread_rng(); + let (iv, data) = encrypt_aes256_internal(rng, data_dec, key); - Ok(EncString::AesCbc256_B64 { iv, data }) + (iv, data) } /// Encrypt using AES-256 in CBC mode with MAC. @@ -80,11 +80,12 @@ pub fn encrypt_aes256_hmac( data_dec: &[u8], mac_key: GenericArray, key: GenericArray, -) -> Result { - let (iv, data) = encrypt_aes256_internal(data_dec, key); +) -> Result<([u8; 16], [u8; 32], Vec)> { + let rng = rand::thread_rng(); + let (iv, data) = encrypt_aes256_internal(rng, data_dec, key); let mac = validate_mac(&mac_key, &iv, &data)?; - Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data }) + Ok((iv, mac, data)) } /// Encrypt using AES-256 in CBC mode. @@ -92,9 +93,13 @@ pub fn encrypt_aes256_hmac( /// Used internally by: /// - [encrypt_aes256] /// - [encrypt_aes256_hmac] -fn encrypt_aes256_internal(data_dec: &[u8], key: GenericArray) -> ([u8; 16], Vec) { +fn encrypt_aes256_internal( + mut rng: impl rand::RngCore, + data_dec: &[u8], + key: GenericArray, +) -> ([u8; 16], Vec) { let mut iv = [0u8; 16]; - rand::thread_rng().fill_bytes(&mut iv); + rng.fill_bytes(&mut iv); let data = cbc::Encryptor::::new(&key, &iv.into()) .encrypt_padded_vec_mut::(data_dec); @@ -112,3 +117,78 @@ fn validate_mac(mac_key: &[u8], iv: &[u8], data: &[u8]) -> Result<[u8; 32]> { Ok(mac) } + +#[cfg(test)] +mod tests { + use aes::cipher::generic_array::sequence::GenericSequence; + use base64::Engine; + use rand::SeedableRng; + + use crate::util::BASE64_ENGINE; + + use super::*; + + /// Helper function for generating a `GenericArray` of size 32 with each element being + /// a multiple of a given increment, starting from a given offset. + fn generate_generic_array(offset: u8, increment: u8) -> GenericArray { + GenericArray::generate(|i| offset + i as u8 * increment) + } + + /// Helper function for generating a vector of a given size with each element being + /// a multiple of a given increment, starting from a given offset. + fn generate_vec(length: usize, offset: u8, increment: u8) -> Vec { + (0..length).map(|i| offset + i as u8 * increment).collect() + } + + #[test] + fn test_encrypt_aes256_internal() { + let key = generate_generic_array(0, 1); + + let rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + let result = encrypt_aes256_internal(rng, "EncryptMe!".as_bytes(), key); + assert_eq!( + result, + ( + [62, 0, 239, 47, 137, 95, 64, 214, 127, 91, 184, 232, 31, 9, 165, 161], + vec![214, 76, 187, 97, 58, 146, 212, 140, 95, 164, 177, 204, 179, 133, 172, 148] + ) + ); + } + + #[test] + fn test_validate_mac() { + let mac_key = generate_vec(16, 0, 16); + + let iv = generate_vec(16, 0, 16); + let data = generate_vec(16, 0, 16); + + let result = validate_mac(&mac_key, &iv, &data); + + assert!(result.is_ok()); + let mac = result.unwrap(); + assert_eq!(mac.len(), 32); + } + + #[test] + fn test_decrypt_aes256() { + let iv = generate_vec(16, 0, 1); + let iv: &[u8; 16] = iv.as_slice().try_into().unwrap(); + let key = generate_generic_array(0, 1); + let data = BASE64_ENGINE.decode("ByUF8vhyX4ddU9gcooznwA==").unwrap(); + + let decrypted = decrypt_aes256(iv, data, key).unwrap(); + + assert_eq!(String::from_utf8(decrypted).unwrap(), "EncryptMe!"); + } + + #[test] + fn test_encrypt_decrypt_aes256() { + let key = generate_generic_array(0, 1); + let data = "EncryptMe!"; + + let (iv, encrypted) = encrypt_aes256(data.as_bytes(), key); + let decrypted = decrypt_aes256(&iv, encrypted, key).unwrap(); + + assert_eq!(String::from_utf8(decrypted).unwrap(), "EncryptMe!"); + } +} diff --git a/crates/bitwarden/src/crypto/enc_string.rs b/crates/bitwarden/src/crypto/enc_string.rs index ac7f3fc6b..09f877c50 100644 --- a/crates/bitwarden/src/crypto/enc_string.rs +++ b/crates/bitwarden/src/crypto/enc_string.rs @@ -1,5 +1,6 @@ use std::{fmt::Display, str::FromStr}; +use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::Engine; use serde::{de::Visitor, Deserialize}; @@ -331,6 +332,15 @@ impl serde::Serialize for EncString { } impl EncString { + pub(crate) fn encrypt_aes256_hmac( + data_dec: &[u8], + mac_key: GenericArray, + key: GenericArray, + ) -> Result { + let (iv, mac, data) = super::encrypt_aes256_hmac(data_dec, mac_key, key)?; + Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data }) + } + /// The numerical representation of the encryption type of the [EncString]. const fn enc_type(&self) -> u8 { match self { @@ -357,7 +367,7 @@ fn invalid_len_error(expected: usize) -> impl Fn(Vec) -> EncStringParseError impl LocateKey for EncString {} impl KeyEncryptable for &[u8] { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { - super::encrypt_aes256_hmac(self, key.mac_key.ok_or(CryptoError::InvalidMac)?, key.key) + EncString::encrypt_aes256_hmac(self, key.mac_key.ok_or(CryptoError::InvalidMac)?, key.key) } } diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden/src/crypto/master_key.rs index b2c8e6e5f..fdcf93dde 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden/src/crypto/master_key.rs @@ -4,8 +4,8 @@ use rand::Rng; use sha2::Digest; use super::{ - encrypt_aes256_hmac, hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, - SymmetricCryptoKey, UserKey, PBKDF_SHA256_HMAC_OUT_SIZE, + hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, SymmetricCryptoKey, UserKey, + PBKDF_SHA256_HMAC_OUT_SIZE, }; use crate::{client::kdf::Kdf, error::Result, util::BASE64_ENGINE}; @@ -61,8 +61,11 @@ fn make_user_key( rng.fill(&mut user_key); let stretched_key = stretch_master_key(master_key)?; - let protected = - encrypt_aes256_hmac(&user_key, stretched_key.mac_key.unwrap(), stretched_key.key)?; + let protected = EncString::encrypt_aes256_hmac( + &user_key, + stretched_key.mac_key.unwrap(), + stretched_key.key, + )?; let u: &[u8] = &user_key; Ok((UserKey::new(SymmetricCryptoKey::try_from(u)?), protected)) diff --git a/crates/bitwarden/src/crypto/rsa.rs b/crates/bitwarden/src/crypto/rsa.rs index 0d2d135b9..f105dbfe2 100644 --- a/crates/bitwarden/src/crypto/rsa.rs +++ b/crates/bitwarden/src/crypto/rsa.rs @@ -5,7 +5,7 @@ use rsa::{ }; use crate::{ - crypto::{encrypt_aes256_hmac, EncString, SymmetricCryptoKey}, + crypto::{EncString, SymmetricCryptoKey}, error::{Error, Result}, util::BASE64_ENGINE, }; @@ -33,7 +33,7 @@ pub(super) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { .to_pkcs8_der() .map_err(|_| Error::Internal("unable to create private key"))?; - let protected = encrypt_aes256_hmac(pkcs.as_bytes(), key.mac_key.unwrap(), key.key)?; + let protected = EncString::encrypt_aes256_hmac(pkcs.as_bytes(), key.mac_key.unwrap(), key.key)?; Ok(RsaKeyPair { public: b64, From 24f0dfdbb09dbc5ff0ca879b89948d7be7d7ae1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 23 Nov 2023 12:49:46 +0100 Subject: [PATCH 30/30] [PM-4695] Implement unlock with user key and update examples to use biometrics (#330) ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Enable the SDK to export the decrypted user key and expose a way to initialize the SDK with it. The Android and iOS examples have been revamped to allow choosing how to unlock the client. Some small notes: - The iOS example is directly storing the user key in a biometric protected keychain, while that doesn't seem possible in Android. Instead, we generate a key in the secure keystore and use it to encrypt/decrypt the user key. - The iOS example biometrics don't seem to work on the simulator and require a real device for testing. This depends on the refactor done on #329 --- crates/bitwarden-uniffi/src/crypto.rs | 13 + crates/bitwarden/src/client/client.rs | 17 + .../src/client/encryption_settings.rs | 38 +- crates/bitwarden/src/mobile/client_crypto.rs | 8 +- crates/bitwarden/src/mobile/crypto.rs | 24 +- languages/kotlin/app/build.gradle | 1 + .../com/bitwarden/myapplication/Biometrics.kt | 132 ++++++ .../bitwarden/myapplication/MainActivity.kt | 369 +++++++++++----- languages/kotlin/doc.md | 32 ++ .../swift/iOS/App.xcodeproj/project.pbxproj | 12 +- languages/swift/iOS/App/Biometrics.swift | 92 ++++ languages/swift/iOS/App/ContentView.swift | 405 +++++++++++------- 12 files changed, 848 insertions(+), 295 deletions(-) create mode 100644 languages/kotlin/app/src/main/java/com/bitwarden/myapplication/Biometrics.kt create mode 100644 languages/swift/iOS/App/Biometrics.swift diff --git a/crates/bitwarden-uniffi/src/crypto.rs b/crates/bitwarden-uniffi/src/crypto.rs index 1792a5bbc..804202e2f 100644 --- a/crates/bitwarden-uniffi/src/crypto.rs +++ b/crates/bitwarden-uniffi/src/crypto.rs @@ -32,4 +32,17 @@ impl ClientCrypto { .initialize_org_crypto(req) .await?) } + + /// Get the uses's decrypted encryption key. Note: It's very important + /// to keep this key safe, as it can be used to decrypt all of the user's data + pub async fn get_user_encryption_key(&self) -> Result { + Ok(self + .0 + .0 + .write() + .await + .crypto() + .get_user_encryption_key() + .await?) + } } diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 213a12fb2..960ca9bda 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -222,6 +222,23 @@ impl Client { Ok(self.encryption_settings.as_ref().unwrap()) } + #[cfg(feature = "mobile")] + pub(crate) fn initialize_user_crypto_decrypted_key( + &mut self, + decrypted_user_key: &str, + private_key: EncString, + ) -> Result<&EncryptionSettings> { + let user_key = decrypted_user_key.parse::()?; + self.encryption_settings = Some(EncryptionSettings::new_decrypted_key( + user_key, + private_key, + )?); + Ok(self + .encryption_settings + .as_ref() + .expect("It was initialized on the previous line")) + } + pub(crate) fn initialize_crypto_single_key( &mut self, key: SymmetricCryptoKey, diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index 6533c7d2e..7c16725e7 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -27,6 +27,7 @@ impl std::fmt::Debug for EncryptionSettings { } impl EncryptionSettings { + /// Initialize the encryption settings with the user password and their encrypted keys #[cfg(feature = "internal")] pub(crate) fn new( login_method: &UserLoginMethod, @@ -45,24 +46,33 @@ impl EncryptionSettings { // Decrypt the user key let user_key = master_key.decrypt_user_key(user_key)?; - // Decrypt the private key with the user key - let private_key = { - let dec: Vec = private_key.decrypt_with_key(&user_key)?; - Some( - rsa::RsaPrivateKey::from_pkcs8_der(&dec) - .map_err(|_| CryptoError::InvalidKey)?, - ) - }; - - Ok(EncryptionSettings { - user_key, - private_key, - org_keys: HashMap::new(), - }) + Self::new_decrypted_key(user_key, private_key) } } } + /// Initialize the encryption settings with the decrypted user key and the encrypted user private key + /// This should only be used when unlocking the vault via biometrics or when the vault is set to lock: "never" + /// Otherwise handling the decrypted user key is dangerous and discouraged + #[cfg(feature = "internal")] + pub(crate) fn new_decrypted_key( + user_key: SymmetricCryptoKey, + private_key: EncString, + ) -> Result { + let private_key = { + let dec: Vec = private_key.decrypt_with_key(&user_key)?; + Some(rsa::RsaPrivateKey::from_pkcs8_der(&dec).map_err(|_| CryptoError::InvalidKey)?) + }; + + Ok(EncryptionSettings { + user_key, + private_key, + org_keys: HashMap::new(), + }) + } + + /// Initialize the encryption settings with only a single decrypted key. + /// This is used only for logging in Secrets Manager with an access token pub(crate) fn new_single_key(key: SymmetricCryptoKey) -> Self { EncryptionSettings { user_key: key, diff --git a/crates/bitwarden/src/mobile/client_crypto.rs b/crates/bitwarden/src/mobile/client_crypto.rs index c0edb1982..118e02726 100644 --- a/crates/bitwarden/src/mobile/client_crypto.rs +++ b/crates/bitwarden/src/mobile/client_crypto.rs @@ -3,7 +3,8 @@ use crate::Client; use crate::{ error::Result, mobile::crypto::{ - initialize_org_crypto, initialize_user_crypto, InitOrgCryptoRequest, InitUserCryptoRequest, + get_user_encryption_key, initialize_org_crypto, initialize_user_crypto, + InitOrgCryptoRequest, InitUserCryptoRequest, }, }; @@ -21,6 +22,11 @@ impl<'a> ClientCrypto<'a> { pub async fn initialize_org_crypto(&mut self, req: InitOrgCryptoRequest) -> Result<()> { initialize_org_crypto(self.client, req).await } + + #[cfg(feature = "internal")] + pub async fn get_user_encryption_key(&mut self) -> Result { + get_user_encryption_key(self.client).await + } } impl<'a> Client { diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index 2cf850279..9c2c8478f 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -3,7 +3,12 @@ use std::collections::HashMap; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{client::kdf::Kdf, crypto::EncString, error::Result, Client}; +use crate::{ + client::kdf::Kdf, + crypto::EncString, + error::{Error, Result}, + Client, +}; #[cfg(feature = "internal")] #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -31,6 +36,10 @@ pub enum InitUserCryptoMethod { /// The user's encrypted symmetric crypto key user_key: String, }, + DecryptedKey { + /// The user's decrypted encryption key, obtained using `get_user_encryption_key` + decrypted_user_key: String, + }, } #[cfg(feature = "internal")] @@ -49,6 +58,9 @@ pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequ let user_key: EncString = user_key.parse()?; client.initialize_user_crypto(&password, user_key, private_key)?; } + InitUserCryptoMethod::DecryptedKey { decrypted_user_key } => { + client.initialize_user_crypto_decrypted_key(&decrypted_user_key, private_key)?; + } } Ok(()) @@ -69,3 +81,13 @@ pub async fn initialize_org_crypto(client: &mut Client, req: InitOrgCryptoReques client.initialize_org_crypto(organization_keys)?; Ok(()) } + +#[cfg(feature = "internal")] +pub async fn get_user_encryption_key(client: &mut Client) -> Result { + let user_key = client + .get_encryption_settings()? + .get_key(&None) + .ok_or(Error::VaultLocked)?; + + Ok(user_key.to_base64()) +} diff --git a/languages/kotlin/app/build.gradle b/languages/kotlin/app/build.gradle index 709e32889..ef42d43bb 100644 --- a/languages/kotlin/app/build.gradle +++ b/languages/kotlin/app/build.gradle @@ -60,6 +60,7 @@ dependencies { implementation 'androidx.compose.ui:ui-graphics' implementation 'androidx.compose.ui:ui-tooling-preview' implementation 'androidx.compose.material3:material3' + implementation "androidx.biometric:biometric:1.1.0" implementation "io.ktor:ktor-client-core:2.3.3" implementation "io.ktor:ktor-client-cio:2.3.3" implementation "io.ktor:ktor-client-content-negotiation:2.3.3" diff --git a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/Biometrics.kt b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/Biometrics.kt new file mode 100644 index 000000000..8f8115e8d --- /dev/null +++ b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/Biometrics.kt @@ -0,0 +1,132 @@ +package com.bitwarden.myapplication + +import android.os.Build +import android.security.keystore.KeyGenParameterSpec +import android.security.keystore.KeyProperties +import android.util.Log +import androidx.biometric.BiometricManager +import androidx.biometric.BiometricManager.Authenticators +import androidx.biometric.BiometricPrompt +import androidx.biometric.BiometricPrompt.CryptoObject +import androidx.core.content.ContextCompat +import androidx.fragment.app.FragmentActivity +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import java.security.KeyStore +import java.util.Base64 +import javax.crypto.Cipher +import javax.crypto.KeyGenerator +import javax.crypto.SecretKey +import javax.crypto.spec.GCMParameterSpec + +/** + * IMPORTANT: This file is provided only for the purpose of demostrating the use of the biometric unlock functionality. + * It hasn't gone through a throrough security review and should not be considered production ready. It also doesn't + * handle a lot of errors and edge cases that a production application would need to deal with. + * Developers are encouraged to review and improve the code as needed to meet their security requirements. + * Additionally, we recommend to consult with security experts and conduct thorough testing before using the code in production. + */ + +class Biometric(private var activity: FragmentActivity) { + private var promptInfo: BiometricPrompt.PromptInfo = + BiometricPrompt.PromptInfo.Builder().setTitle("Unlock") + .setSubtitle("Bitwarden biometric unlock") + .setDescription("Confirm biometric to continue").setConfirmationRequired(true) + .setNegativeButtonText("Use account password").build() + + suspend fun encryptString( + keyName: String, plaintext: String, callback: (String, String) -> Unit + ) { + if (canAuthenticate()) { + val cipher = getCipher() + cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(keyName)) + + val bio = createBiometricPrompt { + val ciphertext = it.cipher!!.doFinal(plaintext.toByteArray()) + callback( + String(Base64.getEncoder().encode(ciphertext)), + String(Base64.getEncoder().encode(cipher.iv)) + ) + } + CoroutineScope(Dispatchers.Main).async { + bio.authenticate(promptInfo, CryptoObject(cipher)) + }.await() + } + } + + suspend fun decryptString( + keyName: String, encrypted: String, initializationVector: String, callback: (String) -> Unit + ) { + if (canAuthenticate()) { + val enc = Base64.getDecoder().decode(encrypted) + val iv = Base64.getDecoder().decode(initializationVector) + + val cipher = getCipher() + cipher.init(Cipher.DECRYPT_MODE, getSecretKey(keyName), GCMParameterSpec(128, iv)) + + val bio = createBiometricPrompt { + callback(String(it.cipher!!.doFinal(enc))) + } + + CoroutineScope(Dispatchers.Main).async { + bio.authenticate(promptInfo, CryptoObject(cipher)) + }.await() + } + } + + private fun canAuthenticate() = BiometricManager.from(activity) + .canAuthenticate(Authenticators.BIOMETRIC_STRONG) == BiometricManager.BIOMETRIC_SUCCESS + + private fun createBiometricPrompt(processData: (CryptoObject) -> Unit): BiometricPrompt { + return BiometricPrompt(activity, + ContextCompat.getMainExecutor(activity), + object : BiometricPrompt.AuthenticationCallback() { + override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { + super.onAuthenticationError(errorCode, errString) + Log.e("Biometric", "$errorCode :: $errString") + } + + override fun onAuthenticationFailed() { + super.onAuthenticationFailed() + Log.e("Biometric", "Authentication failed for an unknown reason") + } + + override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { + super.onAuthenticationSucceeded(result) + processData(result.cryptoObject!!) + } + }) + } + + private fun getCipher(): Cipher { + val transform = + "${KeyProperties.KEY_ALGORITHM_AES}/${KeyProperties.BLOCK_MODE_GCM}/${KeyProperties.ENCRYPTION_PADDING_NONE}" + return Cipher.getInstance(transform) + } + + private fun getSecretKey(keyName: String): SecretKey { + // If the SecretKey exists, return it + val keyStore = KeyStore.getInstance("AndroidKeyStore") + keyStore.load(null) + keyStore.getKey(keyName, null)?.let { return it as SecretKey } + + // Otherwise, we generate a new one + val keyGenParams = KeyGenParameterSpec.Builder( + keyName, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT + ).apply { + setBlockModes(KeyProperties.BLOCK_MODE_GCM) + setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) + setKeySize(256) + setUserAuthenticationRequired(true) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG) + } + }.build() + + val keyGenerator = + KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore") + keyGenerator.init(keyGenParams) + return keyGenerator.generateKey() + } +} diff --git a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt index 13dec7d0e..3c03c6bca 100644 --- a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt +++ b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt @@ -1,15 +1,27 @@ package com.bitwarden.myapplication +import android.content.Context import android.os.Bundle -import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.Checkbox +import androidx.compose.material3.Divider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text -import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.fragment.app.FragmentActivity import com.bitwarden.core.DateTime import com.bitwarden.core.Folder import com.bitwarden.core.InitOrgCryptoRequest @@ -44,151 +56,272 @@ import java.security.cert.X509Certificate import java.util.Base64 import javax.net.ssl.X509TrustManager -class MainActivity : ComponentActivity() { +/** + * IMPORTANT: This file is provided only for the purpose of demostrating the use of the SDK functionality. + * It hasn't gone through a throrough security review and should not be considered production ready. It also doesn't + * handle a lot of errors and edge cases that a production application would need to deal with. + * Developers are encouraged to review and improve the code as needed to meet their security requirements. + * Additionally, we recommend to consult with security experts and conduct thorough testing before using the code in production. + */ + +const val SERVER_URL = "https://10.0.2.2:8080/" +const val API_URL = SERVER_URL + "api/" +const val IDENTITY_URL = SERVER_URL + "identity/" + +const val EMAIL = "test@bitwarden.com" +const val PASSWORD = "asdfasdfasdf" + +// We should separate keys for each user by appending the user_id +const val BIOMETRIC_KEY = "biometric_key" + +class MainActivity : FragmentActivity() { + private lateinit var biometric: Biometric + private lateinit var client: Client + private lateinit var http: HttpClient + + private var accessToken = "" + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + biometric = Biometric(this) + client = Client(null) + http = httpClient() + + setContent { + MyApplicationTheme { + // A surface container using the 'background' color from the theme + Surface( + modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally + ) { - val SERVER_URL = "https://10.0.2.2:8080/" - val API_URL = SERVER_URL + "api/" - val IDENTITY_URL = SERVER_URL + "identity/" + val setupBiometrics = remember { mutableStateOf(true) } + val outputText = remember { mutableStateOf("") } - val EMAIL = "test@bitwarden.com" - val PASSWORD = "asdfasdfasdf" + Row { + Checkbox(checked = setupBiometrics.value, + onCheckedChange = { isChecked -> + setupBiometrics.value = isChecked + }) + Text( + "Setup biometric unlock after login", + modifier = Modifier.align(CenterVertically) + ) + } - GlobalScope.launch { - var client = Client(null) - val http = httpClient() + Button({ + GlobalScope.launch { + clientExamplePassword( + client, http, outputText, setupBiometrics.value + ) + } + }) { + Text("Login with username + password") + } - ///////////////////////////// Get master password hash ///////////////////////////// - @Serializable - data class PreloginRequest(val email: String) + Divider( + color = Color.Black, + thickness = 1.dp, + modifier = Modifier.padding(30.dp) + ) - @Serializable - data class PreloginResponse( - val kdf: UInt, - val kdfIterations: UInt, - val kdfMemory: UInt?, - val kdfParallelism: UInt? - ) + Button({ + GlobalScope.launch { + clientExampleBiometrics(client, http, outputText) + } + }) { + Text("Unlock with biometrics") + } - val prelogin_body = http.post(IDENTITY_URL + "accounts/prelogin") { - contentType(ContentType.Application.Json) - setBody(PreloginRequest(EMAIL)) - }.body() - val kdf = if (prelogin_body.kdf == 0u) { - Kdf.Pbkdf2(prelogin_body.kdfIterations) - } else { - Kdf.Argon2id( - prelogin_body.kdfIterations, - prelogin_body.kdfMemory!!, - prelogin_body.kdfParallelism!! - ) + Button({ + GlobalScope.launch { + client.destroy() + client = Client(null) + outputText.value = "OK" + } + }) { + Text("Lock & reset client") + } + + Text( + "Output: " + outputText.value, + modifier = Modifier.padding(vertical = 10.dp) + ) + } + } } - val masterPasswordHash = client.auth().hashPassword(EMAIL, PASSWORD, kdf) + } + } + + private suspend fun clientExamplePassword( + client: Client, http: HttpClient, outputText: MutableState, setupBiometrics: Boolean + ) { + println("### Logging in with username and password ###") + ///////////////////////////// Get master password hash ///////////////////////////// + @Serializable + data class PreloginRequest(val email: String) - ///////////////////////////// Login ///////////////////////////// + @Serializable + data class PreloginResponse( + val kdf: UInt, val kdfIterations: UInt, val kdfMemory: UInt?, val kdfParallelism: UInt? + ) - @Serializable - data class LoginResponse( - val Key: String, - val PrivateKey: String, - val access_token: String, - val refresh_token: String, + val prelogin_body = http.post(IDENTITY_URL + "accounts/prelogin") { + contentType(ContentType.Application.Json) + setBody(PreloginRequest(EMAIL)) + }.body() + val kdf = if (prelogin_body.kdf == 0u) { + Kdf.Pbkdf2(prelogin_body.kdfIterations) + } else { + Kdf.Argon2id( + prelogin_body.kdfIterations, + prelogin_body.kdfMemory!!, + prelogin_body.kdfParallelism!! ) + } + val masterPasswordHash = client.auth().hashPassword(EMAIL, PASSWORD, kdf) - val loginBody = http.post(IDENTITY_URL + "connect/token") { - contentType(ContentType.Application.Json) - header("Auth-Email", Base64.getEncoder().encodeToString(EMAIL.toByteArray())) - setBody(FormDataContent(Parameters.build { - append("scope", "api offline_access") - append("client_id", "web") - append("deviceType", "12") - append("deviceIdentifier", "0745d426-8dab-484a-9816-4959721d77c7") - append("deviceName", "edge") - - append("grant_type", "password") - append("username", EMAIL) - append("password", masterPasswordHash) - })) - }.body() - - ///////////////////////////// Sync ///////////////////////////// - - val syncBody = http.get(API_URL + "sync?excludeDomains=true") { - bearerAuth(loginBody.access_token) - }.body() - - val folders = (syncBody["folders"] as JsonArray).map { - val o = it as JsonObject - Folder( - (o["id"] as JsonPrimitive).content, - (o["name"] as JsonPrimitive).content, - DateTime.parse( - (o["revisionDate"] as JsonPrimitive).content - ) - ) - } + ///////////////////////////// Login ///////////////////////////// - ///////////////////////////// Initialize crypto ///////////////////////////// - val orgs = ((syncBody["profile"] as JsonObject)["organizations"]) as JsonArray - val orgKeys = HashMap() + @Serializable + data class LoginResponse( + val Key: String, + val PrivateKey: String, + val access_token: String, + val refresh_token: String, + ) - for (org in orgs) { - val o = org as JsonObject - orgKeys[(o["id"] as JsonPrimitive).content] = (o["key"] as JsonPrimitive).content - } + val loginBody = http.post(IDENTITY_URL + "connect/token") { + contentType(ContentType.Application.Json) + header("Auth-Email", Base64.getEncoder().encodeToString(EMAIL.toByteArray())) + setBody(FormDataContent(Parameters.build { + append("scope", "api offline_access") + append("client_id", "web") + append("deviceType", "12") + append("deviceIdentifier", "0745d426-8dab-484a-9816-4959721d77c7") + append("deviceName", "edge") - client.crypto().initializeUserCrypto( - InitUserCryptoRequest( - kdfParams = kdf, - email = EMAIL, - privateKey = loginBody.PrivateKey, - method = InitUserCryptoMethod.Password( - password = PASSWORD, - userKey = loginBody.Key - ) - ) - ) + append("grant_type", "password") + append("username", EMAIL) + append("password", masterPasswordHash) + })) + }.body() - client.crypto().initializeOrgCrypto( - InitOrgCryptoRequest( - organizationKeys = orgKeys + client.crypto().initializeUserCrypto( + InitUserCryptoRequest( + kdfParams = kdf, + email = EMAIL, + privateKey = loginBody.PrivateKey, + method = InitUserCryptoMethod.Password( + password = PASSWORD, userKey = loginBody.Key ) ) + ) - ///////////////////////////// Decrypt some folders ///////////////////////////// + accessToken = loginBody.access_token - val decryptedFolders = client.vault().folders().decryptList(folders) + decryptVault(client, http, outputText) - println(decryptedFolders) + if (setupBiometrics) { + // Save values for future logins + val sharedPref = getPreferences(Context.MODE_PRIVATE) + with(sharedPref.edit()) { + putString("accessToken", accessToken) + putString("privateKey", loginBody.PrivateKey) - } + putInt("kdfType", prelogin_body.kdf.toInt()) + putInt("kdfIterations", prelogin_body.kdfIterations.toInt()) + putInt("kdfMemory", (prelogin_body.kdfMemory ?: 0u).toInt()) + putInt("kdfParallelism", (prelogin_body.kdfParallelism ?: 0u).toInt()) - setContent { - MyApplicationTheme { - // A surface container using the 'background' color from the theme - Surface( - modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background - ) { - Greeting("Hey") + // TODO: This should be protected by Android's secure KeyStore + val decryptedKey = client.crypto().getUserEncryptionKey() + + biometric.encryptString(BIOMETRIC_KEY, decryptedKey) { key, iv -> + putString("encryptedUserKey", key) + putString("encryptedUserKeyIv", iv) + apply() } } } } -} -@Composable -fun Greeting(name: String, modifier: Modifier = Modifier) { - Text( - text = "Hello $name!", modifier = modifier - ) -} + private suspend fun clientExampleBiometrics( + client: Client, http: HttpClient, outputText: MutableState + ) { + println("### Unlocking with Biometrics ###") + + val pref = getPreferences(Context.MODE_PRIVATE) + accessToken = pref.getString("accessToken", "").orEmpty() + val privateKey = pref.getString("privateKey", "") + + val kdf = if (pref.getInt("kdfType", 0) == 0) { + Kdf.Pbkdf2(pref.getInt("kdfIterations", 0).toUInt()) + } else { + Kdf.Argon2id( + pref.getInt("kdfIterations", 0).toUInt(), + pref.getInt("kdfMemory", 0).toUInt(), + pref.getInt("kdfParallelism", 0).toUInt() + ) + } + + val encryptedUserKey = pref.getString("encryptedUserKey", "")!! + val encryptedUserKeyIv = pref.getString("encryptedUserKeyIv", "")!! + + biometric.decryptString( + BIOMETRIC_KEY, encryptedUserKey, encryptedUserKeyIv + ) { key -> + GlobalScope.launch { + client.crypto().initializeUserCrypto( + InitUserCryptoRequest( + kdfParams = kdf, + email = EMAIL, + privateKey = privateKey!!, + method = InitUserCryptoMethod.DecryptedKey(decryptedUserKey = key) + ) + ) + + decryptVault(client, http, outputText) + } + } + } + + suspend fun decryptVault(client: Client, http: HttpClient, outputText: MutableState) { + ///////////////////////////// Sync ///////////////////////////// + + val syncBody = http.get(API_URL + "sync?excludeDomains=true") { + bearerAuth(accessToken) + }.body() + + val folders = (syncBody["folders"] as JsonArray).map { + val o = it as JsonObject + Folder( + (o["id"] as JsonPrimitive).content, + (o["name"] as JsonPrimitive).content, + DateTime.parse( + (o["revisionDate"] as JsonPrimitive).content + ) + ) + } + + ///////////////////////////// Initialize org crypto ///////////////////////////// + val orgs = ((syncBody["profile"] as JsonObject)["organizations"]) as JsonArray + val orgKeys = HashMap() + + for (org in orgs) { + val o = org as JsonObject + orgKeys[(o["id"] as JsonPrimitive).content] = (o["key"] as JsonPrimitive).content + } + + client.crypto().initializeOrgCrypto(InitOrgCryptoRequest(organizationKeys = orgKeys)) + + ///////////////////////////// Decrypt some folders ///////////////////////////// -@Preview(showBackground = true) -@Composable -fun GreetingPreview() { - MyApplicationTheme { - Greeting("Sdk") + val decryptedFolders = client.vault().folders().decryptList(folders) + outputText.value = decryptedFolders.toString() + println(decryptedFolders) } } diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index 70446bd8f..fd65c7b71 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -205,6 +205,17 @@ Initialization method for the organization crypto. Needs to be called after **Output**: std::result::Result<,BitwardenError> +### `get_user_encryption_key` + +Get the uses's decrypted encryption key. Note: It's very important to keep this key safe, +as it can be used to decrypt all of the user's data + +**Arguments**: + +- self: + +**Output**: std::result::Result + ## ClientExporters ### `export_vault` @@ -906,6 +917,27 @@ implementations. + + decryptedKey + object + + + + + + + + + + + + + + + +
KeyTypeDescription
decrypted_user_keystringThe user's decrypted encryption key, obtained using `get_user_encryption_key`
+ + ## `InitUserCryptoRequest` diff --git a/languages/swift/iOS/App.xcodeproj/project.pbxproj b/languages/swift/iOS/App.xcodeproj/project.pbxproj index 003c09c0d..e8b3519fd 100644 --- a/languages/swift/iOS/App.xcodeproj/project.pbxproj +++ b/languages/swift/iOS/App.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 33F2B0502B0511C700E1E91C /* Biometrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33F2B04F2B0511C700E1E91C /* Biometrics.swift */; }; 55B6153E2A8678B300BE93F4 /* testApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B6153D2A8678B300BE93F4 /* testApp.swift */; }; 55B615402A8678B300BE93F4 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B6153F2A8678B300BE93F4 /* ContentView.swift */; }; 55B615422A8678B400BE93F4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 55B615412A8678B400BE93F4 /* Assets.xcassets */; }; @@ -15,6 +16,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 33F2B04F2B0511C700E1E91C /* Biometrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Biometrics.swift; sourceTree = ""; }; 55B6153A2A8678B300BE93F4 /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; }; 55B6153D2A8678B300BE93F4 /* testApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = testApp.swift; sourceTree = ""; }; 55B6153F2A8678B300BE93F4 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -60,6 +62,7 @@ 55B6153F2A8678B300BE93F4 /* ContentView.swift */, 55B615412A8678B400BE93F4 /* Assets.xcassets */, 55B615432A8678B400BE93F4 /* Preview Content */, + 33F2B04F2B0511C700E1E91C /* Biometrics.swift */, ); path = App; sourceTree = ""; @@ -118,7 +121,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1420; - LastUpgradeCheck = 1420; + LastUpgradeCheck = 1500; TargetAttributes = { 55B615392A8678B300BE93F4 = { CreatedOnToolsVersion = 14.2; @@ -160,6 +163,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 33F2B0502B0511C700E1E91C /* Biometrics.swift in Sources */, 55B615402A8678B300BE93F4 /* ContentView.swift in Sources */, 55B6153E2A8678B300BE93F4 /* testApp.swift in Sources */, ); @@ -172,6 +176,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -204,6 +209,7 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -232,6 +238,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -264,6 +271,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -293,6 +301,7 @@ DEVELOPMENT_TEAM = LTZ2PFU5D6; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSFaceIDUsageDescription = "Unlock vault with biometrics"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; @@ -323,6 +332,7 @@ DEVELOPMENT_TEAM = LTZ2PFU5D6; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSFaceIDUsageDescription = "Unlock vault with biometrics"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; diff --git a/languages/swift/iOS/App/Biometrics.swift b/languages/swift/iOS/App/Biometrics.swift new file mode 100644 index 000000000..2fc5ef2a3 --- /dev/null +++ b/languages/swift/iOS/App/Biometrics.swift @@ -0,0 +1,92 @@ +// +// Biometrics.swift +// App +// +// Created by Dani on 15/11/23. +// + +/** + * IMPORTANT: This file is provided only for the purpose of demostrating the use of the biometric unlock functionality. + * It hasn't gone through a throrough security review and should not be considered production ready. It also doesn't + * handle a lot of errors and edge cases that a production application would need to deal with. + * Developers are encouraged to review and improve the code as needed to meet their security requirements. + * Additionally, we recommend to consult with security experts and conduct thorough testing before using the code in production. + */ + +import Foundation +import LocalAuthentication + +let SERVICE: String = "com.example.app" + +// We should separate keys for each user by appending the user_id +let KEY: String = "biometric_key" + + +func biometricStoreValue(value: String) { + var error: Unmanaged? + let accessControl = SecAccessControlCreateWithFlags( + nil, + kSecAttrAccessibleWhenUnlockedThisDeviceOnly, + .biometryCurrentSet, + &error) + + guard accessControl != nil && error == nil else { + fatalError("SecAccessControlCreateWithFlags failed") + } + + let query = [ + kSecClass: kSecClassGenericPassword, + kSecAttrService: SERVICE, + kSecAttrAccount: KEY, + kSecValueData: value.data(using: .utf8)!, + kSecAttrAccessControl: accessControl as Any + ] as CFDictionary + + // Try to delete the previous secret, if it exists + // Otherwise we get `errSecDuplicateItem` + SecItemDelete(query) + + let status = SecItemAdd(query, nil) + guard status == errSecSuccess else { + fatalError("Unable to store the secret: " + errToString(status: status)) + } +} + +private func errToString(status: OSStatus) -> String { + if let err = SecCopyErrorMessageString(status, nil) as String? { + err + } else { + "Unknown error" + } +} + +func biometricRetrieveValue() -> String? { + let searchQuery = [ + kSecClass: kSecClassGenericPassword, + kSecAttrService: SERVICE, + kSecAttrAccount: KEY, + kSecMatchLimit: kSecMatchLimitOne, + kSecReturnData: true, + kSecReturnAttributes: true, + ] as CFDictionary + + var item: AnyObject? + let status = SecItemCopyMatching(searchQuery, &item) + + // If the item is not found, we just return nil + if status == errSecItemNotFound { + return nil + } + + // TODO: We probably want to handle these errors better + guard status == noErr else { + fatalError("Unable to retrieve the secret: " + errToString(status: status)) + } + + if let resultDictionary = item as? [String: Any], + let data = resultDictionary[kSecValueData as String] as? Data { + return String(decoding: data, as: UTF8.self) + } + + return nil +} diff --git a/languages/swift/iOS/App/ContentView.swift b/languages/swift/iOS/App/ContentView.swift index 484caf14f..5df7dc3fd 100644 --- a/languages/swift/iOS/App/ContentView.swift +++ b/languages/swift/iOS/App/ContentView.swift @@ -8,176 +8,261 @@ import BitwardenSdk import SwiftUI -struct ContentView: View { - - @State private var msg: String - - init() { - let client = Client(settings: nil) +/** + * IMPORTANT: This file is provided only for the purpose of demostrating the use of the SDK functionality. + * It hasn't gone through a throrough security review and should not be considered production ready. It also doesn't + * handle a lot of errors and edge cases that a production application would need to deal with. + * Developers are encouraged to review and improve the code as needed to meet their security requirements. + * Additionally, we recommend to consult with security experts and conduct thorough testing before using the code in production. + */ - _msg = State(initialValue: client.echo(msg: "Sdk")) +let SERVER_URL = "https://localhost:8080/" +let API_URL = SERVER_URL + "api/" +let IDENTITY_URL = SERVER_URL + "identity/" - let SERVER_URL = "https://localhost:8080/" - let API_URL = SERVER_URL + "api/" - let IDENTITY_URL = SERVER_URL + "identity/" - - let EMAIL = "test@bitwarden.com" - let PASSWORD = "asdfasdfasdf" +let EMAIL = "test@bitwarden.com" +let PASSWORD = "asdfasdfasdf" +struct ContentView: View { + private var http: URLSession + + @State private var client: Client + + @State private var accessToken: String = "" + + init() { // Disable SSL Cert validation. Don't do this in production - let ignoreHttpsDelegate = IgnoreHttpsDelegate() - let http = URLSession( - configuration: URLSessionConfiguration.default, delegate: ignoreHttpsDelegate, + http = URLSession( + configuration: URLSessionConfiguration.default, delegate: IgnoreHttpsDelegate(), delegateQueue: nil) - - Task { - - ////////////////////////////// Get master password hash ////////////////////////////// - - struct PreloginRequest: Codable { let email: String } - struct PreloginResponse: Codable { - let kdf: UInt32 - let kdfIterations: UInt32 - let kdfMemory: UInt32? - let kdfParallelism: UInt32? - - } - - let (preloginDataJson, _) = try await http.data( - for: request( - method: "POST", url: IDENTITY_URL + "accounts/prelogin", - fn: { r in - r.setValue("application/json", forHTTPHeaderField: "Content-Type") - r.httpBody = try JSONEncoder().encode(PreloginRequest(email: EMAIL)) - })) - let preloginData = try JSONDecoder().decode( - PreloginResponse.self, from: preloginDataJson) - - let kdf: Kdf - if preloginData.kdf == 0 { - kdf = Kdf.pbkdf2(iterations: preloginData.kdfIterations) - } else { - kdf = Kdf.argon2id( - iterations: preloginData.kdfIterations, memory: preloginData.kdfMemory!, - parallelism: preloginData.kdfParallelism!) - } - - let passwordHash = try await client.auth().hashPassword( - email: EMAIL, password: PASSWORD, kdfParams: kdf) - - ///////////////////////////// Login ///////////////////////////// - - struct LoginResponse: Codable { - let Key: String - let PrivateKey: String - let access_token: String - let refresh_token: String - } - - let (loginDataJson, _) = try await http.data( - for: request( - method: "POST", url: IDENTITY_URL + "connect/token", - fn: { r in - r.setValue( - EMAIL.data(using: .utf8)?.base64EncodedString(), - forHTTPHeaderField: "Auth-Email") - r.setValue( - "application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") - - var comp = URLComponents() - comp.queryItems = [ - URLQueryItem(name: "scope", value: "api offline_access"), - URLQueryItem(name: "client_id", value: "web"), - URLQueryItem(name: "deviceType", value: "12"), - URLQueryItem( - name: "deviceIdentifier", - value: "0745d426-8dab-484a-9816-4959721d77c7"), - URLQueryItem(name: "deviceName", value: "edge"), - URLQueryItem(name: "grant_type", value: "password"), - URLQueryItem(name: "username", value: EMAIL), - URLQueryItem(name: "password", value: passwordHash), - ] - r.httpBody = comp.percentEncodedQuery! - .replacingOccurrences(of: "@", with: "%40") - .replacingOccurrences(of: "+", with: "%2B") - .data(using: .utf8) - })) - let loginData = try JSONDecoder().decode(LoginResponse.self, from: loginDataJson) - - ///////////////////////////// Sync ///////////////////////////// - - struct SyncOrganization: Codable { - let id: String - let key: String - } - struct SyncProfile: Codable { - let organizations: [SyncOrganization] - - } - struct SyncFolder: Codable { - let id: String - let name: String - let revisionDate: String - } - struct SyncResponse: Codable { - let profile: SyncProfile - let folders: [SyncFolder] - } - - let (syncDataJson, _) = try await http.data( - for: request( - method: "GET", url: API_URL + "sync?excludeDomains=true", - fn: { r in - r.setValue( - "Bearer " + loginData.access_token, forHTTPHeaderField: "Authorization") - })) - - let syncData = try JSONDecoder().decode(SyncResponse.self, from: syncDataJson) - - ///////////////////////////// Initialize crypto ///////////////////////////// - - try await client.crypto().initializeUserCrypto( - req: InitUserCryptoRequest( - kdfParams: kdf, - email: EMAIL, - privateKey: loginData.PrivateKey, - method: InitUserCryptoMethod.password( - password: PASSWORD, - userKey: loginData.Key - ) - )) - - try await client.crypto().initializeOrgCrypto( - req: InitOrgCryptoRequest( - organizationKeys: Dictionary.init( - uniqueKeysWithValues: syncData.profile.organizations.map { ($0.id, $0.key) } - ) - )) - - ///////////////////////////// Decrypt some folders ///////////////////////////// - - let dateFormatter = ISO8601DateFormatter() - dateFormatter.formatOptions = [.withFractionalSeconds] - - let decryptedFolders = try await client.vault().folders().decryptList( - folders: syncData.folders.map { - Folder( - id: $0.id, name: $0.name, - revisionDate: dateFormatter.date(from: $0.revisionDate)!) - }) - print(decryptedFolders) - } + + client = Client(settings: nil) } - + + @State var setupBiometrics: Bool = true + @State var outputText: String = "" + var body: some View { VStack { - Image(systemName: "globe") - .imageScale(.large) - .foregroundColor(.accentColor) - Text("Hello " + msg) + Toggle("Setup biometric unlock after login", isOn: $setupBiometrics).padding(.init(top: 0, leading: 20, bottom: 0, trailing: 20)) + + Button(action: { + Task { + do { + try await clientExamplePassword(clientAuth: client.auth(), clientCrypto: client.crypto(), setupBiometrics: setupBiometrics) + try await decryptVault(clientCrypto: client.crypto(), clientVault: client.vault()) + } catch { + print("ERROR:", error) + } + } + }, label: { + Text("Login with username + password") + }) + + Divider().padding(30) + + Button(action: { + Task { + do { + try await clientExampleBiometrics(clientCrypto: client.crypto()) + try await decryptVault(clientCrypto: client.crypto(), clientVault: client.vault()) + } catch { + print("ERROR:", error) + } + } + }, label: { + Text("Unlock with biometrics") + }) + + Button(action: { + client = Client(settings: nil) + }, label: { + Text("Lock & reset client") + }).padding() + + Text("Output: " + outputText).padding(.top) } .padding() } + + func clientExamplePassword(clientAuth: ClientAuthProtocol, clientCrypto: ClientCryptoProtocol, setupBiometrics: Bool) async throws { + ////////////////////////////// Get master password hash ////////////////////////////// + + struct PreloginRequest: Codable { let email: String } + struct PreloginResponse: Codable { + let kdf: UInt32 + let kdfIterations: UInt32 + let kdfMemory: UInt32? + let kdfParallelism: UInt32? + + } + + let (preloginDataJson, _) = try await http.data( + for: request( + method: "POST", url: IDENTITY_URL + "accounts/prelogin", + fn: { r in + r.setValue("application/json", forHTTPHeaderField: "Content-Type") + r.httpBody = try JSONEncoder().encode(PreloginRequest(email: EMAIL)) + })) + let preloginData = try JSONDecoder().decode( + PreloginResponse.self, from: preloginDataJson) + + let kdf: Kdf + if preloginData.kdf == 0 { + kdf = Kdf.pbkdf2(iterations: preloginData.kdfIterations) + } else { + kdf = Kdf.argon2id( + iterations: preloginData.kdfIterations, memory: preloginData.kdfMemory!, + parallelism: preloginData.kdfParallelism!) + } + + let passwordHash = try await clientAuth.hashPassword( + email: EMAIL, password: PASSWORD, kdfParams: kdf) + + ///////////////////////////// Login ///////////////////////////// + + struct LoginResponse: Codable { + let Key: String + let PrivateKey: String + let access_token: String + let refresh_token: String + } + + let (loginDataJson, _) = try await http.data( + for: request( + method: "POST", url: IDENTITY_URL + "connect/token", + fn: { r in + r.setValue( + EMAIL.data(using: .utf8)?.base64EncodedString(), + forHTTPHeaderField: "Auth-Email") + r.setValue( + "application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") + + var comp = URLComponents() + comp.queryItems = [ + URLQueryItem(name: "scope", value: "api offline_access"), + URLQueryItem(name: "client_id", value: "web"), + URLQueryItem(name: "deviceType", value: "12"), + URLQueryItem( + name: "deviceIdentifier", + value: "0745d426-8dab-484a-9816-4959721d77c7"), + URLQueryItem(name: "deviceName", value: "edge"), + URLQueryItem(name: "grant_type", value: "password"), + URLQueryItem(name: "username", value: EMAIL), + URLQueryItem(name: "password", value: passwordHash), + ] + r.httpBody = comp.percentEncodedQuery! + .replacingOccurrences(of: "@", with: "%40") + .replacingOccurrences(of: "+", with: "%2B") + .data(using: .utf8) + })) + let loginData = try JSONDecoder().decode(LoginResponse.self, from: loginDataJson) + + try await clientCrypto.initializeUserCrypto( + req: InitUserCryptoRequest( + kdfParams: kdf, + email: EMAIL, + privateKey: loginData.PrivateKey, + method: InitUserCryptoMethod.password( + password: PASSWORD, + userKey: loginData.Key + ) + )) + + accessToken = loginData.access_token + + if (setupBiometrics) { + let defaults = UserDefaults.standard + defaults.set(loginData.PrivateKey, forKey: "privateKey") + defaults.set(preloginData.kdf, forKey: "kdfType") + defaults.set(preloginData.kdfIterations, forKey: "kdfIterations") + defaults.set(preloginData.kdfMemory, forKey: "kdfMemory") + defaults.set(preloginData.kdfParallelism, forKey: "kdfParallelism") + defaults.synchronize() + + let key = try await clientCrypto.getUserEncryptionKey() + biometricStoreValue(value: key) + } + } + + func clientExampleBiometrics(clientCrypto: ClientCryptoProtocol) async throws { + let defaults = UserDefaults.standard + let privateKey = defaults.string(forKey: "privateKey")! + let kdf = if defaults.integer(forKey: "kdfType") == 0 { + Kdf.pbkdf2(iterations: UInt32(defaults.integer(forKey: "kdfIterations"))) + } else { + Kdf.argon2id( + iterations: UInt32(defaults.integer(forKey: "kdfIterations")), + memory: UInt32(defaults.integer(forKey: "kdfMemory")), + parallelism: UInt32(defaults.integer(forKey: "kdfParallelism")) + ) + } + + let key = biometricRetrieveValue()! + + try await clientCrypto.initializeUserCrypto(req: InitUserCryptoRequest( + kdfParams: kdf, + email: EMAIL, + privateKey: privateKey, + method: InitUserCryptoMethod.decryptedKey( + decryptedUserKey: key + ) + )) + } + + func decryptVault(clientCrypto: ClientCryptoProtocol, clientVault: ClientVaultProtocol) async throws { + ///////////////////////////// Sync ///////////////////////////// + + struct SyncOrganization: Codable { + let id: String + let key: String + } + struct SyncProfile: Codable { + let organizations: [SyncOrganization] + + } + struct SyncFolder: Codable { + let id: String + let name: String + let revisionDate: String + } + struct SyncResponse: Codable { + let profile: SyncProfile + let folders: [SyncFolder] + } + + let (syncDataJson, _) = try await http.data( + for: request( + method: "GET", url: API_URL + "sync?excludeDomains=true", + fn: { r in + r.setValue( + "Bearer " + accessToken, forHTTPHeaderField: "Authorization") + })) + + let syncData = try JSONDecoder().decode(SyncResponse.self, from: syncDataJson) + + ///////////////////////////// Initialize org crypto ///////////////////////////// + + try await clientCrypto.initializeOrgCrypto( + req: InitOrgCryptoRequest( + organizationKeys: Dictionary.init( + uniqueKeysWithValues: syncData.profile.organizations.map { ($0.id, $0.key) } + ) + )) + + ///////////////////////////// Decrypt some folders ///////////////////////////// + + let dateFormatter = ISO8601DateFormatter() + dateFormatter.formatOptions = [.withFractionalSeconds] + + let decryptedFolders = try await clientVault.folders().decryptList( + folders: syncData.folders.map { + Folder( + id: $0.id, name: $0.name, + revisionDate: dateFormatter.date(from: $0.revisionDate)!) + }) + print(decryptedFolders) + } } struct ContentView_Previews: PreviewProvider { @@ -202,7 +287,7 @@ extension IgnoreHttpsDelegate: URLSessionDelegate { ) { //Trust the certificate even if not valid let urlCredential = URLCredential(trust: challenge.protectionSpace.serverTrust!) - + completionHandler(.useCredential, urlCredential) } }