From aa7f7ce3f4b227d8d291189578ff2f1e3b710510 Mon Sep 17 00:00:00 2001 From: Adam Spofford Date: Tue, 11 Oct 2022 14:09:50 -0700 Subject: [PATCH 1/6] Warn if the user's identity is unencrypted --- src/dfx/src/lib/environment.rs | 6 ++++- src/dfx/src/lib/identity/identity_manager.rs | 2 +- src/dfx/src/lib/identity/mod.rs | 26 +++++++++++++++----- src/dfx/src/lib/identity/pem_encryption.rs | 26 +++++++++++--------- 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/dfx/src/lib/environment.rs b/src/dfx/src/lib/environment.rs index ee45175316..3792b2c442 100644 --- a/src/dfx/src/lib/environment.rs +++ b/src/dfx/src/lib/environment.rs @@ -11,7 +11,7 @@ use candid::Principal; use fn_error_context::context; use ic_agent::{Agent, Identity}; use semver::Version; -use slog::{Logger, Record}; +use slog::{warn, Logger, Record}; use std::borrow::Cow; use std::collections::BTreeMap; use std::fs::create_dir_all; @@ -234,6 +234,10 @@ impl<'a> AgentEnvironment<'a> { let logger = backend.get_logger().clone(); let mut identity_manager = IdentityManager::new(backend)?; let identity = identity_manager.instantiate_selected_identity()?; + if network_descriptor.is_ic && identity.insecure { + warn!(logger, "The {} identity is not stored securely. Do not use it to control a lot of cycles/ICP. Create a new identity with `dfx identity create` \ + and use it in mainnet-facing commands with the `--identity` flag", identity.name()); + } let url = network_descriptor.first_provider()?; Ok(AgentEnvironment { diff --git a/src/dfx/src/lib/identity/identity_manager.rs b/src/dfx/src/lib/identity/identity_manager.rs index 13487e4489..2bfc23782a 100644 --- a/src/dfx/src/lib/identity/identity_manager.rs +++ b/src/dfx/src/lib/identity/identity_manager.rs @@ -237,7 +237,7 @@ impl IdentityManager { let config = self.get_identity_config_or_default(name)?; let pem_path = self.get_identity_pem_path(name, &config); - let pem = pem_encryption::load_pem_file(&pem_path, Some(&config))?; + let (pem, _) = pem_encryption::load_pem_file(&pem_path, Some(&config))?; validate_pem_file(&pem)?; String::from_utf8(pem).map_err(|e| anyhow!("Could not translate pem file to text: {}", e)) } diff --git a/src/dfx/src/lib/identity/mod.rs b/src/dfx/src/lib/identity/mod.rs index 2e401d8243..9e12c8a8f1 100644 --- a/src/dfx/src/lib/identity/mod.rs +++ b/src/dfx/src/lib/identity/mod.rs @@ -62,6 +62,10 @@ pub struct Identity { /// The name of this Identity. name: String, + /// Whether this identity is stored in unencrypted form. + /// False for identities that are not stored at all. + pub insecure: bool, + /// Inner implementation of this identity. inner: Box, @@ -147,7 +151,7 @@ impl Identity { disable_encryption, } => { identity_config.encryption = create_encryption_config(disable_encryption)?; - let src_pem_content = pem_encryption::load_pem_file(&src_pem_file, None)?; + let (src_pem_content, _) = pem_encryption::load_pem_file(&src_pem_file, None)?; identity_utils::validate_pem_file(&src_pem_content)?; let dst_pem_file = manager.get_identity_pem_path(&temp_identity_name, &identity_config); @@ -202,6 +206,7 @@ impl Identity { Self { name: ANONYMOUS_IDENTITY_NAME.to_string(), inner: Box::new(AnonymousIdentity {}), + insecure: false, dir: PathBuf::new(), } } @@ -210,6 +215,7 @@ impl Identity { manager: &IdentityManager, name: &str, pem_content: &[u8], + was_encrypted: bool, ) -> DfxResult { let inner = Box::new(BasicIdentity::from_pem(pem_content).map_err(|e| { DfxError::new(IdentityError::CannotReadIdentityFile( @@ -222,6 +228,7 @@ impl Identity { name: name.to_string(), inner, dir: manager.get_identity_dir_path(name), + insecure: !was_encrypted, }) } @@ -229,6 +236,7 @@ impl Identity { manager: &IdentityManager, name: &str, pem_content: &[u8], + was_encrypted: bool, ) -> DfxResult { let inner = Box::new(Secp256k1Identity::from_pem(pem_content).map_err(|e| { DfxError::new(IdentityError::CannotReadIdentityFile( @@ -241,6 +249,7 @@ impl Identity { name: name.to_string(), inner, dir: manager.get_identity_dir_path(name), + insecure: !was_encrypted, }) } @@ -262,6 +271,7 @@ impl Identity { name: name.to_string(), inner, dir: manager.get_identity_dir_path(name), + insecure: false, }) } @@ -280,11 +290,15 @@ impl Identity { Identity::load_hardware_identity(manager, name, hsm) } else { let pem_path = manager.load_identity_pem_path(name)?; - let pem_content = pem_encryption::load_pem_file(&pem_path, Some(&config))?; - - Identity::load_secp256k1_identity(manager, name, &pem_content).or_else(|e| { - Identity::load_basic_identity(manager, name, &pem_content).map_err(|_| e) - }) + let (pem_content, was_encrypted) = + pem_encryption::load_pem_file(&pem_path, Some(&config))?; + + Identity::load_secp256k1_identity(manager, name, &pem_content, was_encrypted).or_else( + |e| { + Identity::load_basic_identity(manager, name, &pem_content, was_encrypted) + .map_err(|_| e) + }, + ) } } diff --git a/src/dfx/src/lib/identity/pem_encryption.rs b/src/dfx/src/lib/identity/pem_encryption.rs index e9159d43d4..a543837545 100644 --- a/src/dfx/src/lib/identity/pem_encryption.rs +++ b/src/dfx/src/lib/identity/pem_encryption.rs @@ -13,14 +13,18 @@ use argon2::{password_hash::PasswordHasher, Argon2}; use fn_error_context::context; /// Transparently handles all complexities regarding pem file encryption, including prompting the user for the password. +/// Returns the pem and whether the original was encrypted. /// /// Try to only load the pem file once, as the user may be prompted for the password every single time you call this function. #[context("Failed to load pem file {}.", path.to_string_lossy())] -pub fn load_pem_file(path: &Path, config: Option<&IdentityConfiguration>) -> DfxResult> { +pub fn load_pem_file( + path: &Path, + config: Option<&IdentityConfiguration>, +) -> DfxResult<(Vec, bool)> { let content = std::fs::read(path) .with_context(|| format!("Failed to read {}.", path.to_string_lossy()))?; - let content = maybe_decrypt_pem(content.as_slice(), config)?; - Ok(content) + let (content, was_encrypted) = maybe_decrypt_pem(content.as_slice(), config)?; + Ok((content, was_encrypted)) } /// Transparently handles all complexities regarding pem file encryption, including prompting the user for the password. @@ -88,22 +92,22 @@ fn maybe_encrypt_pem( /// /// If the pem file should not be encrypted, then the content is returned as is. /// +/// Additionally returns whether or not it was necessary to decrypt the file. +/// /// `maybe_encrypt_pem` does the opposite. #[context("Failed to decrypt pem file.")] fn maybe_decrypt_pem( pem_content: &[u8], config: Option<&IdentityConfiguration>, -) -> DfxResult> { +) -> DfxResult<(Vec, bool)> { if let Some(decryption_config) = config.and_then(|c| c.encryption.as_ref()) { let password = password_prompt(DecryptingToUse)?; - let result = decrypt(pem_content, decryption_config, &password); - if result.is_ok() { - // print to stderr so that output redirection works for the identity export command - eprintln!("Decryption complete."); - }; - result + let pem = decrypt(pem_content, decryption_config, &password)?; + // print to stderr so that output redirection works for the identity export command + eprintln!("Decryption complete."); + Ok((pem, true)) } else { - Ok(Vec::from(pem_content)) + Ok((Vec::from(pem_content), false)) } } From c72a621981b96fbae3ce6eac5c6aea48afe52b06 Mon Sep 17 00:00:00 2001 From: Adam Spofford Date: Tue, 11 Oct 2022 18:27:38 -0700 Subject: [PATCH 2/6] Add test --- .../expect_scripts/get_ledger_balance.exp | 18 +++ e2e/tests-dfx/identity.bash | 10 ++ script.exp | 150 ++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100755 e2e/assets/expect_scripts/get_ledger_balance.exp create mode 100755 script.exp diff --git a/e2e/assets/expect_scripts/get_ledger_balance.exp b/e2e/assets/expect_scripts/get_ledger_balance.exp new file mode 100755 index 0000000000..4ab10d8930 --- /dev/null +++ b/e2e/assets/expect_scripts/get_ledger_balance.exp @@ -0,0 +1,18 @@ +#!/usr/bin/expect -df + +# ASSUMPTION: init_alice_with_pw.exp run before this script + +match_max 100000 +set timeout 30 + +spawn dfx ledger balance --network ic --identity alice +expect "Please enter the passphrase for your identity: " +send -- "testpassword\r" +expect "Decryption complete.\r" +expect { + "WARN" { + puts stderr "Warned incorrectly for an encrypted identity" + exit 1 + } + eof {} +} diff --git a/e2e/tests-dfx/identity.bash b/e2e/tests-dfx/identity.bash index 0a215c8d9d..d8abb342f9 100644 --- a/e2e/tests-dfx/identity.bash +++ b/e2e/tests-dfx/identity.bash @@ -160,3 +160,13 @@ teardown() { assert_command dfx canister call --output idl e2e_project_frontend retrieve '("B")' assert_eq '(blob "hello")' } + +@test "using an unencrypted identity on mainnet provokes a warning" { + assert_command dfx ledger balance --network ic + assert_match WARN "$stderr" + assert_command "${BATS_TEST_DIRNAME}/../assets/expect_scripts/init_alice_with_pw.exp" + assert_command "${BATS_TEST_DIRNAME}/../assets/expect_scripts/get_ledger_balance.exp" + dfx identity new bob --disable-encryption + assert_command dfx ledger balance --network ic --identity bob + assert_match WARN "$stderr" +} diff --git a/script.exp b/script.exp new file mode 100755 index 0000000000..a9223fb258 --- /dev/null +++ b/script.exp @@ -0,0 +1,150 @@ +#!/usr/local/bin/expect -f +# +# This Expect script was generated by autoexpect on Tue Oct 11 14:43:37 2022 +# Expect and autoexpect were both written by Don Libes, NIST. +# +# Note that autoexpect does not guarantee a working script. It +# necessarily has to guess about certain things. Two reasons a script +# might fail are: +# +# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet, +# etc.) and devices discard or ignore keystrokes that arrive "too +# quickly" after prompts. If you find your new script hanging up at +# one spot, try adding a short sleep just before the previous send. +# Setting "force_conservative" to 1 (see below) makes Expect do this +# automatically - pausing briefly before sending each character. This +# pacifies every program I know of. The -c flag makes the script do +# this in the first place. The -C flag allows you to define a +# character to toggle this mode off and on. + +set force_conservative 0 ;# set to 1 to force conservative mode even if + ;# script wasn't run conservatively originally +if {$force_conservative} { + set send_slow {1 .1} + proc send {ignore arg} { + sleep .1 + exp_send -s -- $arg + } +} + +# +# 2) differing output - Some programs produce different output each time +# they run. The "date" command is an obvious example. Another is +# ftp, if it produces throughput statistics at the end of a file +# transfer. If this causes a problem, delete these patterns or replace +# them with wildcards. An alternative is to use the -p flag (for +# "prompt") which makes Expect only look for the last line of output +# (i.e., the prompt). The -P flag allows you to define a character to +# toggle this mode off and on. +# +# Read the man page for more info. +# +# -Don + + +set timeout -1 +spawn $env(SHELL) +match_max 100000 +expect -exact "\[1m\[7m%\[27m\[1m\[0m \r \r\]633;D\]633;P;Cwd=/Users/adam/Source/sdk\r\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\r +\[1;32m❯\[0m \]633;B\[K\[206C\]633;H\]633;I\[206D\[?2004h\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\r +\[1;32m❯\[0m \]633;B\[K\[206C\]633;H\]633;I\[206D" +send -- "df" +expect -exact "df" +send -- "x " +expect -exact "x " +expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx\[K\[203C\]633;H\]633;I\[202D" +send -- "identity " +expect -exact "identity " +expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx identity\[K\[194C\]633;H\]633;I\[193D" +send -- "new " +expect -exact "new " +expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx identity new\[K\[190C\]633;H\]633;I\[189D" +send -- "bob " +expect -exact "bob " +expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx identity new bob\[K\[186C\]633;H\]633;I\[185D" +send -- "\r" +expect -exact "\[?2004l\r\r +\]633;C\]633;E;dfx identity new bob \rPlease enter a passphrase for your identity: " +send -- "hunter2\r" +expect -exact "\r +\[1A\r\[2K\[1B\[1APlease enter a passphrase for your identity: \[hidden\]\r +Encryption complete.\r +Your seed phrase for identity 'bob': deposit become pink friend wisdom boss parrot modify album artist unable spatial regret disagree wild seed glare naive call top upgrade inject case result\r +This can be used to reconstruct your key in case of emergency, so write it down in a safe place.\r +\[1mCreated identity: \"bob\".(B\[m\r +\[1m\[7m%\[27m\[1m\[0m \r \r\]633;D;0\]633;P;Cwd=/Users/adam/Source/sdk\r\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;B\[K\[206C\]633;H\]633;I\[206D\[?2004h\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;B\[K\[206C\]633;H\]633;I\[206D" +send -- "df" +expect -exact "df" +send -- "x i" +expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx\[K\[203C\]633;H\]633;I\[202Di" +send -- "dentity " +expect -exact "dentity " +expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx identity\[K\[194C\]633;H\]633;I\[193D\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx identity\[K\[194C\]633;H\]633;I\[193D" +send -- "" +expect -exact "" +send -- "" +expect -exact " " +send -- "" +expect -exact " " +send -- "" +expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx identi\[K\[196C\]633;H\]633;I\[196D  " +send -- "" +expect -exact " " +send -- "" +expect -exact " " +send -- "" +expect -exact " " +send -- "" +expect -exact " " +send -- "led" +expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx le\[K\[200C\]633;H\]633;I\[200Dd" +send -- "ger ac" +expect -exact "ger ac" +expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx ledger ac\[K\[193C\]633;H\]633;I\[193D" +send -- "" +expect -exact " " +send -- "" +expect -exact " " +send -- "balance " +expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx ledger balance\[K\[188C\]633;H\]633;I\[188D \r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx ledger balance\[K\[188C\]633;H\]633;I\[187D\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx ledger balance\[K\[188C\]633;H\]633;I\[187D\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx ledger balance\[K\[188C\]633;H\]633;I\[187D\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx ledger balance\[K\[188C\]633;H\]633;I\[187D\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx ledger balance\[K\[188C\]633;H\]633;I\[187D" +send -- "--networ" +expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx ledger balance --netw\[K\[181C\]633;H\]633;I\[181Dor" +send -- "k ic --" +expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx ledger balance --network ic -\[K\[173C\]633;H\]633;I\[173D-" +send -- "identity bo" +expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;Bdfx ledger balance --network ic --identity b\[K\[162C\]633;H\]633;I\[162Do" +send -- "b\r" +expect -exact "\[?2004l\r\r +\]633;C\]633;E;dfx ledger balance --network ic --identity bob\rPlease enter the passphrase for your identity: " +send -- "hunter2\r" +expect -exact "\r +\[1A\r\[2K\[1B\[1APlease enter the passphrase for your identity: \[hidden\]\r +Decryption complete.\r +0.00000000 ICP\r +\[1m\[7m%\[27m\[1m\[0m \r \r\]633;D;0\]633;P;Cwd=/Users/adam/Source/sdk\r\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r +\[1;32m❯\[0m \]633;B\[K\[206C\]633;H\]633;I\[206D\[?2004h" +send -- "ex" +expect -exact "ex" +send -- "it\r" +expect eof From e1de0915f65589bf4b8a48977d4e41e3022e423a Mon Sep 17 00:00:00 2001 From: Adam Spofford Date: Tue, 11 Oct 2022 18:30:20 -0700 Subject: [PATCH 3/6] Add to changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4aa10c2d5c..7161aa98ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ## DFX +### feat: warn if an unencrypted identity is used on mainnet + ### fix: Save SNS canister IDs SNS canister IDs were not being parsed reliably. Now the candid file is being specified explicitly, which resolves the issue in at least some cases. From 931df86d14c44d4087a5cbb663d5d5731ae792d2 Mon Sep 17 00:00:00 2001 From: Adam Spofford Date: Wed, 12 Oct 2022 10:55:14 -0700 Subject: [PATCH 4/6] didn't mean to commit that --- script.exp | 150 ----------------------------------------------------- 1 file changed, 150 deletions(-) delete mode 100755 script.exp diff --git a/script.exp b/script.exp deleted file mode 100755 index a9223fb258..0000000000 --- a/script.exp +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/local/bin/expect -f -# -# This Expect script was generated by autoexpect on Tue Oct 11 14:43:37 2022 -# Expect and autoexpect were both written by Don Libes, NIST. -# -# Note that autoexpect does not guarantee a working script. It -# necessarily has to guess about certain things. Two reasons a script -# might fail are: -# -# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet, -# etc.) and devices discard or ignore keystrokes that arrive "too -# quickly" after prompts. If you find your new script hanging up at -# one spot, try adding a short sleep just before the previous send. -# Setting "force_conservative" to 1 (see below) makes Expect do this -# automatically - pausing briefly before sending each character. This -# pacifies every program I know of. The -c flag makes the script do -# this in the first place. The -C flag allows you to define a -# character to toggle this mode off and on. - -set force_conservative 0 ;# set to 1 to force conservative mode even if - ;# script wasn't run conservatively originally -if {$force_conservative} { - set send_slow {1 .1} - proc send {ignore arg} { - sleep .1 - exp_send -s -- $arg - } -} - -# -# 2) differing output - Some programs produce different output each time -# they run. The "date" command is an obvious example. Another is -# ftp, if it produces throughput statistics at the end of a file -# transfer. If this causes a problem, delete these patterns or replace -# them with wildcards. An alternative is to use the -p flag (for -# "prompt") which makes Expect only look for the last line of output -# (i.e., the prompt). The -P flag allows you to define a character to -# toggle this mode off and on. -# -# Read the man page for more info. -# -# -Don - - -set timeout -1 -spawn $env(SHELL) -match_max 100000 -expect -exact "\[1m\[7m%\[27m\[1m\[0m \r \r\]633;D\]633;P;Cwd=/Users/adam/Source/sdk\r\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\r -\[1;32m❯\[0m \]633;B\[K\[206C\]633;H\]633;I\[206D\[?2004h\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\r -\[1;32m❯\[0m \]633;B\[K\[206C\]633;H\]633;I\[206D" -send -- "df" -expect -exact "df" -send -- "x " -expect -exact "x " -expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx\[K\[203C\]633;H\]633;I\[202D" -send -- "identity " -expect -exact "identity " -expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx identity\[K\[194C\]633;H\]633;I\[193D" -send -- "new " -expect -exact "new " -expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx identity new\[K\[190C\]633;H\]633;I\[189D" -send -- "bob " -expect -exact "bob " -expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx identity new bob\[K\[186C\]633;H\]633;I\[185D" -send -- "\r" -expect -exact "\[?2004l\r\r -\]633;C\]633;E;dfx identity new bob \rPlease enter a passphrase for your identity: " -send -- "hunter2\r" -expect -exact "\r -\[1A\r\[2K\[1B\[1APlease enter a passphrase for your identity: \[hidden\]\r -Encryption complete.\r -Your seed phrase for identity 'bob': deposit become pink friend wisdom boss parrot modify album artist unable spatial regret disagree wild seed glare naive call top upgrade inject case result\r -This can be used to reconstruct your key in case of emergency, so write it down in a safe place.\r -\[1mCreated identity: \"bob\".(B\[m\r -\[1m\[7m%\[27m\[1m\[0m \r \r\]633;D;0\]633;P;Cwd=/Users/adam/Source/sdk\r\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;B\[K\[206C\]633;H\]633;I\[206D\[?2004h\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;B\[K\[206C\]633;H\]633;I\[206D" -send -- "df" -expect -exact "df" -send -- "x i" -expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx\[K\[203C\]633;H\]633;I\[202Di" -send -- "dentity " -expect -exact "dentity " -expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx identity\[K\[194C\]633;H\]633;I\[193D\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx identity\[K\[194C\]633;H\]633;I\[193D" -send -- "" -expect -exact "" -send -- "" -expect -exact " " -send -- "" -expect -exact " " -send -- "" -expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx identi\[K\[196C\]633;H\]633;I\[196D  " -send -- "" -expect -exact " " -send -- "" -expect -exact " " -send -- "" -expect -exact " " -send -- "" -expect -exact " " -send -- "led" -expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx le\[K\[200C\]633;H\]633;I\[200Dd" -send -- "ger ac" -expect -exact "ger ac" -expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx ledger ac\[K\[193C\]633;H\]633;I\[193D" -send -- "" -expect -exact " " -send -- "" -expect -exact " " -send -- "balance " -expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx ledger balance\[K\[188C\]633;H\]633;I\[188D \r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx ledger balance\[K\[188C\]633;H\]633;I\[187D\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx ledger balance\[K\[188C\]633;H\]633;I\[187D\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx ledger balance\[K\[188C\]633;H\]633;I\[187D\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx ledger balance\[K\[188C\]633;H\]633;I\[187D\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx ledger balance\[K\[188C\]633;H\]633;I\[187D" -send -- "--networ" -expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx ledger balance --netw\[K\[181C\]633;H\]633;I\[181Dor" -send -- "k ic --" -expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx ledger balance --network ic -\[K\[173C\]633;H\]633;I\[173D-" -send -- "identity bo" -expect -exact "\r\r\[A\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;Bdfx ledger balance --network ic --identity b\[K\[162C\]633;H\]633;I\[162Do" -send -- "b\r" -expect -exact "\[?2004l\r\r -\]633;C\]633;E;dfx ledger balance --network ic --identity bob\rPlease enter the passphrase for your identity: " -send -- "hunter2\r" -expect -exact "\r -\[1A\r\[2K\[1B\[1APlease enter the passphrase for your identity: \[hidden\]\r -Decryption complete.\r -0.00000000 ICP\r -\[1m\[7m%\[27m\[1m\[0m \r \r\]633;D;0\]633;P;Cwd=/Users/adam/Source/sdk\r\[0m\[27m\[24m\[J\]633;A\[1;36msdk\[0m \[\[1;35m \[0m\[1;35mspofford/warn-unencrypted\[0m\]\[1;31m\[\[0m\[1;31m\$\[0m\[1;31m?\[0m\[1;31m\]\[0m\[\[1;31m \[0m\[1;31mv1.60.0\[0m\]\[\[1;33m鬒 \[0m\[1;33m2s\[0m\]\r -\[1;32m❯\[0m \]633;B\[K\[206C\]633;H\]633;I\[206D\[?2004h" -send -- "ex" -expect -exact "ex" -send -- "it\r" -expect eof From 14c479f92e26d31b3f7c649ac262550c7d911777 Mon Sep 17 00:00:00 2001 From: Adam Spofford Date: Wed, 12 Oct 2022 11:12:38 -0700 Subject: [PATCH 5/6] Be more specific in the test --- e2e/tests-dfx/identity.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/tests-dfx/identity.bash b/e2e/tests-dfx/identity.bash index d8abb342f9..5159261d7f 100644 --- a/e2e/tests-dfx/identity.bash +++ b/e2e/tests-dfx/identity.bash @@ -163,10 +163,10 @@ teardown() { @test "using an unencrypted identity on mainnet provokes a warning" { assert_command dfx ledger balance --network ic - assert_match WARN "$stderr" + assert_match "WARN: The default identity is not stored securely." "$stderr" assert_command "${BATS_TEST_DIRNAME}/../assets/expect_scripts/init_alice_with_pw.exp" assert_command "${BATS_TEST_DIRNAME}/../assets/expect_scripts/get_ledger_balance.exp" dfx identity new bob --disable-encryption assert_command dfx ledger balance --network ic --identity bob - assert_match WARN "$stderr" + assert_match "WARN: The bob identity is not stored securely." "$stderr" } From 05684257f663bb9d369ae569b0e75051b93bdffe Mon Sep 17 00:00:00 2001 From: Adam Spofford Date: Wed, 26 Oct 2022 13:16:41 -0700 Subject: [PATCH 6/6] fix e2e --- scripts/workflows/provision-linux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/workflows/provision-linux.sh b/scripts/workflows/provision-linux.sh index dc40e0d20d..9522f3d25e 100755 --- a/scripts/workflows/provision-linux.sh +++ b/scripts/workflows/provision-linux.sh @@ -39,7 +39,7 @@ if [ "$E2E_TEST" = "tests-dfx/certificate.bash" ]; then sudo tar --directory /usr/local/bin --extract --file mitmproxy.tar.gz echo "mitmproxy version: $(mitmproxy --version)" fi -if [ "$E2E_TEST" = "tests-dfx/identity_encryption.bash" ]; then +if [ "$E2E_TEST" = "tests-dfx/identity_encryption.bash" ] || [ "$E2E_TEST" = "tests-dfx/identity.bash" ]; then sudo apt-get install --yes expect fi