Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add hidden types and seed words to key manager #4925

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5841cde
first commit
jorgeantonio21 Nov 11, 2022
cc21bd9
add seed words
jorgeantonio21 Nov 15, 2022
68bc795
first commit
jorgeantonio21 Nov 15, 2022
9b22bc6
merge development and resolve conflicts
jorgeantonio21 Nov 16, 2022
8b5dca7
address PR changes
jorgeantonio21 Nov 16, 2022
1f0c191
revert unnecessary changes
jorgeantonio21 Nov 16, 2022
b703522
add imports
jorgeantonio21 Nov 17, 2022
f39caac
add serde imports
jorgeantonio21 Nov 17, 2022
2b73026
merge development and resolve conflicts
jorgeantonio21 Nov 18, 2022
bf78cd6
update tari-utilities tag version
jorgeantonio21 Nov 18, 2022
7d7c25c
remove unused dependencies
jorgeantonio21 Nov 18, 2022
f0a16bc
update dependencies and merge development
jorgeantonio21 Nov 21, 2022
85f3b00
update to newer version of tari-crypto + resolve compiler errors
jorgeantonio21 Nov 21, 2022
8d65187
improve code chunks
jorgeantonio21 Nov 21, 2022
b2c6912
Merge branch 'development' into ja-add-zeroize-to-kdfs
jorgeantonio21 Nov 21, 2022
c98c1cd
merge development and compiled tests
jorgeantonio21 Nov 21, 2022
dd08109
catching bugs
jorgeantonio21 Nov 21, 2022
7ebbb1b
add comments
jorgeantonio21 Nov 21, 2022
654364d
add refactor
jorgeantonio21 Nov 21, 2022
75ee612
cargo fmt
jorgeantonio21 Nov 21, 2022
7924a23
refactor get_recovery_seed
jorgeantonio21 Nov 21, 2022
4568c71
Merge branch 'development' into ja-add-zeroize-to-kdfs
jorgeantonio21 Nov 21, 2022
a59985b
further refactor
jorgeantonio21 Nov 21, 2022
d284a4f
Merge branch 'development' into ja-add-zeroize-to-kdfs
jorgeantonio21 Nov 22, 2022
0808539
address PR comments
jorgeantonio21 Nov 22, 2022
c450789
address one more comment
jorgeantonio21 Nov 22, 2022
992b62f
reduce allocations, while preserving security
jorgeantonio21 Nov 22, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
678 changes: 415 additions & 263 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion applications/tari_app_grpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ edition = "2018"
tari_common_types = { version = "^0.38", path = "../../base_layer/common_types" }
tari_comms = { path = "../../comms/core" }
tari_core = { path = "../../base_layer/core" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.15.7" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.16.0" }
tari_script = { path = "../../infrastructure/tari_script" }
tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag="v0.4.7" }

Expand Down
2 changes: 1 addition & 1 deletion applications/tari_app_utilities/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ license = "BSD-3-Clause"

[dependencies]
tari_comms = { path = "../../comms/core" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.15.7" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.16.0" }
tari_common = { path = "../../common" }
tari_common_types = { path = "../../base_layer/common_types" }
tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag="v0.4.7" }
Expand Down
2 changes: 1 addition & 1 deletion applications/tari_base_node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ tari_comms = { path = "../../comms/core", features = ["rpc"] }
tari_common_types = { path = "../../base_layer/common_types" }
tari_comms_dht = { path = "../../comms/dht" }
tari_core = { path = "../../base_layer/core", default-features = false, features = ["transactions"] }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.15.7" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.16.0" }
tari_libtor = { path = "../../infrastructure/libtor", optional = true }
tari_mmr = { path = "../../base_layer/mmr", features = ["native_bitmap"] }
tari_p2p = { path = "../../base_layer/p2p", features = ["auto-update"] }
Expand Down
2 changes: 1 addition & 1 deletion applications/tari_console_wallet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ license = "BSD-3-Clause"

[dependencies]
tari_wallet = { path = "../../base_layer/wallet", features = ["bundled_sqlite"] }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.15.7" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.16.0" }
tari_common = { path = "../../common" }
tari_app_utilities = { path = "../tari_app_utilities" }
tari_comms = { path = "../../comms/core" }
Expand Down
2 changes: 1 addition & 1 deletion applications/tari_merge_mining_proxy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ tari_common = { path = "../../common" }
tari_comms = { path = "../../comms/core" }
tari_core = { path = "../../base_layer/core", default-features = false, features = ["transactions"] }
tari_app_utilities = { path = "../tari_app_utilities" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.15.7" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.16.0" }
tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag="v0.4.7" }
tari_base_node_grpc_client = {path="../../clients/rust/base_node_grpc_client" }
tari_wallet_grpc_client = {path="../../clients/rust/wallet_grpc_client" }
Expand Down
2 changes: 1 addition & 1 deletion applications/tari_miner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ tari_common_types = { path = "../../base_layer/common_types" }
tari_comms = { path = "../../comms/core" }
tari_app_utilities = { path = "../tari_app_utilities" }
tari_app_grpc = { path = "../tari_app_grpc" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.15.7" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.16.0" }
tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag="v0.4.7" }

crossterm = { version = "0.25.0" }
Expand Down
2 changes: 1 addition & 1 deletion base_layer/common_types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ version = "0.38.8"
edition = "2018"

[dependencies]
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.15.7" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.16.0" }
tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag="v0.4.7" }

base64 = "0.13.0"
Expand Down
2 changes: 1 addition & 1 deletion base_layer/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ tari_common_types = { version = "^0.38", path = "../../base_layer/common_types"
tari_comms = { version = "^0.38", path = "../../comms/core" }
tari_comms_dht = { version = "^0.38", path = "../../comms/dht" }
tari_comms_rpc_macros = { version = "^0.38", path = "../../comms/rpc_macros" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.15.7" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.16.0" }
tari_metrics = { path = "../../infrastructure/metrics" }
tari_mmr = { version = "^0.38", path = "../../base_layer/mmr", optional = true, features = ["native_bitmap"] }
tari_p2p = { version = "^0.38", path = "../../base_layer/p2p" }
Expand Down
4 changes: 2 additions & 2 deletions base_layer/key_manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ crate-type = ["lib", "cdylib"]
# NB: All dependencies must support or be gated for the WASM target.
[dependencies]
tari_common_types = { version = "^0.38", path = "../../base_layer/common_types", optional = true }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.15.7" }
tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag="v0.4.7" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.16.0" }
tari_utilities = { git = "https://github.com/AaronFeickert/tari_utilities.git", branch="clandestine" }

arrayvec = "0.7.1"
argon2 = { version = "0.4.1", features = ["std", "alloc"] }
Expand Down
106 changes: 74 additions & 32 deletions base_layer/key_manager/src/cipher_seed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::{convert::TryFrom, mem::size_of};
use std::{convert::TryFrom, mem::size_of, str::FromStr};

use argon2;
use chacha20::{
Expand All @@ -34,12 +34,16 @@ use rand::{rngs::OsRng, RngCore};
use serde::{Deserialize, Serialize};
use subtle::ConstantTimeEq;
use tari_crypto::hash::blake2::Blake256;
use tari_utilities::{hidden::Hidden, SafePassword};
jorgeantonio21 marked this conversation as resolved.
Show resolved Hide resolved
use zeroize::{Zeroize, Zeroizing};

use crate::{
error::KeyManagerError,
mac_domain_hasher,
mnemonic::{from_bytes, to_bytes, to_bytes_with_language, Mnemonic, MnemonicLanguage},
CipherSeedEncryptionKey,
CipherSeedMacKey,
SeedWords,
LABEL_ARGON_ENCODING,
LABEL_CHACHA20_ENCODING,
LABEL_MAC_GENERATION,
Expand Down Expand Up @@ -121,7 +125,7 @@ pub struct CipherSeed {
}

// This is a separate type to make the linter happy
type DerivedCipherSeedKeys = Result<(Zeroizing<Vec<u8>>, Zeroizing<Vec<u8>>), KeyManagerError>;
type DerivedCipherSeedKeys = Result<(CipherSeedEncryptionKey, CipherSeedMacKey), KeyManagerError>;

impl CipherSeed {
#[cfg(not(target_arch = "wasm32"))]
Expand Down Expand Up @@ -165,9 +169,12 @@ impl CipherSeed {
}

/// Generate an encrypted seed from a passphrase
pub fn encipher(&self, passphrase: Option<String>) -> Result<Vec<u8>, KeyManagerError> {
pub fn encipher(&self, passphrase: Option<SafePassword>) -> Result<Vec<u8>, KeyManagerError> {
// Derive encryption and MAC keys from passphrase and main salt
let passphrase = Zeroizing::new(passphrase.unwrap_or_else(|| DEFAULT_CIPHER_SEED_PASSPHRASE.to_string()));
let passphrase = passphrase.unwrap_or_else(|| {
SafePassword::from_str(DEFAULT_CIPHER_SEED_PASSPHRASE)
.expect("Failed to parse default cipher seed passphrase to SafePassword")
});
let (encryption_key, mac_key) = Self::derive_keys(&passphrase, self.salt.as_ref())?;

// Generate the MAC
Expand All @@ -176,7 +183,7 @@ impl CipherSeed {
self.entropy.as_ref(),
CIPHER_SEED_VERSION,
self.salt.as_ref(),
mac_key.as_ref(),
mac_key.reveal(),
jorgeantonio21 marked this conversation as resolved.
Show resolved Hide resolved
)?;

// Assemble the secret data to be encrypted: birthday, entropy, MAC
Expand All @@ -188,7 +195,7 @@ impl CipherSeed {
secret_data.extend(&mac);

// Encrypt the secret data
Self::apply_stream_cipher(&mut secret_data, encryption_key.as_ref(), self.salt.as_ref())?;
Self::apply_stream_cipher(&mut secret_data, encryption_key.reveal(), self.salt.as_ref())?;
jorgeantonio21 marked this conversation as resolved.
Show resolved Hide resolved

// Assemble the final seed: version, main salt, secret data, checksum
let mut encrypted_seed =
Expand All @@ -206,7 +213,10 @@ impl CipherSeed {
}

/// Recover a seed from encrypted data and a passphrase
pub fn from_enciphered_bytes(encrypted_seed: &[u8], passphrase: Option<String>) -> Result<Self, KeyManagerError> {
pub fn from_enciphered_bytes(
encrypted_seed: &[u8],
passphrase: Option<SafePassword>,
) -> Result<Self, KeyManagerError> {
// Check the length: version, birthday, entropy, MAC, salt, checksum
if encrypted_seed.len() !=
1 + CIPHER_SEED_BIRTHDAY_BYTES +
Expand Down Expand Up @@ -241,7 +251,10 @@ impl CipherSeed {
}

// Derive encryption and MAC keys from passphrase and main salt
let passphrase = Zeroizing::new(passphrase.unwrap_or_else(|| DEFAULT_CIPHER_SEED_PASSPHRASE.to_string()));
let passphrase = passphrase.unwrap_or_else(|| {
SafePassword::from_str(DEFAULT_CIPHER_SEED_PASSPHRASE)
.expect("Failed to parse default cipher seed passphrase to SafePassword")
});
let salt: Box<[u8; CIPHER_SEED_MAIN_SALT_BYTES]> = encrypted_seed
.split_off(1 + CIPHER_SEED_BIRTHDAY_BYTES + CIPHER_SEED_ENTROPY_BYTES + CIPHER_SEED_MAC_BYTES)
.into_boxed_slice()
Expand All @@ -251,7 +264,7 @@ impl CipherSeed {

// Decrypt the secret data: birthday, entropy, MAC
let mut secret_data = Zeroizing::new(encrypted_seed.split_off(1));
Self::apply_stream_cipher(&mut secret_data, encryption_key.as_ref(), salt.as_ref())?;
Self::apply_stream_cipher(&mut secret_data, encryption_key.reveal(), salt.as_ref())?;
jorgeantonio21 marked this conversation as resolved.
Show resolved Hide resolved

// Parse secret data
let mac = secret_data.split_off(CIPHER_SEED_BIRTHDAY_BYTES + CIPHER_SEED_ENTROPY_BYTES);
Expand All @@ -271,7 +284,7 @@ impl CipherSeed {
entropy.as_ref(),
version,
salt.as_ref(),
mac_key.as_ref(),
mac_key.reveal(),
jorgeantonio21 marked this conversation as resolved.
Show resolved Hide resolved
)?;

// Verify the MAC in constant time to avoid leaking data
Expand Down Expand Up @@ -343,7 +356,8 @@ impl CipherSeed {
}

/// Use Argon2 to derive encryption and MAC keys from a passphrase and main salt
fn derive_keys(passphrase: &str, salt: &[u8]) -> DerivedCipherSeedKeys {
// TODO: passhphrase should be SafePassword
fn derive_keys(passphrase: &SafePassword, salt: &[u8]) -> DerivedCipherSeedKeys {
// The Argon2 salt is derived from the main salt
let argon2_salt = mac_domain_hasher::<Blake256>(LABEL_ARGON_ENCODING)
.chain(salt)
Expand All @@ -362,15 +376,23 @@ impl CipherSeed {
.map_err(|_| KeyManagerError::CryptographicError("Problem generating Argon2 parameters".to_string()))?;

// Derive the main key from the password in place
let mut main_key = Zeroizing::new([0u8; CIPHER_SEED_ENCRYPTION_KEY_BYTES + CIPHER_SEED_MAC_KEY_BYTES]);
let mut main_key = Hidden::hide([0u8; CIPHER_SEED_ENCRYPTION_KEY_BYTES + CIPHER_SEED_MAC_KEY_BYTES]);
let hasher = argon2::Argon2::new(argon2::Algorithm::Argon2d, argon2::Version::V0x13, params);
hasher
.hash_password_into(passphrase.as_bytes(), argon2_salt, main_key.as_mut())
.hash_password_into(passphrase.reveal(), argon2_salt, main_key.reveal_mut())
.map_err(|_| KeyManagerError::CryptographicError("Problem generating Argon2 password hash".to_string()))?;

// Split off the keys
let encryption_key = Zeroizing::new(main_key.as_ref()[..CIPHER_SEED_ENCRYPTION_KEY_BYTES].to_vec());
let mac_key = Zeroizing::new(main_key.as_ref()[CIPHER_SEED_ENCRYPTION_KEY_BYTES..].to_vec());
let mut encryption_key = CipherSeedEncryptionKey::from([0u8; CIPHER_SEED_ENCRYPTION_KEY_BYTES]);
jorgeantonio21 marked this conversation as resolved.
Show resolved Hide resolved
encryption_key
.reveal_mut()
.copy_from_slice(&main_key.reveal()[..CIPHER_SEED_ENCRYPTION_KEY_BYTES]);

let mut mac_key = CipherSeedMacKey::from([0u8; CIPHER_SEED_MAC_KEY_BYTES]);
jorgeantonio21 marked this conversation as resolved.
Show resolved Hide resolved
mac_key
.reveal_mut()
.copy_from_slice(&main_key.reveal()[CIPHER_SEED_ENCRYPTION_KEY_BYTES..]);

Ok((encryption_key, mac_key))
}
}
Expand All @@ -384,16 +406,19 @@ impl Default for CipherSeed {
impl Mnemonic<CipherSeed> for CipherSeed {
/// Generates a CipherSeed that represent the provided mnemonic sequence of words, the language of the mnemonic
/// sequence is autodetected
fn from_mnemonic(mnemonic_seq: &[String], passphrase: Option<String>) -> Result<CipherSeed, KeyManagerError> {
fn from_mnemonic(
mnemonic_seq: &SeedWords,
passphrase: Option<SafePassword>,
) -> Result<CipherSeed, KeyManagerError> {
let bytes = to_bytes(mnemonic_seq)?;
CipherSeed::from_enciphered_bytes(&bytes, passphrase)
}

/// Generates a SecretKey that represent the provided mnemonic sequence of words using the specified language
fn from_mnemonic_with_language(
mnemonic_seq: &[String],
mnemonic_seq: &SeedWords,
language: MnemonicLanguage,
passphrase: Option<String>,
passphrase: Option<SafePassword>,
) -> Result<CipherSeed, KeyManagerError> {
let bytes = to_bytes_with_language(mnemonic_seq, &language)?;
CipherSeed::from_enciphered_bytes(&bytes, passphrase)
Expand All @@ -403,41 +428,51 @@ impl Mnemonic<CipherSeed> for CipherSeed {
fn to_mnemonic(
&self,
language: MnemonicLanguage,
passphrase: Option<String>,
) -> Result<Vec<String>, KeyManagerError> {
passphrase: Option<SafePassword>,
) -> Result<SeedWords, KeyManagerError> {
Ok(from_bytes(&self.encipher(passphrase)?, language)?)
}
}

#[cfg(test)]
mod test {
use std::str::FromStr;

use crc32fast::Hasher as CrcHasher;
use tari_utilities::SafePassword;

use crate::{
cipher_seed::{CipherSeed, CIPHER_SEED_VERSION},
error::KeyManagerError,
mnemonic::{Mnemonic, MnemonicLanguage},
SeedWords,
};

#[test]
fn test_cipher_seed_generation_and_deciphering() {
let seed = CipherSeed::new();

let mut enciphered_seed = seed.encipher(Some("Passphrase".to_string())).unwrap();
let mut enciphered_seed = seed
.encipher(Some(SafePassword::from_str("Passphrase").unwrap()))
.unwrap();

let deciphered_seed =
CipherSeed::from_enciphered_bytes(&enciphered_seed, Some("Passphrase".to_string())).unwrap();
CipherSeed::from_enciphered_bytes(&enciphered_seed, Some(SafePassword::from_str("Passphrase").unwrap()))
.unwrap();

assert_eq!(seed, deciphered_seed);

match CipherSeed::from_enciphered_bytes(&enciphered_seed, Some("WrongPassphrase".to_string())) {
match CipherSeed::from_enciphered_bytes(
&enciphered_seed,
Some(SafePassword::from_str("WrongPassphrase").unwrap()),
) {
Err(KeyManagerError::DecryptionFailed) => (),
_ => panic!("Version should not match"),
}

enciphered_seed[0] = CIPHER_SEED_VERSION + 1; // this is an unsupported version

match CipherSeed::from_enciphered_bytes(&enciphered_seed, Some("Passphrase".to_string())) {
match CipherSeed::from_enciphered_bytes(&enciphered_seed, Some(SafePassword::from_str("Passphrase").unwrap())) {
Err(KeyManagerError::VersionMismatch) => (),
_ => panic!("Version should not match"),
}
Expand All @@ -447,7 +482,7 @@ mod test {

// flip some bits
enciphered_seed[1] = !enciphered_seed[1];
match CipherSeed::from_enciphered_bytes(&enciphered_seed, Some("Passphrase".to_string())) {
match CipherSeed::from_enciphered_bytes(&enciphered_seed, Some(SafePassword::from_str("Passphrase").unwrap())) {
Err(KeyManagerError::CrcError) => (),
_ => panic!("Crc should not match"),
}
Expand All @@ -473,7 +508,7 @@ mod test {
enciphered_seed[(n - 4)..].copy_from_slice(&calculated_checksum);

// the MAC decryption should fail in this case
match CipherSeed::from_enciphered_bytes(&enciphered_seed, Some("passphrase".to_string())) {
match CipherSeed::from_enciphered_bytes(&enciphered_seed, Some(SafePassword::from_str("passphrase").unwrap())) {
Err(KeyManagerError::DecryptionFailed) => (),
_ => panic!("Decryption should fail"),
}
Expand All @@ -500,7 +535,7 @@ mod test {
enciphered_seed[(n - 4)..].copy_from_slice(&calculated_checksum);

// the MAC decryption should fail in this case
match CipherSeed::from_enciphered_bytes(&enciphered_seed, Some("passphrase".to_string())) {
match CipherSeed::from_enciphered_bytes(&enciphered_seed, Some(SafePassword::from_str("passphrase").unwrap())) {
Err(KeyManagerError::DecryptionFailed) => (),
_ => panic!("Decryption should fail"),
}
Expand All @@ -526,7 +561,7 @@ mod test {
enciphered_seed[(n - 4)..].copy_from_slice(&calculated_checksum);

// the MAC decryption should fail in this case
match CipherSeed::from_enciphered_bytes(&enciphered_seed, Some("passphrase".to_string())) {
match CipherSeed::from_enciphered_bytes(&enciphered_seed, Some(SafePassword::from_str("passphrase").unwrap())) {
Err(KeyManagerError::DecryptionFailed) => (),
_ => panic!("Decryption should fail"),
}
Expand Down Expand Up @@ -559,6 +594,7 @@ mod test {
.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>();
let mnemonic_seq = SeedWords::new(&mnemonic_seq);
// Language not known
match CipherSeed::from_mnemonic(&mnemonic_seq, None) {
Ok(_k) => panic!(),
Expand All @@ -575,18 +611,24 @@ mod test {
fn cipher_seed_to_and_from_mnemonic_with_passphrase() {
let seed = CipherSeed::new();
let mnemonic_seq = seed
.to_mnemonic(MnemonicLanguage::Spanish, Some("Passphrase".to_string()))
.to_mnemonic(
MnemonicLanguage::Spanish,
Some(SafePassword::from_str("Passphrase").unwrap()),
)
.expect("Couldn't convert CipherSeed to Mnemonic");
match CipherSeed::from_mnemonic(&mnemonic_seq, Some("Passphrase".to_string())) {
match CipherSeed::from_mnemonic(&mnemonic_seq, Some(SafePassword::from_str("Passphrase").unwrap())) {
Ok(mnemonic_seed) => assert_eq!(seed, mnemonic_seed),
Err(e) => panic!("Couldn't create CipherSeed from Mnemonic: {}", e),
}

let mnemonic_seq = seed
.to_mnemonic(MnemonicLanguage::Spanish, Some("Passphrase".to_string()))
.to_mnemonic(
MnemonicLanguage::Spanish,
Some(SafePassword::from_str("Passphrase").unwrap()),
)
.expect("Couldn't convert CipherSeed to Mnemonic");
assert!(
CipherSeed::from_mnemonic(&mnemonic_seq, Some("WrongPassphrase".to_string())).is_err(),
CipherSeed::from_mnemonic(&mnemonic_seq, Some(SafePassword::from_str("WrongPassphrase").unwrap())).is_err(),
"Should not be able to derive seed with wrong passphrase"
);
}
Expand Down
Loading