chore: simplify mnemonic zeroize story (#3165)

* updated bip39 dependency to simplify our zeroize story

* Replaced UserPassword wrapper with Zeroizing type alias

* fixed wallet-types cosmwasm-std dependency version
This commit is contained in:
Jędrzej Stuczyński
2023-03-13 11:29:56 +00:00
committed by GitHub
parent 6de829163d
commit 54287666e8
20 changed files with 255 additions and 654 deletions
Generated
+31 -30
View File
@@ -302,22 +302,23 @@ dependencies = [
[[package]]
name = "bip39"
version = "1.0.1"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e89470017230c38e52b82b3ee3f530db1856ba1d434e3a67a3456a8a8dec5f"
checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f"
dependencies = [
"bitcoin_hashes",
"rand 0.6.5",
"rand_core 0.4.2",
"rand 0.8.5",
"rand_core 0.6.4",
"serde",
"unicode-normalization",
"zeroize",
]
[[package]]
name = "bitcoin_hashes"
version = "0.9.7"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ce18265ec2324ad075345d5814fbeed4f41f0a660055dc78840b74d19b874b1"
checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4"
[[package]]
name = "bitflags"
@@ -2845,12 +2846,6 @@ dependencies = [
"serde",
]
[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]]
name = "memchr"
version = "2.5.0"
@@ -4171,7 +4166,7 @@ dependencies = [
"instant",
"libc",
"redox_syscall",
"smallvec 1.10.0",
"smallvec",
"winapi",
]
@@ -4184,7 +4179,7 @@ dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec 1.10.0",
"smallvec",
"windows-sys 0.45.0",
]
@@ -5057,7 +5052,7 @@ dependencies = [
"pin-project-lite",
"ref-cast",
"serde",
"smallvec 1.10.0",
"smallvec",
"stable-pattern",
"state",
"time 0.3.17",
@@ -5552,15 +5547,6 @@ dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "smallvec"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0"
dependencies = [
"maybe-uninit",
]
[[package]]
name = "smallvec"
version = "1.10.0"
@@ -5725,7 +5711,7 @@ dependencies = [
"percent-encoding",
"rustls 0.19.1",
"sha2 0.10.6",
"smallvec 1.10.0",
"smallvec",
"sqlformat 0.1.8",
"sqlx-rt 0.5.13",
"stringprep",
@@ -5773,7 +5759,7 @@ dependencies = [
"rustls 0.20.8",
"rustls-pemfile",
"sha2 0.10.6",
"smallvec 1.10.0",
"smallvec",
"sqlformat 0.2.1",
"sqlx-rt 0.6.2",
"stringprep",
@@ -6198,6 +6184,21 @@ dependencies = [
"serde_json",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.25.0"
@@ -6495,7 +6496,7 @@ dependencies = [
"once_cell",
"regex",
"sharded-slab",
"smallvec 1.10.0",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
@@ -6661,11 +6662,11 @@ checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-normalization"
version = "0.1.9"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09c8070a9942f5e7cfccd93f490fdebd230ee3c3c9f107cb25bad5351ef671cf"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"smallvec 0.6.14",
"tinyvec",
]
[[package]]
+1
View File
@@ -105,6 +105,7 @@ license = "Apache-2.0"
[workspace.dependencies]
async-trait = "0.1.64"
bip39 = { version = "2.0.0", features = ["zeroize"] }
cfg-if = "1.0.0"
dotenvy = "0.15.6"
lazy_static = "1.4.0"
+1 -1
View File
@@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bip39 = "1.0.1"
bip39 = { workspace = true }
clap = { version = "4.0", features = ["cargo", "derive"] }
log = "0.4"
rand = "0.7.3"
@@ -37,7 +37,7 @@ nym-execute = { path = "../../execute" }
# at some point it might be possible to make it wasm-compatible
# perhaps after https://github.com/cosmos/cosmos-rust/pull/97 is resolved (and tendermint-rs is updated)
async-trait = { workspace = true, optional = true }
bip39 = { version = "1", features = ["rand"], optional = true }
bip39 = { workspace = true, features = ["rand"], optional = true }
nym-config = { path = "../../config", optional = true }
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support", features = ["rpc", "bip32", "cosmwasm"], optional = true}
cw3 = { version = "0.13.4", optional = true }
@@ -47,7 +47,7 @@ flate2 = { version = "1.0.20", optional = true }
sha2 = { version = "0.9.5", optional = true }
itertools = { version = "0.10", optional = true }
cosmwasm-std = { version = "1.0.0", optional = true }
zeroize = { version = "1.5.7", optional = true }
zeroize = { version = "1.5.7", optional = true, features = ["zeroize_derive"] }
[dev-dependencies]
ts-rs = "6.1.2"
@@ -8,7 +8,7 @@ use cosmrs::crypto::PublicKey;
use cosmrs::tx::SignDoc;
use cosmrs::{tx, AccountId};
use nym_config::defaults;
use zeroize::Zeroize;
use zeroize::{Zeroize, ZeroizeOnDrop};
/// Derivation information required to derive a keypair and an address from a mnemonic.
#[derive(Debug, Clone)]
@@ -41,7 +41,7 @@ impl AccountData {
type Secp256k1Keypair = (SigningKey, PublicKey);
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Zeroize, ZeroizeOnDrop)]
pub struct DirectSecp256k1HdWallet {
/// Base secret
secret: bip39::Mnemonic,
@@ -54,30 +54,10 @@ pub struct DirectSecp256k1HdWallet {
// that would include the secret key which is a dyn EcdsaSigner and hence not Sync making the wallet
// not Sync and if used on the signing client in an async trait, it wouldn't be Send
/// Derivation instructions
#[zeroize(skip)]
accounts: Vec<Secp256k1Derivation>,
}
impl Zeroize for DirectSecp256k1HdWallet {
fn zeroize(&mut self) {
// in ideal world, Mnemonic would have had zeroize defined on it (there's an almost year old PR that introduces it)
// and the memory would have been filled with zeroes.
//
// we really don't want to keep our real mnemonic in memory, so let's do the semi-nasty thing
// of overwriting it with a fresh mnemonic that was never used before
//
// note: this function can only fail on an invalid word count, which clearly is not the case here
self.secret = bip39::Mnemonic::generate(self.secret.word_count()).unwrap();
self.seed.zeroize();
// there's nothing secret about derivation paths
}
}
impl Drop for DirectSecp256k1HdWallet {
fn drop(&mut self) {
self.zeroize()
}
}
impl DirectSecp256k1HdWallet {
pub fn builder(prefix: &str) -> DirectSecp256k1HdWalletBuilder {
DirectSecp256k1HdWalletBuilder::new(prefix)
+1 -1
View File
@@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
base64 = "0.13.0"
bip39 = "1.0.1"
bip39 = { workspace = true }
bs58 = "0.4"
comfy-table = "6.0.0"
cfg-if = "1.0.0"
+1 -1
View File
@@ -17,7 +17,7 @@ rust-version = "1.56"
[dependencies]
anyhow = "1.0.53"
async-trait = { workspace = true }
bip39 = "1.0.1"
bip39 = { workspace = true }
bs58 = "0.4.0"
clap = { version = "4.0", features = ["cargo", "derive"] }
colored = "2.0"
+1 -1
View File
@@ -17,7 +17,7 @@ rust-version = "1.56"
[dependencies]
async-trait = { workspace = true }
bs58 = {version = "0.4.0" }
bip39 = "1"
bip39 = { workspace = true }
cfg-if = "1.0"
clap = { version = "4.0", features = ["cargo", "derive"] }
console-subscriber = { version = "0.1.1", optional = true } # validator-api needs to be built with RUSTFLAGS="--cfg tokio_unstable"
+1 -1
View File
@@ -20,7 +20,7 @@ tauri-macros = "^1.2.1"
[dependencies]
anyhow = "1.0"
bip39 = "1.0"
bip39 = { version = "2.0.0", features = ["zeroize"] }
dirs = "4.0"
eyre = "0.6.5"
fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs", branch = "release"}
+1 -1
View File
@@ -21,7 +21,7 @@ tauri-build = { version = "2.0.0-alpha.1", features = [] }
[dependencies]
anyhow = "1.0"
bip39 = "1.0"
bip39 = { version = "2.0.0", features = ["zeroize"] }
chrono = "0.4"
dirs = "4.0"
eyre = "0.6.5"
+59 -197
View File
@@ -181,15 +181,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "autocfg"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "autocfg"
version = "1.1.0"
@@ -240,22 +231,23 @@ dependencies = [
[[package]]
name = "bip39"
version = "1.0.1"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e89470017230c38e52b82b3ee3f530db1856ba1d434e3a67a3456a8a8dec5f"
checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f"
dependencies = [
"bitcoin_hashes",
"rand 0.6.5",
"rand_core 0.4.2",
"rand 0.8.5",
"rand_core 0.6.4",
"serde",
"unicode-normalization",
"zeroize",
]
[[package]]
name = "bitcoin_hashes"
version = "0.9.7"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ce18265ec2324ad075345d5814fbeed4f41f0a660055dc78840b74d19b874b1"
checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4"
[[package]]
name = "bitflags"
@@ -476,7 +468,7 @@ version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3431df59f28accaf4cb4eed4a9acc66bea3f3c3753aa6cdc2f024174ef232af7"
dependencies = [
"smallvec 1.10.0",
"smallvec",
]
[[package]]
@@ -485,7 +477,7 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0357a6402b295ca3a86bc148e84df46c02e41f41fef186bda662557ef6328aa"
dependencies = [
"smallvec 1.10.0",
"smallvec",
]
[[package]]
@@ -569,15 +561,6 @@ dependencies = [
"os_str_bytes",
]
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "cocoa"
version = "0.24.1"
@@ -869,7 +852,7 @@ dependencies = [
"phf 0.8.0",
"proc-macro2",
"quote",
"smallvec 1.10.0",
"smallvec",
"syn",
]
@@ -1431,12 +1414,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e"
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "funty"
version = "2.0.0"
@@ -1762,7 +1739,7 @@ dependencies = [
"gobject-sys",
"libc",
"once_cell",
"smallvec 1.10.0",
"smallvec",
"thiserror",
]
@@ -2248,7 +2225,7 @@ version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg 1.1.0",
"autocfg",
"hashbrown",
"serde",
]
@@ -2508,7 +2485,7 @@ version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
dependencies = [
"autocfg 1.1.0",
"autocfg",
"scopeguard",
]
@@ -2581,12 +2558,6 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]]
name = "memchr"
version = "2.5.0"
@@ -2599,7 +2570,7 @@ version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg 1.1.0",
"autocfg",
]
[[package]]
@@ -2729,7 +2700,7 @@ version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg 1.1.0",
"autocfg",
"num-traits",
]
@@ -2739,7 +2710,7 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
dependencies = [
"autocfg 1.1.0",
"autocfg",
"num-integer",
"num-traits",
]
@@ -2750,7 +2721,7 @@ version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg 1.1.0",
"autocfg",
"libm",
]
@@ -2878,6 +2849,20 @@ dependencies = [
"thiserror",
]
[[package]]
name = "nym-crypto"
version = "0.2.0"
dependencies = [
"bs58",
"ed25519-dalek",
"nym-pemstore",
"nym-sphinx-types",
"rand 0.7.3",
"subtle-encoding",
"thiserror",
"x25519-dalek",
]
[[package]]
name = "nym-dkg"
version = "0.1.0"
@@ -2899,20 +2884,6 @@ dependencies = [
"zeroize",
]
[[package]]
name = "nym-crypto"
version = "0.1.0"
dependencies = [
"bs58",
"ed25519-dalek",
"nym-pemstore",
"nym-sphinx-types",
"rand 0.7.3",
"subtle-encoding",
"thiserror",
"x25519-dalek",
]
[[package]]
name = "nym-execute"
version = "0.1.0"
@@ -2984,7 +2955,7 @@ dependencies = [
[[package]]
name = "nym-sphinx-types"
version = "0.1.0"
version = "0.2.0"
dependencies = [
"sphinx-packet",
]
@@ -3110,7 +3081,6 @@ dependencies = [
"nym-wallet-types",
"once_cell",
"pretty_env_logger",
"rand 0.6.5",
"rand_chacha 0.2.2",
"reqwest",
"serde",
@@ -3258,7 +3228,7 @@ version = "0.9.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7"
dependencies = [
"autocfg 1.1.0",
"autocfg",
"cc",
"libc",
"pkg-config",
@@ -3330,7 +3300,7 @@ dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec 1.10.0",
"smallvec",
"windows-sys 0.45.0",
]
@@ -3790,25 +3760,6 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg 0.1.8",
"libc",
"rand_chacha 0.1.1",
"rand_core 0.4.2",
"rand_hc 0.1.0",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg 0.1.2",
"rand_xorshift",
"winapi",
]
[[package]]
name = "rand"
version = "0.7.3"
@@ -3819,8 +3770,8 @@ dependencies = [
"libc",
"rand_chacha 0.2.2",
"rand_core 0.5.1",
"rand_hc 0.2.0",
"rand_pcg 0.2.1",
"rand_hc",
"rand_pcg",
]
[[package]]
@@ -3834,16 +3785,6 @@ dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.3.1",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
@@ -3864,21 +3805,6 @@ dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_core"
version = "0.5.1"
@@ -3907,15 +3833,6 @@ dependencies = [
"rand 0.7.3",
]
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
@@ -3925,50 +3842,6 @@ dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.4.2",
]
[[package]]
name = "rand_pcg"
version = "0.2.1"
@@ -3978,15 +3851,6 @@ dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "raw-window-handle"
version = "0.5.0"
@@ -3996,15 +3860,6 @@ dependencies = [
"cty",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
@@ -4350,7 +4205,7 @@ dependencies = [
"phf_codegen",
"precomputed-hash",
"servo_arc",
"smallvec 1.10.0",
"smallvec",
"thin-slice",
]
@@ -4605,16 +4460,7 @@ version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "smallvec"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0"
dependencies = [
"maybe-uninit",
"autocfg",
]
[[package]]
@@ -5281,13 +5127,28 @@ dependencies = [
"time-core",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af"
dependencies = [
"autocfg 1.1.0",
"autocfg",
"bytes",
"libc",
"memchr",
@@ -5434,7 +5295,7 @@ dependencies = [
"once_cell",
"regex",
"sharded-slab",
"smallvec 1.10.0",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
@@ -5517,11 +5378,11 @@ checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-normalization"
version = "0.1.9"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09c8070a9942f5e7cfccd93f490fdebd230ee3c3c9f107cb25bad5351ef671cf"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"smallvec 0.6.14",
"tinyvec",
]
[[package]]
@@ -6228,6 +6089,7 @@ version = "1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
dependencies = [
"serde",
"zeroize_derive",
]
@@ -10,7 +10,7 @@ aes-gcm = "0.9"
anyhow = "1.0"
argon2 = "0.4"
base64 = "0.13"
bip39 = "1.0"
bip39 = { version = "2.0.0", features = ["zeroize"] }
clap = { version = "4.0", features = ["derive"] }
log = "0.4"
pretty_env_logger = "0.4"
+1 -1
View File
@@ -11,7 +11,7 @@ serde_json = "1.0"
strum = { version = "0.23", features = ["derive"] }
ts-rs = "6.1.2"
cosmwasm-std = "1.0.0-beta8"
cosmwasm-std = "1.0.0"
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support" }
nym-config = { path = "../../common/config" }
+2 -3
View File
@@ -20,7 +20,7 @@ tauri-macros = "=1.2.1"
[dependencies]
async-trait = "0.1.64"
bip39 = "1.0"
bip39 = { version = "2.0.0", features = ["zeroize", "rand"] }
cfg-if = "1.0.0"
colored = "2.0"
dirs = "4.0"
@@ -32,7 +32,6 @@ itertools = "0.10"
log = { version = "0.4", features = ["serde"] }
once_cell = "1.7.2"
pretty_env_logger = "0.4"
rand = "0.6.5"
reqwest = {version = "0.11.9", features = ["json"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
@@ -50,7 +49,7 @@ k256 = { version = "0.10", features = ["ecdsa", "sha256"] }
aes-gcm = "0.9.4"
argon2 = { version = "0.3.2", features = ["std"] }
base64 = "0.13"
zeroize = "1.4.3"
zeroize = { version = "1.5", features = ["zeroize_derive", "serde"] }
cosmwasm-std = "1.0.0"
cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegrant_support" }
@@ -2,15 +2,14 @@ use crate::config::{Config, CUSTOM_SIMULATED_GAS_MULTIPLIER};
use crate::error::BackendError;
use crate::network_config;
use crate::state::{WalletAccountIds, WalletState};
use crate::utils::{SensitiveStringWrapper, ZeroizeMnemonicWrapper};
use crate::wallet_storage::{self, UserPassword, DEFAULT_LOGIN_ID};
use bip39::rand::{self, seq::SliceRandom};
use bip39::{Language, Mnemonic};
use cosmrs::bip32::DerivationPath;
use itertools::Itertools;
use nym_config::defaults::{NymNetworkDetails, COSMOS_DERIVATION_PATH};
use nym_types::account::{Account, AccountEntry, Balance};
use nym_wallet_types::network::Network as WalletNetwork;
use rand::seq::SliceRandom;
use std::collections::HashMap;
use strum::IntoEnumIterator;
use url::Url;
@@ -19,10 +18,9 @@ use validator_client::{nyxd::SigningNyxdClient, Client};
#[tauri::command]
pub async fn connect_with_mnemonic(
mnemonic: SensitiveStringWrapper,
mnemonic: Mnemonic,
state: tauri::State<'_, WalletState>,
) -> Result<Account, BackendError> {
let mnemonic = ZeroizeMnemonicWrapper::try_from_string(mnemonic)?;
_connect_with_mnemonic(mnemonic, state).await
}
@@ -48,13 +46,13 @@ pub async fn get_balance(state: tauri::State<'_, WalletState>) -> Result<Balance
}
#[tauri::command]
pub fn create_new_mnemonic() -> SensitiveStringWrapper {
random_mnemonic().into_string()
pub fn create_new_mnemonic() -> Mnemonic {
random_mnemonic()
}
#[tauri::command]
pub fn validate_mnemonic(mnemonic: SensitiveStringWrapper) -> bool {
ZeroizeMnemonicWrapper::try_from_string(mnemonic).is_ok()
pub fn validate_mnemonic(_mnemonic: Mnemonic) -> bool {
true
}
#[tauri::command]
@@ -82,15 +80,13 @@ pub async fn logout(state: tauri::State<'_, WalletState>) -> Result<(), BackendE
Ok(())
}
fn random_mnemonic() -> ZeroizeMnemonicWrapper {
fn random_mnemonic() -> Mnemonic {
let mut rng = rand::thread_rng();
Mnemonic::generate_in_with(&mut rng, Language::English, 24)
.unwrap()
.into()
Mnemonic::generate_in_with(&mut rng, Language::English, 24).unwrap()
}
async fn _connect_with_mnemonic(
mnemonic: ZeroizeMnemonicWrapper,
mnemonic: Mnemonic,
state: tauri::State<'_, WalletState>,
) -> Result<Account, BackendError> {
{
@@ -141,7 +137,7 @@ async fn _connect_with_mnemonic(
&default_nyxd_urls,
&default_api_urls,
&config,
mnemonic.as_ref(),
&mnemonic,
)?;
// Set the default account
@@ -298,16 +294,12 @@ pub fn does_password_file_exist() -> Result<bool, BackendError> {
}
#[tauri::command]
pub fn create_password(
mnemonic: SensitiveStringWrapper,
password: UserPassword,
) -> Result<(), BackendError> {
pub fn create_password(mnemonic: Mnemonic, password: UserPassword) -> Result<(), BackendError> {
if does_password_file_exist()? {
return Err(BackendError::WalletFileAlreadyExists);
}
log::info!("Creating password");
let mnemonic = ZeroizeMnemonicWrapper::try_from_string(mnemonic)?;
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
// Currently we only support a single, default, login id in the wallet
let login_id = wallet_storage::LoginId::new(DEFAULT_LOGIN_ID.to_string());
@@ -330,7 +322,7 @@ pub async fn sign_in_with_password(
set_state_with_all_accounts(stored_login, first_login_id_when_converting, state.clone())
.await?;
_connect_with_mnemonic(mnemonic.into(), state).await
_connect_with_mnemonic(mnemonic, state).await
}
fn extract_first_mnemonic(
@@ -370,7 +362,7 @@ pub async fn sign_in_with_password_and_account_id(
set_state_with_all_accounts(stored_login, first_login_id_when_converting, state.clone())
.await?;
_connect_with_mnemonic(mnemonic.into(), state).await
_connect_with_mnemonic(mnemonic, state).await
}
fn extract_mnemonic(
@@ -404,13 +396,12 @@ pub fn archive_wallet_file() -> Result<(), BackendError> {
#[tauri::command]
pub async fn add_account_for_password(
mnemonic: SensitiveStringWrapper,
mnemonic: Mnemonic,
password: UserPassword,
account_id: &str,
state: tauri::State<'_, WalletState>,
) -> Result<AccountEntry, BackendError> {
log::info!("Adding account for the current password: {account_id}");
let mnemonic = ZeroizeMnemonicWrapper::try_from_string(mnemonic)?;
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
// Currently we only support a single, default, login id in the wallet
let login_id = wallet_storage::LoginId::new(DEFAULT_LOGIN_ID.to_string());
@@ -427,13 +418,7 @@ pub async fn add_account_for_password(
let address = {
let state = state.read().await;
let network: NymNetworkDetails = state.current_network().into();
// safety: the call to `clone_inner` is fine here as the raw mnemonic will get immediately
// passed to `DirectSecp256k1HdWallet` which will zeroize it on drop
derive_address(
mnemonic.into_cloned_inner(),
&network.chain_details.bech32_account_prefix,
)?
.to_string()
derive_address(mnemonic, &network.chain_details.bech32_account_prefix)?.to_string()
};
// Re-read all the acccounts from the wallet to reset the state, rather than updating it
@@ -553,19 +538,19 @@ pub async fn list_accounts(
pub fn show_mnemonic_for_account_in_password(
account_id: String,
password: UserPassword,
) -> Result<SensitiveStringWrapper, BackendError> {
) -> Result<Mnemonic, BackendError> {
log::info!("Getting mnemonic for: {account_id}");
let login_id = wallet_storage::LoginId::new(DEFAULT_LOGIN_ID.to_string());
let account_id = wallet_storage::AccountId::new(account_id);
let mnemonic = _show_mnemonic_for_account_in_password(&login_id, &account_id, &password)?;
Ok(mnemonic.into_string())
Ok(mnemonic)
}
fn _show_mnemonic_for_account_in_password(
login_id: &wallet_storage::LoginId,
account_id: &wallet_storage::AccountId,
password: &wallet_storage::UserPassword,
) -> Result<ZeroizeMnemonicWrapper, BackendError> {
) -> Result<Mnemonic, BackendError> {
let stored_account = wallet_storage::load_existing_login(login_id, password)?;
let mnemonic = match stored_account {
wallet_storage::StoredLogin::Mnemonic(ref account) => account.mnemonic().clone(),
@@ -575,7 +560,7 @@ fn _show_mnemonic_for_account_in_password(
.mnemonic()
.clone(),
};
Ok(mnemonic.into())
Ok(mnemonic)
}
#[cfg(test)]
@@ -590,8 +575,8 @@ mod tests {
use super::*;
// This decryptes a stored wallet file using the same procedure as when signing in. Most tests
// related to the encryped wallet storage is in `wallet_storage`.
// This decrypts a stored wallet file using the same procedure as when signing in. Most tests
// related to the encrypted wallet storage is in `wallet_storage`.
#[test]
fn decrypt_stored_wallet_for_sign_in() {
const SAVED_WALLET: &str = "src/wallet_storage/test-data/saved-wallet.json";
+1 -94
View File
@@ -4,16 +4,14 @@
use crate::error::BackendError;
use crate::nyxd_client;
use crate::state::WalletState;
use bip39::Mnemonic;
use cosmwasm_std::Decimal;
use nym_mixnet_contract_common::{IdentityKey, MixId, Percent};
use nym_types::currency::DecCoin;
use nym_types::mixnode::MixNodeCostParams;
use nym_wallet_types::app::AppEnv;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::{Deserialize, Serialize};
use validator_client::nyxd::traits::MixnetQueryClient;
use validator_client::nyxd::{tx, Coin, CosmosCoin, Gas, GasPrice};
use zeroize::Zeroize;
fn get_env_as_option(key: &str) -> Option<String> {
match ::std::env::var(key) {
@@ -194,94 +192,3 @@ pub async fn get_old_and_incorrect_hardcoded_fee(
log::info!("hardcoded fee for {:?} is {:?}", operation, coin);
guard.attempt_convert_to_display_dec_coin(coin)
}
#[derive(Zeroize)]
#[zeroize(drop)]
pub struct SensitiveStringWrapper(String);
impl<'de> Deserialize<'de> for SensitiveStringWrapper {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(SensitiveStringWrapper(String::deserialize(deserializer)?))
}
}
impl Serialize for SensitiveStringWrapper {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
// unfortunately this serialized value will live on...
self.0.serialize(serializer)
}
}
impl From<String> for SensitiveStringWrapper {
fn from(value: String) -> Self {
SensitiveStringWrapper(value)
}
}
impl AsRef<str> for SensitiveStringWrapper {
fn as_ref(&self) -> &str {
self.0.as_ref()
}
}
#[derive(Clone)]
// can't do it natively until https://github.com/rust-bitcoin/rust-bip39/pull/32 gets merged and released...
pub(crate) struct ZeroizeMnemonicWrapper(bip39::Mnemonic);
impl From<bip39::Mnemonic> for ZeroizeMnemonicWrapper {
fn from(value: Mnemonic) -> Self {
ZeroizeMnemonicWrapper(value)
}
}
impl Zeroize for ZeroizeMnemonicWrapper {
fn zeroize(&mut self) {
// overwrite the mnemonic value with a completely random one
// (a poor man's zeroize until bip39 crate does it properly...)
self.0 = Mnemonic::generate(self.0.word_count()).unwrap();
}
}
impl Drop for ZeroizeMnemonicWrapper {
fn drop(&mut self) {
self.zeroize()
}
}
impl AsRef<bip39::Mnemonic> for ZeroizeMnemonicWrapper {
fn as_ref(&self) -> &Mnemonic {
&self.0
}
}
impl ZeroizeMnemonicWrapper {
pub(crate) fn into_string(self) -> SensitiveStringWrapper {
SensitiveStringWrapper(self.0.to_string())
}
pub(crate) fn try_from_string(string: SensitiveStringWrapper) -> Result<Self, bip39::Error> {
let res = string.as_ref().parse()?;
Ok(ZeroizeMnemonicWrapper(res))
}
// special care must be taken when calling this method as the mnemonic will no longer get zeroized!
pub(crate) fn into_cloned_inner(self) -> bip39::Mnemonic {
self.0.clone()
}
#[cfg(test)]
pub(crate) fn unchecked_clone_inner(&self) -> bip39::Mnemonic {
self.0.clone()
}
#[cfg(test)]
pub(crate) fn generate_random() -> Self {
ZeroizeMnemonicWrapper(Mnemonic::generate(24).unwrap())
}
}
@@ -14,16 +14,14 @@
// In the future we might want to simplify by dropping the support for a single account entry,
// instead treating as muliple accounts with one entry.
use serde::{Deserialize, Serialize};
use validator_client::nyxd::bip32::DerivationPath;
use zeroize::Zeroize;
use crate::error::BackendError;
use crate::utils::ZeroizeMnemonicWrapper;
use super::encryption::EncryptedData;
use super::password::{AccountId, LoginId};
use super::UserPassword;
use crate::error::BackendError;
use bip39::Mnemonic;
use serde::{Deserialize, Serialize};
use validator_client::nyxd::bip32::DerivationPath;
use zeroize::{Zeroize, ZeroizeOnDrop};
const CURRENT_WALLET_FILE_VERSION: u32 = 1;
@@ -153,9 +151,8 @@ impl EncryptedLogin {
/// A stored login is either a account, such as a mnemonic, or a list of multiple accounts where
/// each has an inner id. Future proofed for having private key backed accounts.
#[derive(Serialize, Deserialize, Debug, Zeroize)]
#[derive(Serialize, Deserialize, Debug, Zeroize, ZeroizeOnDrop)]
#[serde(untagged)]
#[zeroize(drop)]
pub(crate) enum StoredLogin {
Mnemonic(MnemonicAccount),
// PrivateKey(PrivateKeyAccount)
@@ -193,8 +190,7 @@ impl StoredLogin {
}
/// Multiple stored accounts, each entry having an id and a data field.
#[derive(Serialize, Deserialize, Clone, Debug, Zeroize, PartialEq, Eq)]
#[zeroize(drop)]
#[derive(Serialize, Deserialize, Clone, Debug, Zeroize, ZeroizeOnDrop, PartialEq, Eq)]
pub(crate) struct MultipleAccounts {
accounts: Vec<WalletAccount>,
}
@@ -238,19 +234,17 @@ impl MultipleAccounts {
pub(crate) fn add(
&mut self,
id: AccountId,
mnemonic: ZeroizeMnemonicWrapper,
mnemonic: Mnemonic,
hd_path: DerivationPath,
) -> Result<(), BackendError> {
if self.get_account(&id).is_some() {
Err(BackendError::WalletAccountIdAlreadyExistsInWalletLogin)
} else if self.get_account_with_mnemonic(mnemonic.as_ref()).is_some() {
} else if self.get_account_with_mnemonic(&mnemonic).is_some() {
Err(BackendError::WalletMnemonicAlreadyExistsInWalletLogin)
} else {
self.accounts.push(WalletAccount::new(
id,
// safety: the call to `clone_inner` is fine here as the raw mnemonic will get immediately
// passed to `MnemonicAccount` which will zeroize it on drop
MnemonicAccount::new(mnemonic.into_cloned_inner(), hd_path),
MnemonicAccount::new(mnemonic, hd_path),
));
Ok(())
}
@@ -272,8 +266,7 @@ impl From<Vec<WalletAccount>> for MultipleAccounts {
}
/// An entry in the list of stored accounts
#[derive(Serialize, Deserialize, Clone, Debug, Zeroize, PartialEq, Eq)]
#[zeroize(drop)]
#[derive(Serialize, Deserialize, Clone, Debug, Zeroize, ZeroizeOnDrop, PartialEq, Eq)]
pub(crate) struct WalletAccount {
id: AccountId,
account: AccountData,
@@ -307,19 +300,20 @@ impl WalletAccount {
/// An account usually is a mnemonic account, but in the future it might be backed by a private
/// key.
#[derive(Serialize, Deserialize, Clone, Debug, Zeroize, PartialEq, Eq)]
#[derive(Serialize, Deserialize, Clone, Debug, Zeroize, ZeroizeOnDrop, PartialEq, Eq)]
#[serde(untagged)]
#[zeroize(drop)]
enum AccountData {
Mnemonic(MnemonicAccount),
// PrivateKey(PrivateKeyAccount)
}
/// An account backed by a unique mnemonic.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[derive(Serialize, Deserialize, Clone, Debug, Zeroize, ZeroizeOnDrop, PartialEq, Eq)]
pub(crate) struct MnemonicAccount {
mnemonic: bip39::Mnemonic,
#[serde(with = "display_hd_path")]
// there's nothing secret about our derivation path
#[zeroize(skip)]
hd_path: DerivationPath,
}
@@ -338,27 +332,6 @@ impl MnemonicAccount {
}
}
impl Zeroize for MnemonicAccount {
fn zeroize(&mut self) {
// in ideal world, Mnemonic would have had zeroize defined on it (there's an almost year old PR that introduces it)
// and the memory would have been filled with zeroes.
//
// we really don't want to keep our real mnemonic in memory, so let's do the semi-nasty thing
// of overwriting it with a fresh mnemonic that was never used before
//
// note: this function can only fail on an invalid word count, which clearly is not the case here
self.mnemonic = bip39::Mnemonic::generate(self.mnemonic.word_count()).unwrap();
// further note: we don't really care about the hd_path, there's nothing secret about it.
}
}
impl Drop for MnemonicAccount {
fn drop(&mut self) {
self.zeroize()
}
}
mod display_hd_path {
use serde::{Deserialize, Deserializer, Serializer};
use validator_client::nyxd::bip32::DerivationPath;
+107 -191
View File
@@ -14,7 +14,7 @@ pub(crate) use crate::wallet_storage::password::{AccountId, LoginId, UserPasswor
use crate::error::BackendError;
use crate::platform_constants::{STORAGE_DIR_NAME, WALLET_INFO_FILENAME};
use crate::utils::ZeroizeMnemonicWrapper;
use bip39::Mnemonic;
use std::ffi::OsString;
use std::fs::{self, create_dir_all, OpenOptions};
use std::path::{Path, PathBuf};
@@ -139,7 +139,7 @@ fn store_login_at_file(
}
pub(crate) fn store_login_with_multiple_accounts(
mnemonic: ZeroizeMnemonicWrapper,
mnemonic: Mnemonic,
hd_path: DerivationPath,
id: LoginId,
password: &UserPassword,
@@ -154,7 +154,7 @@ pub(crate) fn store_login_with_multiple_accounts(
fn store_login_with_multiple_accounts_at_file(
filepath: &Path,
mnemonic: ZeroizeMnemonicWrapper,
mnemonic: Mnemonic,
hd_path: DerivationPath,
id: LoginId,
password: &UserPassword,
@@ -185,7 +185,7 @@ fn store_login_with_multiple_accounts_at_file(
/// account in the list of accounts associated with the encrypted entry. The inner id for this
/// entry will be set to the same as the outer, unencrypted, id.
pub(crate) fn append_account_to_login(
mnemonic: ZeroizeMnemonicWrapper,
mnemonic: Mnemonic,
hd_path: DerivationPath,
id: LoginId,
inner_id: AccountId,
@@ -201,7 +201,7 @@ pub(crate) fn append_account_to_login(
fn append_account_to_login_at_file(
filepath: &Path,
mnemonic: ZeroizeMnemonicWrapper,
mnemonic: Mnemonic,
hd_path: DerivationPath,
id: LoginId,
inner_id: AccountId,
@@ -422,19 +422,12 @@ mod tests {
fn store_single_login() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
store_login_at_file(
&wallet_file,
account1.into_cloned_inner(),
hd_path,
id1.clone(),
&password,
)
.unwrap();
store_login_at_file(&wallet_file, account1, hd_path, id1.clone(), &password).unwrap();
let stored_wallet = load_existing_wallet_at_file(&wallet_file).unwrap();
assert_eq!(stored_wallet.len(), 1);
@@ -450,7 +443,7 @@ mod tests {
fn store_single_login_with_multi() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -478,7 +471,7 @@ mod tests {
fn store_twice_for_the_same_id_fails() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -486,7 +479,7 @@ mod tests {
// Store the first login
store_login_at_file(
&wallet_file,
account1.unchecked_clone_inner(),
account1.clone(),
hd_path.clone(),
id1.clone(),
&password,
@@ -495,13 +488,7 @@ mod tests {
// and storing the same id again fails
assert!(matches!(
store_login_at_file(
&wallet_file,
account1.into_cloned_inner(),
hd_path,
id1,
&password,
),
store_login_at_file(&wallet_file, account1, hd_path, id1, &password,),
Err(BackendError::WalletLoginIdAlreadyExists),
));
}
@@ -510,7 +497,7 @@ mod tests {
fn store_twice_for_the_same_id_fails_with_multiple() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -542,20 +529,13 @@ mod tests {
fn load_with_wrong_password_fails() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let bad_password = UserPassword::new("bad-password".to_string());
let id1 = LoginId::new("first".to_string());
store_login_at_file(
&wallet_file,
account1.into_cloned_inner(),
hd_path,
id1.clone(),
&password,
)
.unwrap();
store_login_at_file(&wallet_file, account1, hd_path, id1.clone(), &password).unwrap();
// Trying to load it with wrong password now fails
assert!(matches!(
@@ -568,7 +548,7 @@ mod tests {
fn load_with_wrong_password_fails_with_multi() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let bad_password = UserPassword::new("bad-password".to_string());
@@ -594,20 +574,13 @@ mod tests {
fn load_with_wrong_id_fails() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
let id2 = LoginId::new("second".to_string());
store_login_at_file(
&wallet_file,
account1.into_cloned_inner(),
hd_path,
id1,
&password,
)
.unwrap();
store_login_at_file(&wallet_file, account1, hd_path, id1, &password).unwrap();
// Trying to load with the wrong id
assert!(matches!(
@@ -620,7 +593,7 @@ mod tests {
fn load_with_wrong_id_fails_with_multi() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -640,14 +613,14 @@ mod tests {
fn store_and_load_a_single_login() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
store_login_at_file(
&wallet_file,
account1.unchecked_clone_inner(),
account1.clone(),
hd_path.clone(),
id1.clone(),
&password,
@@ -656,7 +629,7 @@ mod tests {
let loaded_login = load_existing_login_at_file(&wallet_file, &id1, &password).unwrap();
let acc = loaded_login.as_mnemonic_account().unwrap();
assert_eq!(account1.as_ref(), acc.mnemonic());
assert_eq!(&account1, acc.mnemonic());
assert_eq!(&hd_path, acc.hd_path());
}
@@ -664,7 +637,7 @@ mod tests {
fn store_and_load_a_single_login_with_multi() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let acc1 = ZeroizeMnemonicWrapper::generate_random();
let acc1 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -685,7 +658,7 @@ mod tests {
.get_account(&DEFAULT_FIRST_ACCOUNT_NAME.into())
.unwrap();
assert_eq!(account.id().as_ref(), DEFAULT_FIRST_ACCOUNT_NAME);
assert_eq!(account.mnemonic(), acc1.as_ref());
assert_eq!(account.mnemonic(), &acc1);
assert_eq!(account.hd_path(), &hd_path);
}
@@ -693,8 +666,8 @@ mod tests {
fn store_a_second_login_with_a_different_password_fails() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account2 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let account2 = Mnemonic::generate(24).unwrap();
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let bad_password = UserPassword::new("bad-password".to_string());
@@ -703,7 +676,7 @@ mod tests {
store_login_at_file(
&wallet_file,
account1.into_cloned_inner(),
account1,
cosmos_hd_path.clone(),
id1,
&password,
@@ -712,13 +685,7 @@ mod tests {
// Can't store a second login if you use different password
assert!(matches!(
store_login_at_file(
&wallet_file,
account2.into_cloned_inner(),
cosmos_hd_path,
id2,
&bad_password
),
store_login_at_file(&wallet_file, account2, cosmos_hd_path, id2, &bad_password),
Err(BackendError::WalletDifferentPasswordDetected),
));
}
@@ -727,8 +694,8 @@ mod tests {
fn store_a_second_login_with_a_different_password_fails_with_multi() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account2 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let account2 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let bad_password = UserPassword::new("bad-password".to_string());
@@ -761,8 +728,8 @@ mod tests {
fn store_two_mnemonic_accounts_gives_different_salts_and_iv() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account2 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let account2 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let different_hd_path: DerivationPath = "m".parse().unwrap();
let password = UserPassword::new("password".to_string());
@@ -770,14 +737,7 @@ mod tests {
let id2 = LoginId::new("second".to_string());
// Store the first account
store_login_at_file(
&wallet_file,
account1.into_cloned_inner(),
hd_path,
id1,
&password,
)
.unwrap();
store_login_at_file(&wallet_file, account1, hd_path, id1, &password).unwrap();
let stored_wallet = load_existing_wallet_at_file(&wallet_file).unwrap();
let encrypted_blob = &stored_wallet
@@ -790,14 +750,7 @@ mod tests {
let original_salt = encrypted_blob.salt().to_vec();
// Add an extra account
store_login_at_file(
&wallet_file,
account2.into_cloned_inner(),
different_hd_path,
id2,
&password,
)
.unwrap();
store_login_at_file(&wallet_file, account2, different_hd_path, id2, &password).unwrap();
let loaded_accounts = load_existing_wallet_at_file(&wallet_file).unwrap();
assert_eq!(loaded_accounts.len(), 2);
@@ -815,8 +768,8 @@ mod tests {
fn store_two_mnemonic_accounts_using_two_logins() {
let store_dir = tempdir().unwrap();
let wallet = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account2 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let account2 = Mnemonic::generate(24).unwrap();
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let different_hd_path: DerivationPath = "m".parse().unwrap();
let password = UserPassword::new("password".to_string());
@@ -826,7 +779,7 @@ mod tests {
// Store the first account
store_login_at_file(
&wallet,
account1.unchecked_clone_inner(),
account1.clone(),
cosmos_hd_path.clone(),
id1.clone(),
&password,
@@ -835,13 +788,13 @@ mod tests {
let login = load_existing_login_at_file(&wallet, &id1, &password).unwrap();
let acc = login.as_mnemonic_account().unwrap();
assert_eq!(account1.as_ref(), acc.mnemonic());
assert_eq!(&account1, acc.mnemonic());
assert_eq!(&cosmos_hd_path, acc.hd_path());
// Add an extra account
store_login_at_file(
&wallet,
account2.unchecked_clone_inner(),
account2.clone(),
different_hd_path.clone(),
id2.clone(),
&password,
@@ -851,12 +804,12 @@ mod tests {
// first account should be unchanged
let loaded_login = load_existing_login_at_file(&wallet, &id1, &password).unwrap();
let acc1 = loaded_login.as_mnemonic_account().unwrap();
assert_eq!(account1.as_ref(), acc1.mnemonic());
assert_eq!(&account1, acc1.mnemonic());
assert_eq!(&cosmos_hd_path, acc1.hd_path());
let loaded_login = load_existing_login_at_file(&wallet, &id2, &password).unwrap();
let acc2 = loaded_login.as_mnemonic_account().unwrap();
assert_eq!(account2.as_ref(), acc2.mnemonic());
assert_eq!(&account2, acc2.mnemonic());
assert_eq!(&different_hd_path, acc2.hd_path());
}
@@ -864,8 +817,8 @@ mod tests {
fn store_one_mnemonic_account_and_one_multi_account() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account2 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let account2 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let different_hd_path: DerivationPath = "m".parse().unwrap();
let password = UserPassword::new("password".to_string());
@@ -875,7 +828,7 @@ mod tests {
// Store the first account
store_login_at_file(
&wallet_file,
account1.unchecked_clone_inner(),
account1.clone(),
hd_path.clone(),
id1.clone(),
&password,
@@ -884,7 +837,7 @@ mod tests {
let loaded_login = load_existing_login_at_file(&wallet_file, &id1, &password).unwrap();
let acc = loaded_login.as_mnemonic_account().unwrap();
assert_eq!(account1.as_ref(), acc.mnemonic());
assert_eq!(&account1, acc.mnemonic());
assert_eq!(&hd_path, acc.hd_path());
// Add an extra account
@@ -900,7 +853,7 @@ mod tests {
// first account should be unchanged
let loaded_login = load_existing_login_at_file(&wallet_file, &id1, &password).unwrap();
let acc1 = loaded_login.as_mnemonic_account().unwrap();
assert_eq!(account1.as_ref(), acc1.mnemonic());
assert_eq!(&account1, acc1.mnemonic());
assert_eq!(&hd_path, acc1.hd_path());
let loaded_login = load_existing_login_at_file(&wallet_file, &id2, &password).unwrap();
@@ -910,7 +863,7 @@ mod tests {
.get_account(&DEFAULT_FIRST_ACCOUNT_NAME.into())
.unwrap();
assert_eq!(account.id().as_ref(), DEFAULT_FIRST_ACCOUNT_NAME);
assert_eq!(account.mnemonic(), account2.as_ref());
assert_eq!(account.mnemonic(), &account2);
assert_eq!(account.hd_path(), &different_hd_path);
}
@@ -918,7 +871,7 @@ mod tests {
fn remove_non_existent_id_fails() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -938,8 +891,8 @@ mod tests {
fn store_and_remove_wallet_login_information() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account2 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let account2 = Mnemonic::generate(24).unwrap();
let cosmos_hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let different_hd_path: DerivationPath = "m".parse().unwrap();
let password = UserPassword::new("password".to_string());
@@ -949,7 +902,7 @@ mod tests {
// Store two accounts with two different passwords
store_login_at_file(
&wallet_file,
account1.unchecked_clone_inner(),
account1.clone(),
cosmos_hd_path.clone(),
id1.clone(),
&password,
@@ -957,7 +910,7 @@ mod tests {
.unwrap();
store_login_at_file(
&wallet_file,
account2.unchecked_clone_inner(),
account2.clone(),
different_hd_path.clone(),
id2.clone(),
&password,
@@ -967,12 +920,12 @@ mod tests {
// Load and compare
let loaded_login = load_existing_login_at_file(&wallet_file, &id1, &password).unwrap();
let acc1 = loaded_login.as_mnemonic_account().unwrap();
assert_eq!(account1.as_ref(), acc1.mnemonic());
assert_eq!(&account1, acc1.mnemonic());
assert_eq!(&cosmos_hd_path, acc1.hd_path());
let loaded_login = load_existing_login_at_file(&wallet_file, &id2, &password).unwrap();
let acc2 = loaded_login.as_mnemonic_account().unwrap();
assert_eq!(account2.as_ref(), acc2.mnemonic());
assert_eq!(&account2, acc2.mnemonic());
assert_eq!(&different_hd_path, acc2.hd_path());
// Delete the second account
@@ -981,7 +934,7 @@ mod tests {
// The first account should be unchanged
let loaded_login = load_existing_login_at_file(&wallet_file, &id1, &password).unwrap();
let acc1 = loaded_login.as_mnemonic_account().unwrap();
assert_eq!(account1.as_ref(), acc1.mnemonic());
assert_eq!(&account1, acc1.mnemonic());
assert_eq!(&cosmos_hd_path, acc1.hd_path());
// And we can't load the second one anymore
@@ -1008,8 +961,8 @@ mod tests {
fn append_account_converts_the_type() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account2 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let account2 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -1017,7 +970,7 @@ mod tests {
store_login_at_file(
&wallet_file,
account1.unchecked_clone_inner(),
account1.clone(),
hd_path.clone(),
id1.clone(),
&password,
@@ -1027,7 +980,7 @@ mod tests {
// Check that it's there as the correct non-multiple type
let loaded_login = load_existing_login_at_file(&wallet_file, &id1, &password).unwrap();
let acc = loaded_login.as_mnemonic_account().unwrap();
assert_eq!(acc.mnemonic(), account1.as_ref());
assert_eq!(acc.mnemonic(), &account1);
assert_eq!(acc.hd_path(), &hd_path);
append_account_to_login_at_file(
@@ -1044,14 +997,8 @@ mod tests {
let loaded_login = load_existing_login_at_file(&wallet_file, &id1, &password).unwrap();
let loaded_accounts = loaded_login.as_multiple_accounts().unwrap();
let expected = vec![
WalletAccount::new(
id1.into(),
MnemonicAccount::new(account1.into_cloned_inner(), hd_path.clone()),
),
WalletAccount::new(
id2,
MnemonicAccount::new(account2.into_cloned_inner(), hd_path),
),
WalletAccount::new(id1.into(), MnemonicAccount::new(account1, hd_path.clone())),
WalletAccount::new(id2, MnemonicAccount::new(account2, hd_path)),
]
.into();
assert_eq!(loaded_accounts, &expected);
@@ -1061,10 +1008,10 @@ mod tests {
fn append_accounts_to_existing_login() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account2 = ZeroizeMnemonicWrapper::generate_random();
let account3 = ZeroizeMnemonicWrapper::generate_random();
let account4 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let account2 = Mnemonic::generate(24).unwrap();
let account3 = Mnemonic::generate(24).unwrap();
let account4 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -1074,7 +1021,7 @@ mod tests {
store_login_at_file(
&wallet_file,
account1.unchecked_clone_inner(),
account1.clone(),
hd_path.clone(),
id1.clone(),
&password,
@@ -1083,7 +1030,7 @@ mod tests {
store_login_at_file(
&wallet_file,
account2.unchecked_clone_inner(),
account2.clone(),
hd_path.clone(),
id2.clone(),
&password,
@@ -1093,7 +1040,7 @@ mod tests {
// Check that it's there as the correct non-multiple type
let loaded_login = load_existing_login_at_file(&wallet_file, &id2, &password).unwrap();
let acc2 = loaded_login.as_mnemonic_account().unwrap();
assert_eq!(acc2.mnemonic(), account2.as_ref());
assert_eq!(acc2.mnemonic(), &account2);
assert_eq!(acc2.hd_path(), &hd_path);
// Add a third and fourth mnenonic grouped together with the second one
@@ -1119,24 +1066,15 @@ mod tests {
// Check that we can load all four
let loaded_login = load_existing_login_at_file(&wallet_file, &id1, &password).unwrap();
let acc1 = loaded_login.as_mnemonic_account().unwrap();
assert_eq!(acc1.mnemonic(), account1.as_ref());
assert_eq!(acc1.mnemonic(), &account1);
assert_eq!(acc1.hd_path(), &hd_path);
let loaded_login = load_existing_login_at_file(&wallet_file, &id2, &password).unwrap();
let loaded_accounts = loaded_login.as_multiple_accounts().unwrap();
let expected = vec![
WalletAccount::new(
id2.into(),
MnemonicAccount::new(account2.into_cloned_inner(), hd_path.clone()),
),
WalletAccount::new(
id3,
MnemonicAccount::new(account3.into_cloned_inner(), hd_path.clone()),
),
WalletAccount::new(
id4,
MnemonicAccount::new(account4.into_cloned_inner(), hd_path),
),
WalletAccount::new(id2.into(), MnemonicAccount::new(account2, hd_path.clone())),
WalletAccount::new(id3, MnemonicAccount::new(account3, hd_path.clone())),
WalletAccount::new(id4, MnemonicAccount::new(account4, hd_path)),
]
.into();
assert_eq!(loaded_accounts, &expected);
@@ -1146,10 +1084,10 @@ mod tests {
fn append_accounts_to_existing_login_with_multi() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account2 = ZeroizeMnemonicWrapper::generate_random();
let account3 = ZeroizeMnemonicWrapper::generate_random();
let account4 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let account2 = Mnemonic::generate(24).unwrap();
let account3 = Mnemonic::generate(24).unwrap();
let account4 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -1200,7 +1138,7 @@ mod tests {
let loaded_accounts = loaded_login.as_multiple_accounts().unwrap();
let expected = vec![WalletAccount::new(
DEFAULT_FIRST_ACCOUNT_NAME.into(),
MnemonicAccount::new(account1.into_cloned_inner(), hd_path.clone()),
MnemonicAccount::new(account1, hd_path.clone()),
)]
.into();
assert_eq!(loaded_accounts, &expected);
@@ -1210,16 +1148,10 @@ mod tests {
let expected = vec![
WalletAccount::new(
DEFAULT_FIRST_ACCOUNT_NAME.into(),
MnemonicAccount::new(account2.into_cloned_inner(), hd_path.clone()),
),
WalletAccount::new(
id3,
MnemonicAccount::new(account3.into_cloned_inner(), hd_path.clone()),
),
WalletAccount::new(
id4,
MnemonicAccount::new(account4.into_cloned_inner(), hd_path),
MnemonicAccount::new(account2, hd_path.clone()),
),
WalletAccount::new(id3, MnemonicAccount::new(account3, hd_path.clone())),
WalletAccount::new(id4, MnemonicAccount::new(account4, hd_path)),
]
.into();
assert_eq!(loaded_accounts, &expected);
@@ -1229,7 +1161,7 @@ mod tests {
fn append_the_same_mnemonic_twice_fails() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -1254,21 +1186,14 @@ mod tests {
fn delete_the_same_account_twice_for_a_login_fails() {
let store_dir = tempdir().unwrap();
let wallet = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account2 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let account2 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
let id2 = AccountId::new("second".to_string());
store_login_at_file(
&wallet,
account1.into_cloned_inner(),
hd_path.clone(),
id1.clone(),
&password,
)
.unwrap();
store_login_at_file(&wallet, account1, hd_path.clone(), id1.clone(), &password).unwrap();
append_account_to_login_at_file(
&wallet,
@@ -1292,8 +1217,8 @@ mod tests {
fn delete_the_same_account_twice_for_a_login_fails_with_multi() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account2 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let account2 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -1330,9 +1255,9 @@ mod tests {
fn delete_appended_account_doesnt_affect_others() {
let store_dir = tempdir().unwrap();
let wallet_file = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account2 = ZeroizeMnemonicWrapper::generate_random();
let account3 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let account2 = Mnemonic::generate(24).unwrap();
let account3 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -1341,7 +1266,7 @@ mod tests {
store_login_at_file(
&wallet_file,
account1.into_cloned_inner(),
account1,
hd_path.clone(),
id1.clone(),
&password,
@@ -1350,7 +1275,7 @@ mod tests {
store_login_at_file(
&wallet_file,
account2.unchecked_clone_inner(),
account2.clone(),
hd_path.clone(),
id2.clone(),
&password,
@@ -1373,14 +1298,8 @@ mod tests {
let loaded_login = load_existing_login_at_file(&wallet_file, &id2, &password).unwrap();
let loaded_accounts = loaded_login.as_multiple_accounts().unwrap();
let expected = vec![
WalletAccount::new(
id2.into(),
MnemonicAccount::new(account2.into_cloned_inner(), hd_path.clone()),
),
WalletAccount::new(
id3,
MnemonicAccount::new(account3.into_cloned_inner(), hd_path),
),
WalletAccount::new(id2.into(), MnemonicAccount::new(account2, hd_path.clone())),
WalletAccount::new(id3, MnemonicAccount::new(account3, hd_path)),
]
.into();
assert_eq!(loaded_accounts, &expected);
@@ -1390,8 +1309,8 @@ mod tests {
fn remove_all_accounts_for_a_login_removes_the_file_when_empty() {
let store_dir = tempdir().unwrap();
let wallet = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account2 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let account2 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -1439,9 +1358,9 @@ mod tests {
fn remove_all_accounts_for_a_login_removes_that_login() {
let store_dir = tempdir().unwrap();
let wallet = store_dir.path().join(WALLET_INFO_FILENAME);
let account1 = ZeroizeMnemonicWrapper::generate_random();
let account2 = ZeroizeMnemonicWrapper::generate_random();
let account3 = ZeroizeMnemonicWrapper::generate_random();
let account1 = Mnemonic::generate(24).unwrap();
let account2 = Mnemonic::generate(24).unwrap();
let account3 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -1496,7 +1415,7 @@ mod tests {
let acc3 = loaded_login.as_multiple_accounts().unwrap();
let expected = vec![WalletAccount::new(
DEFAULT_FIRST_ACCOUNT_NAME.into(),
MnemonicAccount::new(account3.into_cloned_inner(), hd_path),
MnemonicAccount::new(account3, hd_path),
)]
.into();
assert_eq!(acc3, &expected);
@@ -1506,10 +1425,10 @@ mod tests {
fn append_accounts_and_remove_appended_accounts() {
let store_dir = tempdir().unwrap();
let wallet = store_dir.path().join(WALLET_INFO_FILENAME);
let acc1 = ZeroizeMnemonicWrapper::generate_random();
let acc2 = ZeroizeMnemonicWrapper::generate_random();
let acc3 = ZeroizeMnemonicWrapper::generate_random();
let acc4 = ZeroizeMnemonicWrapper::generate_random();
let acc1 = Mnemonic::generate(24).unwrap();
let acc2 = Mnemonic::generate(24).unwrap();
let acc3 = Mnemonic::generate(24).unwrap();
let acc4 = Mnemonic::generate(24).unwrap();
let hd_path: DerivationPath = COSMOS_DERIVATION_PATH.parse().unwrap();
let password = UserPassword::new("password".to_string());
let id1 = LoginId::new("first".to_string());
@@ -1519,7 +1438,7 @@ mod tests {
store_login_at_file(
&wallet,
acc1.unchecked_clone_inner(),
acc1.clone(),
hd_path.clone(),
id1.clone(),
&password,
@@ -1528,7 +1447,7 @@ mod tests {
store_login_at_file(
&wallet,
acc2.unchecked_clone_inner(),
acc2.clone(),
hd_path.clone(),
id2.clone(),
&password,
@@ -1564,12 +1483,9 @@ mod tests {
let expected = vec![
WalletAccount::new(
id2.clone().into(),
MnemonicAccount::new(acc2.into_cloned_inner(), hd_path.clone()),
),
WalletAccount::new(
id4.clone(),
MnemonicAccount::new(acc4.into_cloned_inner(), hd_path.clone()),
MnemonicAccount::new(acc2, hd_path.clone()),
),
WalletAccount::new(id4.clone(), MnemonicAccount::new(acc4, hd_path.clone())),
]
.into();
assert_eq!(loaded_accounts, &expected);
@@ -1585,7 +1501,7 @@ mod tests {
// The first login is still available
let loaded_login = load_existing_login_at_file(&wallet, &id1, &password).unwrap();
let account = loaded_login.as_mnemonic_account().unwrap();
assert_eq!(account.mnemonic(), acc1.as_ref());
assert_eq!(account.mnemonic(), &acc1);
assert_eq!(account.hd_path(), &hd_path);
}
@@ -1,13 +1,12 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use serde::{Deserialize, Serialize};
use std::fmt;
use serde::{Deserialize, Deserializer, Serialize};
use zeroize::Zeroize;
use zeroize::{Zeroize, Zeroizing};
// The `LoginId` is the top level id in the wallet file, and is not stored encrypted
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) struct LoginId(String);
impl LoginId {
@@ -81,26 +80,4 @@ impl fmt::Display for AccountId {
}
// simple wrapper for String that will get zeroized on drop
#[derive(Zeroize)]
#[zeroize(drop)]
pub struct UserPassword(String);
impl UserPassword {
#[cfg(test)]
pub(crate) fn new(inner: String) -> Self {
UserPassword(inner)
}
pub(crate) fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
}
impl<'de> Deserialize<'de> for UserPassword {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(UserPassword(String::deserialize(deserializer)?))
}
}
pub type UserPassword = Zeroizing<String>;
+1 -1
View File
@@ -16,7 +16,7 @@ pretty_env_logger = "0.4"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1.11", features = [ "net", "rt-multi-thread", "macros", "signal"] }
bip39 = "1.0.1"
bip39 = { workspace = true }
anyhow = "1"
tap = "1"