Use ZeroingString for password and passpharse in wallet (#2285)

This commit is contained in:
hashmap 2019-01-11 00:58:37 +01:00 committed by Ignotus Peverell
parent 950fa0e496
commit 5cf4d7acfe
4 changed files with 31 additions and 20 deletions

View file

@ -14,7 +14,7 @@
use crate::api::TLSConfig; use crate::api::TLSConfig;
use crate::util::file::get_first_line; use crate::util::file::get_first_line;
use crate::util::Mutex; use crate::util::{Mutex, ZeroingString};
/// Argument parsing and error handling for wallet commands /// Argument parsing and error handling for wallet commands
use clap::ArgMatches; use clap::ArgMatches;
use failure::Fail; use failure::Fail;
@ -57,19 +57,23 @@ impl From<std::io::Error> for ParseError {
} }
} }
pub fn prompt_password(password: &Option<String>) -> String { fn prompt_password_stdout(prompt: &str) -> ZeroingString {
ZeroingString::from(rpassword::prompt_password_stdout(prompt).unwrap())
}
pub fn prompt_password(password: &Option<ZeroingString>) -> ZeroingString {
match password { match password {
None => rpassword::prompt_password_stdout("Password: ").unwrap(), None => prompt_password_stdout("Password: "),
Some(p) => p.to_owned(), Some(p) => p.clone(),
} }
} }
fn prompt_password_confirm() -> String { fn prompt_password_confirm() -> ZeroingString {
let mut first = String::from("first"); let mut first = ZeroingString::from("first");
let mut second = String::from("second"); let mut second = ZeroingString::from("second");
while first != second { while first != second {
first = rpassword::prompt_password_stdout("Password: ").unwrap(); first = prompt_password_stdout("Password: ");
second = rpassword::prompt_password_stdout("Confirm Password: ").unwrap(); second = prompt_password_stdout("Confirm Password: ");
} }
first first
} }
@ -101,9 +105,9 @@ fn prompt_replace_seed() -> Result<bool, ParseError> {
} }
} }
fn prompt_recovery_phrase() -> Result<String, ParseError> { fn prompt_recovery_phrase() -> Result<ZeroingString, ParseError> {
let interface = Arc::new(Interface::new("recover")?); let interface = Arc::new(Interface::new("recover")?);
let mut phrase = String::new(); let mut phrase = ZeroingString::from("");
interface.set_report_signal(Signal::Interrupt, true); interface.set_report_signal(Signal::Interrupt, true);
interface.set_prompt("phrase> ")?; interface.set_prompt("phrase> ")?;
loop { loop {
@ -119,7 +123,7 @@ fn prompt_recovery_phrase() -> Result<String, ParseError> {
} }
ReadResult::Input(line) => { ReadResult::Input(line) => {
if WalletSeed::from_mnemonic(&line).is_ok() { if WalletSeed::from_mnemonic(&line).is_ok() {
phrase = line; phrase = ZeroingString::from(line);
break; break;
} else { } else {
println!(); println!();
@ -194,7 +198,7 @@ pub fn parse_global_args(
let node_api_secret = get_first_line(config.node_api_secret_path.clone()); let node_api_secret = get_first_line(config.node_api_secret_path.clone());
let password = match args.value_of("pass") { let password = match args.value_of("pass") {
None => None, None => None,
Some(p) => Some(p.to_owned()), Some(p) => Some(ZeroingString::from(p)),
}; };
let tls_conf = match config.tls_certificate_file.clone() { let tls_conf = match config.tls_certificate_file.clone() {

View file

@ -68,6 +68,7 @@ impl Default for LoggingConfig {
use std::ops::Deref; use std::ops::Deref;
use zeroize::Zeroize; use zeroize::Zeroize;
/// Zeroing string, mainly useful for password /// Zeroing string, mainly useful for password
#[derive(Clone, PartialEq, PartialOrd)]
pub struct ZeroingString(String); pub struct ZeroingString(String);
impl Drop for ZeroingString { impl Drop for ZeroingString {
@ -82,6 +83,12 @@ impl From<&str> for ZeroingString {
} }
} }
impl From<String> for ZeroingString {
fn from(s: String) -> Self {
ZeroingString(s)
}
}
impl Deref for ZeroingString { impl Deref for ZeroingString {
type Target = str; type Target = str;

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::util::Mutex; use crate::util::{Mutex, ZeroingString};
use std::collections::HashMap; use std::collections::HashMap;
/// Grin wallet command-line function implementations /// Grin wallet command-line function implementations
use std::fs::File; use std::fs::File;
@ -41,7 +41,7 @@ pub struct GlobalArgs {
pub account: String, pub account: String,
pub node_api_secret: Option<String>, pub node_api_secret: Option<String>,
pub show_spent: bool, pub show_spent: bool,
pub password: Option<String>, pub password: Option<ZeroingString>,
pub tls_conf: Option<TLSConfig>, pub tls_conf: Option<TLSConfig>,
} }
@ -49,9 +49,9 @@ pub struct GlobalArgs {
pub struct InitArgs { pub struct InitArgs {
/// BIP39 recovery phrase length /// BIP39 recovery phrase length
pub list_length: usize, pub list_length: usize,
pub password: String, pub password: ZeroingString,
pub config: WalletConfig, pub config: WalletConfig,
pub recovery_phrase: Option<String>, pub recovery_phrase: Option<ZeroingString>,
pub restore: bool, pub restore: bool,
} }
@ -75,8 +75,8 @@ pub fn init(g_args: &GlobalArgs, args: InitArgs) -> Result<(), Error> {
/// Argument for recover /// Argument for recover
pub struct RecoverArgs { pub struct RecoverArgs {
pub recovery_phrase: Option<String>, pub recovery_phrase: Option<ZeroingString>,
pub passphrase: String, pub passphrase: ZeroingString,
} }
/// Check whether seed file exists /// Check whether seed file exists

View file

@ -216,7 +216,7 @@ impl WalletSeed {
pub fn init_file( pub fn init_file(
wallet_config: &WalletConfig, wallet_config: &WalletConfig,
seed_length: usize, seed_length: usize,
recovery_phrase: Option<String>, recovery_phrase: Option<util::ZeroingString>,
password: &str, password: &str,
) -> Result<WalletSeed, Error> { ) -> Result<WalletSeed, Error> {
// create directory if it doesn't exist // create directory if it doesn't exist