From eaa3e87eb0c6c7fef3304283e9d17128a5a850e6 Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Mon, 25 Nov 2019 23:33:15 -0500 Subject: [PATCH] Support passphrases in keygen (#7134) * Support passphrases in keygen * remove short * Update solana_keygen calls --- ci/localnet-sanity.sh | 2 +- clap-utils/src/keypair.rs | 2 +- keygen/src/keygen.rs | 37 +++++++++++++++++++++++--------- multinode-demo/archiver.sh | 4 ++-- multinode-demo/delegate-stake.sh | 2 +- multinode-demo/setup.sh | 10 ++++----- multinode-demo/validator.sh | 6 +++--- net/remote/remote-client.sh | 2 +- net/remote/remote-node.sh | 4 ++-- run.sh | 10 ++++----- scripts/wallet-sanity.sh | 2 +- 11 files changed, 49 insertions(+), 32 deletions(-) diff --git a/ci/localnet-sanity.sh b/ci/localnet-sanity.sh index 17a2c5db14..6fd02d2beb 100755 --- a/ci/localnet-sanity.sh +++ b/ci/localnet-sanity.sh @@ -324,7 +324,7 @@ while [[ $iteration -le $iterations ]]; do ( set -x client_keypair=/tmp/client-id.json-$$ - $solana_keygen new -f -o $client_keypair || exit $? + $solana_keygen new --no-passphrase -fso $client_keypair || exit $? $solana_gossip spy -n 127.0.0.1:8001 --num-nodes-exactly $numNodes || exit $? rm -rf $client_keypair ) || flag_error diff --git a/clap-utils/src/keypair.rs b/clap-utils/src/keypair.rs index 783e3fbbeb..2046c5a4ff 100644 --- a/clap-utils/src/keypair.rs +++ b/clap-utils/src/keypair.rs @@ -42,7 +42,7 @@ impl KeypairWithSource { } /// Reads user input from stdin to retrieve a seed phrase and passphrase for keypair derivation -pub(crate) fn keypair_from_seed_phrase( +pub fn keypair_from_seed_phrase( keypair_name: &str, skip_validation: bool, ) -> Result> { diff --git a/keygen/src/keygen.rs b/keygen/src/keygen.rs index 3d6e153291..28ec2c0db2 100644 --- a/keygen/src/keygen.rs +++ b/keygen/src/keygen.rs @@ -4,6 +4,7 @@ use clap::{ crate_description, crate_name, values_t_or_exit, App, AppSettings, Arg, ArgMatches, SubCommand, }; use num_cpus; +use solana_clap_utils::keypair::{keypair_from_seed_phrase, SKIP_SEED_PHRASE_VALIDATION_ARG}; use solana_sdk::{ pubkey::write_pubkey_file, signature::{ @@ -56,7 +57,7 @@ fn main() -> Result<(), Box> { .setting(AppSettings::SubcommandRequiredElseHelp) .subcommand( SubCommand::with_name("new") - .about("Generate new keypair file") + .about("Generate new keypair file from a passphrase and random seed phrase") .setting(AppSettings::DisableVersion) .arg( Arg::with_name("outfile") @@ -72,11 +73,16 @@ fn main() -> Result<(), Box> { .long("force") .help("Overwrite the output file if it exists"), ) + .arg( + Arg::with_name("no_passphrase") + .long("no-passphrase") + .help("Do not prompt for a passphrase"), + ) .arg( Arg::with_name("silent") .short("s") .long("silent") - .help("Do not display mnemonic phrase. Useful when piping output to other programs that prompt for user input, like gpg"), + .help("Do not display seed phrase. Useful when piping output to other programs that prompt for user input, like gpg"), ) ) .subcommand( @@ -143,7 +149,7 @@ fn main() -> Result<(), Box> { ) .subcommand( SubCommand::with_name("recover") - .about("Recover keypair from mnemonic phrase") + .about("Recover keypair from seed phrase and passphrase") .setting(AppSettings::DisableVersion) .arg( Arg::with_name("outfile") @@ -158,7 +164,13 @@ fn main() -> Result<(), Box> { .short("f") .long("force") .help("Overwrite the output file if it exists"), + ) + .arg( + Arg::with_name(SKIP_SEED_PHRASE_VALIDATION_ARG.name) + .long(SKIP_SEED_PHRASE_VALIDATION_ARG.long) + .help(SKIP_SEED_PHRASE_VALIDATION_ARG.help), ), + ) .get_matches(); @@ -200,7 +212,15 @@ fn main() -> Result<(), Box> { } let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); - let seed = Seed::new(&mnemonic, NO_PASSPHRASE); + let passphrase = if matches.is_present("no_passphrase") { + NO_PASSPHRASE.to_string() + } else { + eprintln!("Generating a new keypair"); + rpassword::prompt_password_stderr( + "For added security, enter a passphrase (empty for no passphrase):", + )? + }; + let seed = Seed::new(&mnemonic, &passphrase); let keypair = keypair_from_seed(seed.as_bytes())?; output_keypair(&keypair, &outfile, "new")?; @@ -210,7 +230,7 @@ fn main() -> Result<(), Box> { let phrase: &str = mnemonic.phrase(); let divider = String::from_utf8(vec![b'='; phrase.len()]).unwrap(); eprintln!( - "{}\npubkey: {}\n{}\nSave this mnemonic phrase to recover your new keypair:\n{}\n{}", + "{}\npubkey: {}\n{}\nSave this seed phrase to recover your new keypair:\n{}\n{}", ÷r, keypair.pubkey(), ÷r, phrase, ÷r ); } @@ -228,11 +248,8 @@ fn main() -> Result<(), Box> { check_for_overwrite(&outfile, &matches); } - let phrase = rpassword::prompt_password_stderr("Mnemonic recovery phrase: ").unwrap(); - let mnemonic = Mnemonic::from_phrase(phrase.trim(), Language::English)?; - let seed = Seed::new(&mnemonic, NO_PASSPHRASE); - let keypair = keypair_from_seed(seed.as_bytes())?; - + let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name); + let keypair = keypair_from_seed_phrase("recover", skip_validation)?; output_keypair(&keypair, &outfile, "recovered")?; } ("grind", Some(matches)) => { diff --git a/multinode-demo/archiver.sh b/multinode-demo/archiver.sh index f9b7abfec6..c55b0b8214 100755 --- a/multinode-demo/archiver.sh +++ b/multinode-demo/archiver.sh @@ -59,7 +59,7 @@ ledger="$SOLANA_ROOT"/farf/archiver-ledger"$label" rpc_url=$($solana_gossip get-rpc-url --entrypoint "$entrypoint") if [[ ! -r $identity_keypair ]]; then - $solana_keygen new -o "$identity_keypair" + $solana_keygen new --no-passphrase -so "$identity_keypair" # See https://github.com/solana-labs/solana/issues/4344 $solana_cli --keypair "$identity_keypair" --url "$rpc_url" airdrop 1 @@ -67,7 +67,7 @@ fi identity_pubkey=$($solana_keygen pubkey "$identity_keypair") if [[ ! -r $storage_keypair ]]; then - $solana_keygen new -o "$storage_keypair" + $solana_keygen new --no-passphrase -so "$storage_keypair" $solana_cli --keypair "$identity_keypair" --url "$rpc_url" \ create-archiver-storage-account "$identity_pubkey" "$storage_keypair" diff --git a/multinode-demo/delegate-stake.sh b/multinode-demo/delegate-stake.sh index 37ffbbc391..3e1149474b 100755 --- a/multinode-demo/delegate-stake.sh +++ b/multinode-demo/delegate-stake.sh @@ -96,7 +96,7 @@ if ((airdrops_enabled)); then $solana_cli "${common_args[@]}" airdrop "$stake_lamports" lamports fi -$solana_keygen new -o "$stake_keypair_path" +$solana_keygen new --no-passphrase -so "$stake_keypair_path" set -x $solana_cli "${common_args[@]}" \ diff --git a/multinode-demo/setup.sh b/multinode-demo/setup.sh index 5606f7b42f..a17cd1b4d5 100755 --- a/multinode-demo/setup.sh +++ b/multinode-demo/setup.sh @@ -13,18 +13,18 @@ mkdir -p "$SOLANA_CONFIG_DIR"/bootstrap-leader if [[ -r $FAUCET_KEYPAIR ]]; then cp -f "$FAUCET_KEYPAIR" "$SOLANA_CONFIG_DIR"/faucet-keypair.json else - $solana_keygen new -f -o "$SOLANA_CONFIG_DIR"/faucet-keypair.json + $solana_keygen new --no-passphrase -fso "$SOLANA_CONFIG_DIR"/faucet-keypair.json fi if [[ -f $BOOTSTRAP_LEADER_IDENTITY_KEYPAIR ]]; then cp -f "$BOOTSTRAP_LEADER_IDENTITY_KEYPAIR" "$SOLANA_CONFIG_DIR"/bootstrap-leader/identity-keypair.json else - $solana_keygen new -o "$SOLANA_CONFIG_DIR"/bootstrap-leader/identity-keypair.json + $solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/bootstrap-leader/identity-keypair.json fi -$solana_keygen new -o "$SOLANA_CONFIG_DIR"/bootstrap-leader/vote-keypair.json -$solana_keygen new -o "$SOLANA_CONFIG_DIR"/bootstrap-leader/stake-keypair.json -$solana_keygen new -o "$SOLANA_CONFIG_DIR"/bootstrap-leader/storage-keypair.json +$solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/bootstrap-leader/vote-keypair.json +$solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/bootstrap-leader/stake-keypair.json +$solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/bootstrap-leader/storage-keypair.json args=("$@") default_arg --bootstrap-leader-pubkey "$SOLANA_CONFIG_DIR"/bootstrap-leader/identity-keypair.json diff --git a/multinode-demo/validator.sh b/multinode-demo/validator.sh index a1d4a54d17..a9a4647a80 100755 --- a/multinode-demo/validator.sh +++ b/multinode-demo/validator.sh @@ -280,9 +280,9 @@ setup_validator_accounts() { rpc_url=$($solana_gossip get-rpc-url --entrypoint "$gossip_entrypoint") -[[ -r "$identity_keypair_path" ]] || $solana_keygen new -o "$identity_keypair_path" -[[ -r "$voting_keypair_path" ]] || $solana_keygen new -o "$voting_keypair_path" -[[ -r "$storage_keypair_path" ]] || $solana_keygen new -o "$storage_keypair_path" +[[ -r "$identity_keypair_path" ]] || $solana_keygen new --no-passphrase -so "$identity_keypair_path" +[[ -r "$voting_keypair_path" ]] || $solana_keygen new --no-passphrase -so "$voting_keypair_path" +[[ -r "$storage_keypair_path" ]] || $solana_keygen new --no-passphrase -so "$storage_keypair_path" setup_validator_accounts "$node_lamports" diff --git a/net/remote/remote-client.sh b/net/remote/remote-client.sh index a8166c4de4..5467dcd70b 100755 --- a/net/remote/remote-client.sh +++ b/net/remote/remote-client.sh @@ -58,7 +58,7 @@ solana-bench-tps) " ;; solana-bench-exchange) - solana-keygen new -f -o bench.keypair + solana-keygen new --no-passphrase -fso bench.keypair net/scripts/rsync-retry.sh -vPrc \ "$entrypointIp":~/solana/config/bench-exchange"$clientIndex".yml ./client-accounts.yml clientCommand="\ diff --git a/net/remote/remote-node.sh b/net/remote/remote-node.sh index ac1eb25763..5e66f3d268 100755 --- a/net/remote/remote-node.sh +++ b/net/remote/remote-node.sh @@ -166,7 +166,7 @@ EOF if [[ -f net/keypairs/"$name".json ]]; then cp net/keypairs/"$name".json config/"$name".json else - solana-keygen new -o config/"$name".json + solana-keygen new --no-passphrase -so config/"$name".json fi if [[ -n $internalNodesLamports ]]; then declare pubkey @@ -302,7 +302,7 @@ EOF fi if [[ ! -f config/validator-identity.json ]]; then - solana-keygen new -o config/validator-identity.json + solana-keygen new --no-passphrase -so config/validator-identity.json fi args+=(--identity-keypair config/validator-identity.json) diff --git a/run.sh b/run.sh index d987447309..ff7b027092 100755 --- a/run.sh +++ b/run.sh @@ -50,31 +50,31 @@ leader_keypair="$dataDir/leader-keypair.json" if [[ -e $leader_keypair ]]; then echo "Use existing leader keypair" else - solana-keygen new -o "$leader_keypair" + solana-keygen new --no-passphrase -so "$leader_keypair" fi leader_vote_account_keypair="$dataDir/leader-vote-account-keypair.json" if [[ -e $leader_vote_account_keypair ]]; then echo "Use existing leader vote account keypair" else - solana-keygen new -o "$leader_vote_account_keypair" + solana-keygen new --no-passphrase -so "$leader_vote_account_keypair" fi leader_stake_account_keypair="$dataDir/leader-stake-account-keypair.json" if [[ -e $leader_stake_account_keypair ]]; then echo "Use existing leader stake account keypair" else - solana-keygen new -o "$leader_stake_account_keypair" + solana-keygen new --no-passphrase -so "$leader_stake_account_keypair" fi faucet_keypair="$dataDir"/faucet-keypair.json if [[ -e $faucet_keypair ]]; then echo "Use existing faucet keypair" else - solana-keygen new -f -o "$faucet_keypair" + solana-keygen new --no-passphrase -fso "$faucet_keypair" fi leader_storage_account_keypair="$dataDir"/leader-storage-account-keypair.json if [[ -e $leader_storage_account_keypair ]]; then echo "Use existing leader storage account keypair" else - solana-keygen new -f -o "$leader_storage_account_keypair" + solana-keygen new --no-passphrase -fso "$leader_storage_account_keypair" fi solana-genesis \ diff --git a/scripts/wallet-sanity.sh b/scripts/wallet-sanity.sh index 3dea177a2b..4a9bb14408 100755 --- a/scripts/wallet-sanity.sh +++ b/scripts/wallet-sanity.sh @@ -15,7 +15,7 @@ else args=("$@") fi -$solana_keygen new -f +$solana_keygen new --no-passphrase -sf node_readiness=false timeout=60