Skip to content

Commit

Permalink
solana-keygen - Poor mans keypair encryption (solana-labs#6259)
Browse files Browse the repository at this point in the history
* SDK: Refactor (read|write)_keypair

Split file opening and data writing operations
Drop filename == "-" stdio signal. It is an app-level feature

* keygen: Move all non-key printing to stderr

* keygen: Adapt to SDK refactor

* keygen: Factor keypair output out to a helper function
  • Loading branch information
t-nelson authored Oct 10, 2019
1 parent f8b36f4 commit 9cde670
Show file tree
Hide file tree
Showing 13 changed files with 94 additions and 68 deletions.
4 changes: 2 additions & 2 deletions bench-exchange/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use clap::{crate_description, crate_name, crate_version, value_t, App, Arg, ArgMatches};
use solana_core::gen_keys::GenKeys;
use solana_drone::drone::DRONE_PORT;
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
use solana_sdk::signature::{read_keypair_file, Keypair, KeypairUtil};
use std::net::SocketAddr;
use std::process::exit;
use std::time::Duration;
Expand Down Expand Up @@ -179,7 +179,7 @@ pub fn extract_args<'a>(matches: &ArgMatches<'a>) -> Config {
});

if matches.is_present("identity") {
args.identity = read_keypair(matches.value_of("identity").unwrap())
args.identity = read_keypair_file(matches.value_of("identity").unwrap())
.expect("can't read client identity");
} else {
args.identity = {
Expand Down
4 changes: 2 additions & 2 deletions bench-tps/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use clap::{crate_description, crate_name, crate_version, App, Arg, ArgMatches};
use solana_drone::drone::DRONE_PORT;
use solana_sdk::fee_calculator::FeeCalculator;
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
use solana_sdk::signature::{read_keypair_file, Keypair, KeypairUtil};
use std::{net::SocketAddr, process::exit, time::Duration};

const NUM_LAMPORTS_PER_ACCOUNT_DEFAULT: u64 = 64 * 1024;
Expand Down Expand Up @@ -181,7 +181,7 @@ pub fn extract_args<'a>(matches: &ArgMatches<'a>) -> Config {
}

if matches.is_present("identity") {
args.id = read_keypair(matches.value_of("identity").unwrap())
args.id = read_keypair_file(matches.value_of("identity").unwrap())
.expect("can't read client identity");
}

Expand Down
4 changes: 2 additions & 2 deletions cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1385,7 +1385,7 @@ mod tests {
use serde_json::Value;
use solana_client::mock_rpc_client_request::SIGNATURE;
use solana_sdk::{
signature::{gen_keypair_file, read_keypair},
signature::{gen_keypair_file, read_keypair_file},
transaction::TransactionError,
};
use std::path::PathBuf;
Expand Down Expand Up @@ -1442,7 +1442,7 @@ mod tests {
// Test Balance Subcommand, incl pubkey and keypair-file inputs
let keypair_file = make_tmp_path("keypair_file");
gen_keypair_file(&keypair_file).unwrap();
let keypair = read_keypair(&keypair_file).unwrap();
let keypair = read_keypair_file(&keypair_file).unwrap();
let test_balance = test_commands.clone().get_matches_from(vec![
"test",
"balance",
Expand Down
10 changes: 5 additions & 5 deletions cli/src/input_parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use clap::ArgMatches;
use solana_sdk::{
native_token::sol_to_lamports,
pubkey::Pubkey,
signature::{read_keypair, Keypair, KeypairUtil},
signature::{read_keypair_file, Keypair, KeypairUtil},
};

// Return parsed values from matches at `name`
Expand Down Expand Up @@ -32,7 +32,7 @@ where
// Return the keypair for an argument with filename `name` or None if not present.
pub fn keypair_of(matches: &ArgMatches<'_>, name: &str) -> Option<Keypair> {
if let Some(value) = matches.value_of(name) {
read_keypair(value).ok()
read_keypair_file(value).ok()
} else {
None
}
Expand All @@ -56,7 +56,7 @@ pub fn amount_of(matches: &ArgMatches<'_>, name: &str, unit: &str) -> Option<u64
mod tests {
use super::*;
use clap::{App, Arg};
use solana_sdk::signature::write_keypair;
use solana_sdk::signature::write_keypair_file;
use std::fs;

fn app<'ab, 'v>() -> App<'ab, 'v> {
Expand Down Expand Up @@ -120,7 +120,7 @@ mod tests {
fn test_keypair_of() {
let keypair = Keypair::new();
let outfile = tmp_file_path("test_gen_keypair_file.json", &keypair.pubkey());
let _ = write_keypair(&keypair, &outfile).unwrap();
let _ = write_keypair_file(&keypair, &outfile).unwrap();

let matches = app()
.clone()
Expand All @@ -141,7 +141,7 @@ mod tests {
fn test_pubkey_of() {
let keypair = Keypair::new();
let outfile = tmp_file_path("test_gen_keypair_file.json", &keypair.pubkey());
let _ = write_keypair(&keypair, &outfile).unwrap();
let _ = write_keypair_file(&keypair, &outfile).unwrap();

let matches = app()
.clone()
Expand Down
4 changes: 2 additions & 2 deletions cli/src/input_validators.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::read_keypair;
use solana_sdk::signature::read_keypair_file;

// Return an error if a pubkey cannot be parsed.
pub fn is_pubkey(string: String) -> Result<(), String> {
Expand All @@ -11,7 +11,7 @@ pub fn is_pubkey(string: String) -> Result<(), String> {

// Return an error if a keypair file cannot be parsed.
pub fn is_keypair(string: String) -> Result<(), String> {
read_keypair(&string)
read_keypair_file(&string)
.map(|_| ())
.map_err(|err| format!("{:?}", err))
}
Expand Down
4 changes: 2 additions & 2 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use solana_cli::{
display::{println_name_value, println_name_value_or},
input_validators::is_url,
};
use solana_sdk::signature::{read_keypair, KeypairUtil};
use solana_sdk::signature::{read_keypair_file, KeypairUtil};
use std::error;

fn parse_settings(matches: &ArgMatches<'_>) -> Result<bool, Box<dyn error::Error>> {
Expand Down Expand Up @@ -94,7 +94,7 @@ pub fn parse_args(matches: &ArgMatches<'_>) -> Result<CliConfig, Box<dyn error::
}
default.keypair_path
};
let keypair = read_keypair(&keypair_path).or_else(|err| {
let keypair = read_keypair_file(&keypair_path).or_else(|err| {
Err(CliError::BadParameter(format!(
"{}: Unable to open keypair file: {}",
err, keypair_path
Expand Down
6 changes: 3 additions & 3 deletions drone/src/bin/drone.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use clap::{crate_description, crate_name, crate_version, App, Arg};
use solana_drone::drone::{run_drone, Drone, DRONE_PORT};
use solana_drone::socketaddr;
use solana_sdk::signature::read_keypair;
use solana_sdk::signature::read_keypair_file;
use std::error;
use std::net::{Ipv4Addr, SocketAddr};
use std::sync::{Arc, Mutex};
Expand Down Expand Up @@ -38,8 +38,8 @@ fn main() -> Result<(), Box<dyn error::Error>> {
)
.get_matches();

let mint_keypair =
read_keypair(matches.value_of("keypair").unwrap()).expect("failed to read client keypair");
let mint_keypair = read_keypair_file(matches.value_of("keypair").unwrap())
.expect("failed to read client keypair");

let time_slice: Option<u64>;
if let Some(secs) = matches.value_of("slice") {
Expand Down
12 changes: 6 additions & 6 deletions genesis/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use solana_sdk::{
poh_config::PohConfig,
pubkey::Pubkey,
rent_calculator::RentCalculator,
signature::{read_keypair, Keypair, KeypairUtil},
signature::{read_keypair_file, Keypair, KeypairUtil},
system_program, timing,
};
use solana_stake_api::stake_state;
Expand Down Expand Up @@ -298,11 +298,11 @@ fn main() -> Result<(), Box<dyn error::Error>> {
let bootstrap_leader_stake_lamports =
value_t_or_exit!(matches, "bootstrap_leader_stake_lamports", u64);

let bootstrap_leader_keypair = read_keypair(bootstrap_leader_keypair_file)?;
let bootstrap_vote_keypair = read_keypair(bootstrap_vote_keypair_file)?;
let bootstrap_stake_keypair = read_keypair(bootstrap_stake_keypair_file)?;
let bootstrap_storage_keypair = read_keypair(bootstrap_storage_keypair_file)?;
let mint_keypair = read_keypair(mint_keypair_file)?;
let bootstrap_leader_keypair = read_keypair_file(bootstrap_leader_keypair_file)?;
let bootstrap_vote_keypair = read_keypair_file(bootstrap_vote_keypair_file)?;
let bootstrap_stake_keypair = read_keypair_file(bootstrap_stake_keypair_file)?;
let bootstrap_storage_keypair = read_keypair_file(bootstrap_storage_keypair_file)?;
let mint_keypair = read_keypair_file(mint_keypair_file)?;

let vote_account = vote_state::create_account(
&bootstrap_vote_keypair.pubkey(),
Expand Down
6 changes: 3 additions & 3 deletions install/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use solana_client::rpc_client::RpcClient;
use solana_config_api::{config_instruction, get_config_data};
use solana_sdk::message::Message;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil, Signable};
use solana_sdk::signature::{read_keypair_file, Keypair, KeypairUtil, Signable};
use solana_sdk::transaction::Transaction;
use std::fs::{self, File};
use std::io::{self, BufReader, Read};
Expand Down Expand Up @@ -626,9 +626,9 @@ pub fn deploy(
download_url: &str,
update_manifest_keypair_file: &str,
) -> Result<(), String> {
let from_keypair = read_keypair(from_keypair_file)
let from_keypair = read_keypair_file(from_keypair_file)
.map_err(|err| format!("Unable to read {}: {}", from_keypair_file, err))?;
let update_manifest_keypair = read_keypair(update_manifest_keypair_file)
let update_manifest_keypair = read_keypair_file(update_manifest_keypair_file)
.map_err(|err| format!("Unable to read {}: {}", update_manifest_keypair_file, err))?;

println_name_value("JSON RPC URL:", json_rpc_url);
Expand Down
47 changes: 30 additions & 17 deletions keygen/src/keygen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use clap::{
crate_description, crate_name, crate_version, App, AppSettings, Arg, ArgMatches, SubCommand,
};
use solana_sdk::pubkey::write_pubkey;
use solana_sdk::signature::{keypair_from_seed, read_keypair, write_keypair, KeypairUtil};
use solana_sdk::signature::{
keypair_from_seed, read_keypair, read_keypair_file, write_keypair, write_keypair_file, Keypair,
KeypairUtil,
};
use std::error;
use std::path::Path;
use std::process::exit;
Expand All @@ -18,6 +21,21 @@ fn check_for_overwrite(outfile: &str, matches: &ArgMatches) {
}
}

fn output_keypair(
keypair: &Keypair,
outfile: &str,
source: &str,
) -> Result<(), Box<dyn error::Error>> {
if outfile == "-" {
let mut stdout = std::io::stdout();
write_keypair(&keypair, &mut stdout)?;
} else {
write_keypair_file(&keypair, outfile)?;
eprintln!("Wrote {} keypair to {}", source, outfile);
}
Ok(())
}

fn main() -> Result<(), Box<dyn error::Error>> {
let matches = App::new(crate_name!())
.about(crate_description!())
Expand Down Expand Up @@ -45,7 +63,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
Arg::with_name("silent")
.short("s")
.long("silent")
.help("Do not display mnemonic phrase"),
.help("Do not display mnemonic phrase. Useful when piping output to other programs that prompt for user input, like gpg"),
),
)
.subcommand(
Expand Down Expand Up @@ -104,7 +122,12 @@ fn main() -> Result<(), Box<dyn error::Error>> {
path.extend(&[".config", "solana", "id.json"]);
path.to_str().unwrap()
};
let keypair = read_keypair(infile)?;
let keypair = if infile == "-" {
let mut stdin = std::io::stdin();
read_keypair(&mut stdin)?
} else {
read_keypair_file(infile)?
};

if matches.is_present("outfile") {
let outfile = matches.value_of("outfile").unwrap();
Expand Down Expand Up @@ -132,17 +155,12 @@ fn main() -> Result<(), Box<dyn error::Error>> {
let seed = Seed::new(&mnemonic, NO_PASSPHRASE);
let keypair = keypair_from_seed(seed.as_bytes())?;

let serialized_keypair = write_keypair(&keypair, outfile)?;
if outfile == "-" {
println!("{}", serialized_keypair);
} else {
println!("Wrote new keypair to {}", outfile);
}
output_keypair(&keypair, &outfile, "new")?;

let silent = matches.is_present("silent");
if !silent {
let divider = String::from_utf8(vec![b'='; phrase.len()]).unwrap();
println!(
eprintln!(
"{}\nSave this mnemonic phrase to recover your new keypair:\n{}\n{}",
&divider, phrase, &divider
);
Expand All @@ -161,17 +179,12 @@ fn main() -> Result<(), Box<dyn error::Error>> {
check_for_overwrite(&outfile, &matches);
}

let phrase = rpassword::prompt_password_stdout("Mnemonic recovery phrase: ").unwrap();
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 serialized_keypair = write_keypair(&keypair, outfile)?;
if outfile == "-" {
println!("{}", serialized_keypair);
} else {
println!("Wrote recovered keypair to {}", outfile);
}
output_keypair(&keypair, &outfile, "recovered")?;
}
_ => unreachable!(),
}
Expand Down
8 changes: 4 additions & 4 deletions replicator/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ use console::style;
use solana_core::cluster_info::{Node, FULLNODE_PORT_RANGE};
use solana_core::contact_info::ContactInfo;
use solana_core::replicator::Replicator;
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
use solana_sdk::signature::{read_keypair_file, Keypair, KeypairUtil};
use std::net::SocketAddr;
use std::path::PathBuf;
use std::process::exit;
use std::sync::Arc;

// Return an error if a keypair file cannot be parsed.
fn is_keypair(string: String) -> Result<(), String> {
read_keypair(&string)
read_keypair_file(&string)
.map(|_| ())
.map_err(|err| format!("{:?}", err))
}
Expand Down Expand Up @@ -65,15 +65,15 @@ fn main() {
let ledger_path = PathBuf::from(matches.value_of("ledger").unwrap());

let keypair = if let Some(identity) = matches.value_of("identity") {
read_keypair(identity).unwrap_or_else(|err| {
read_keypair_file(identity).unwrap_or_else(|err| {
eprintln!("{}: Unable to open keypair file: {}", err, identity);
exit(1);
})
} else {
Keypair::new()
};
let storage_keypair = if let Some(storage_keypair) = matches.value_of("storage_keypair") {
read_keypair(storage_keypair).unwrap_or_else(|err| {
read_keypair_file(storage_keypair).unwrap_or_else(|err| {
eprintln!("{}: Unable to open keypair file: {}", err, storage_keypair);
exit(1);
})
Expand Down
Loading

0 comments on commit 9cde670

Please sign in to comment.