Skip to content
Snippets Groups Projects
Commit fb218187 authored by Nicolas80's avatar Nicolas80
Browse files

Revert "Added support for the different SecretFormat within the Vault"

This reverts commit fd92df0c.
parent 2b8dac2d
No related branches found
No related tags found
No related merge requests found
use crate::*; use crate::*;
use age::secrecy::Secret; use age::secrecy::Secret;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::path::PathBuf;
/// define universal dividends subcommands /// define universal dividends subcommands
#[derive(Clone, Default, Debug, clap::Parser)] #[derive(Clone, Default, Debug, clap::Parser)]
...@@ -13,18 +12,8 @@ pub enum Subcommand { ...@@ -13,18 +12,8 @@ pub enum Subcommand {
Where, Where,
/// Generate a mnemonic /// Generate a mnemonic
Generate, Generate,
/// Import key from (substrate)mnemonic or other format with interactive prompt /// Import mnemonic with interactive prompt
Import { Import,
/// Secret key format (substrate, seed, cesium)
#[clap(short = 'S', long, required = false, default_value = SecretFormat::Substrate)]
secret_format: SecretFormat,
},
}
struct VaultItem {
secret_format: SecretFormat,
secret: keys::Secret,
keypair: KeyPair,
} }
// encrypt input with passphrase // encrypt input with passphrase
...@@ -73,14 +62,11 @@ pub fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliError> ...@@ -73,14 +62,11 @@ pub fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliError>
let mnemonic = bip39::Mnemonic::generate(12).unwrap(); let mnemonic = bip39::Mnemonic::generate(12).unwrap();
println!("{mnemonic}"); println!("{mnemonic}");
} }
Subcommand::Import { Subcommand::Import => {
secret_format, let mnemonic = rpassword::prompt_password("Mnemonic: ")?;
} => {
let vault_item = prompt_secret_and_compute_vault_item(secret_format)?;
println!("Enter password to protect the key"); println!("Enter password to protect the key");
let password = rpassword::prompt_password("Password: ")?; let password = rpassword::prompt_password("Password: ")?;
let address = store_vault_item(&data, vault_item, password)?; let address = store_mnemonic(&data, &mnemonic, password)?;
println!("Stored secret for {address}"); println!("Stored secret for {address}");
} }
}; };
...@@ -88,120 +74,34 @@ pub fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliError> ...@@ -88,120 +74,34 @@ pub fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliError>
Ok(()) Ok(())
} }
fn create_vault_item<F, P>(secret_format: SecretFormat, prompt_fn: F) -> Result<VaultItem, GcliError> /// store mnemonic protected with password
where pub fn store_mnemonic(
F: Fn() -> (keys::Secret, P),
P: Into<KeyPair>,
{
let (secret, pair) = prompt_fn();
Ok(VaultItem {
secret_format,
secret,
keypair: pair.into(),
})
}
fn prompt_secret_and_compute_vault_item(secret_format: SecretFormat) -> Result<VaultItem, GcliError> {
match secret_format {
SecretFormat::Substrate =>
create_vault_item(secret_format, prompt_secret_substrate_and_compute_keypair),
SecretFormat::Seed =>
create_vault_item(secret_format, prompt_seed_and_compute_keypair),
SecretFormat::Cesium =>
create_vault_item(secret_format, prompt_secret_cesium_and_compute_keypair),
SecretFormat::Predefined =>
create_vault_item(secret_format, prompt_predefined_and_compute_keypair),
}
}
/// store VaultItem protected with password
fn store_vault_item(
data: &Data, data: &Data,
vault_item: VaultItem, mnemonic: &str,
password: String, password: String,
) -> Result<AccountId, GcliError> { ) -> Result<AccountId, GcliError> {
let keypair = vault_item.keypair; // check validity by deriving keypair
let address = keypair.address(); let keypair = pair_from_str(mnemonic)?;
// write encrypted secret in file identified by address pubkey and secret_format let address = keypair.public();
let path = get_vault_key_path(data, vault_item.secret_format, address.to_string()); // write encrypted mnemonic in file identified by pubkey
let path = data.project_dir.data_dir().join(address.to_string());
let mut file = std::fs::File::create(path)?; let mut file = std::fs::File::create(path)?;
file.write_all(&encrypt(mnemonic.as_bytes(), password).map_err(|e| anyhow!(e))?[..])?;
match vault_item.secret { Ok(keypair.public().into())
keys::Secret::SimpleSecret(secret) => {
file.write_all(&encrypt(secret.as_bytes(), password).map_err(|e| anyhow!(e))?[..])?;
}
keys::Secret::DualSecret(id, pwd) => {
//Making a simple separation of the 2 parts with a newline character
let secret = format!("{id}\n{pwd}");
file.write_all(&encrypt(secret.as_bytes(), password).map_err(|e| anyhow!(e))?[..])?;
}
}
Ok(address)
} }
fn get_vault_key_path(data: &Data, secret_format: SecretFormat, address: String) -> PathBuf { /// try get secret in keystore
let format_str: &'static str = From::from(secret_format); pub fn try_fetch_secret(data: &Data, address: AccountId) -> Result<Option<String>, GcliError> {
data.project_dir.data_dir().join(format!("{}-{}", address, format_str)) let path = data.project_dir.data_dir().join(address.to_string());
}
/// look for different possible paths for vault keys and return both format and path
fn find_vault_key(data: &Data, address: String) -> Result<Option<(SecretFormat, PathBuf)>, GcliError> {
let mut secret_format = SecretFormat::Substrate;
let mut path = get_vault_key_path(data, secret_format, address.to_string());
//Also checking for old file name without secret_format which would be for (default) substrate key
if !path.exists() {
path = data.project_dir.data_dir().join(address.to_string());
}
if !path.exists() {
secret_format = SecretFormat::Seed;
path = get_vault_key_path(data, secret_format, address.to_string());
}
if !path.exists() {
secret_format = SecretFormat::Cesium;
path = get_vault_key_path(data, secret_format, address.to_string());
}
if !path.exists() {
secret_format = SecretFormat::Predefined;
path = get_vault_key_path(data, secret_format, address.to_string());
}
if path.exists() { if path.exists() {
Ok(Some((secret_format, path)))
} else {
Ok(None)
}
}
/// try to get secret in keystore, prompt for the password and compute the keypair
pub fn try_fetch_key_pair(data: &Data, address: AccountId) -> Result<Option<KeyPair>, GcliError> {
if let Some((secret_format, path)) = find_vault_key(data, address.to_string())? {
println!("Enter password to unlock account {address}"); println!("Enter password to unlock account {address}");
let password = rpassword::prompt_password("Password: ")?; let password = rpassword::prompt_password("Password: ")?;
let mut file = std::fs::OpenOptions::new().read(true).open(path)?; let mut file = std::fs::OpenOptions::new().read(true).open(path)?;
let mut cypher = vec![]; let mut cypher = vec![];
file.read_to_end(&mut cypher)?; file.read_to_end(&mut cypher)?;
let secret_vec = decrypt(&cypher, password).map_err(|e| GcliError::Input(e.to_string()))?; let secret = decrypt(&cypher, password).map_err(|e| GcliError::Input(e.to_string()))?;
let secret = String::from_utf8(secret_vec).map_err(|e| anyhow!(e))?; let secretstr = String::from_utf8(secret).map_err(|e| anyhow!(e))?;
Ok(Some(secretstr))
//Still need to handle different secret formats
match secret_format {
SecretFormat::Substrate => {
Ok(Some(pair_from_str(&secret)?.into()))
}
SecretFormat::Seed => {
Ok(Some(pair_from_seed(&secret)?.into()))
}
SecretFormat::Cesium => {
let mut lines = secret.lines();
//Un-wrapping the 2 secrets from each line
let id = lines.next().unwrap();
let pwd = lines.next().unwrap();
Ok(Some(pair_from_cesium(id.to_string(), pwd.to_string()).into()))
}
SecretFormat::Predefined => {
Ok(Some(pair_from_predefined(&secret)?.into()))
}
}
} else { } else {
Ok(None) Ok(None)
} }
......
use sp_core::sr25519::Pair;
use crate::*; use crate::*;
use sr25519::Pair as Sr25519Pair; use sr25519::Pair as Sr25519Pair;
...@@ -18,12 +17,6 @@ pub enum SecretFormat { ...@@ -18,12 +17,6 @@ pub enum SecretFormat {
/// Cesium (scrypt + nacl) /// Cesium (scrypt + nacl)
Cesium, Cesium,
} }
pub enum Secret {
SimpleSecret(String),
DualSecret(String, String),
}
impl FromStr for SecretFormat { impl FromStr for SecretFormat {
type Err = std::io::Error; type Err = std::io::Error;
...@@ -159,15 +152,10 @@ pub fn pair_from_cesium(id: String, pwd: String) -> nacl::sign::Keypair { ...@@ -159,15 +152,10 @@ pub fn pair_from_cesium(id: String, pwd: String) -> nacl::sign::Keypair {
/// ask user to input a secret /// ask user to input a secret
pub fn prompt_secret_substrate() -> Sr25519Pair { pub fn prompt_secret_substrate() -> Sr25519Pair {
// Only interested in the keypair which is the second element of the tuple
prompt_secret_substrate_and_compute_keypair().1
}
pub fn prompt_secret_substrate_and_compute_keypair() -> (Secret, Sr25519Pair) {
loop { loop {
let mnemonic = rpassword::prompt_password("Mnemonic: ").unwrap(); let mnemonic = &rpassword::prompt_password("Mnemonic: ").unwrap();
match pair_from_str(&mnemonic) { match pair_from_str(mnemonic) {
Ok(pair) => return (Secret::SimpleSecret(mnemonic), pair), Ok(pair) => return pair,
Err(_) => println!("Invalid secret"), Err(_) => println!("Invalid secret"),
} }
} }
...@@ -175,27 +163,17 @@ pub fn prompt_secret_substrate_and_compute_keypair() -> (Secret, Sr25519Pair) { ...@@ -175,27 +163,17 @@ pub fn prompt_secret_substrate_and_compute_keypair() -> (Secret, Sr25519Pair) {
/// ask user pass (Cesium format) /// ask user pass (Cesium format)
pub fn prompt_secret_cesium() -> nacl::sign::Keypair { pub fn prompt_secret_cesium() -> nacl::sign::Keypair {
// Only interested in the keypair which is the second element of the tuple
prompt_secret_cesium_and_compute_keypair().1
}
pub fn prompt_secret_cesium_and_compute_keypair() -> (Secret, nacl::sign::Keypair) {
let id = rpassword::prompt_password("Cesium id: ").unwrap(); let id = rpassword::prompt_password("Cesium id: ").unwrap();
let pwd = rpassword::prompt_password("Cesium password: ").unwrap(); let pwd = rpassword::prompt_password("Cesium password: ").unwrap();
(Secret::DualSecret(id.clone(),pwd.clone()), pair_from_cesium(id, pwd)) pair_from_cesium(id, pwd)
} }
/// ask user to input a seed /// ask user to input a seed
pub fn prompt_seed() -> Sr25519Pair { pub fn prompt_seed() -> Sr25519Pair {
// Only interested in the keypair which is the second element of the tuple
prompt_seed_and_compute_keypair().1
}
pub fn prompt_seed_and_compute_keypair() -> (Secret,Pair) {
loop { loop {
let seed = rpassword::prompt_password("Seed: ").unwrap(); let seed = &rpassword::prompt_password("Seed: ").unwrap();
match pair_from_seed(&seed) { match pair_from_seed(seed) {
Ok(pair) => return (Secret::SimpleSecret(seed), pair), Ok(pair) => return pair,
Err(_) => println!("Invalid seed"), Err(_) => println!("Invalid seed"),
} }
} }
...@@ -203,13 +181,8 @@ pub fn prompt_seed_and_compute_keypair() -> (Secret,Pair) { ...@@ -203,13 +181,8 @@ pub fn prompt_seed_and_compute_keypair() -> (Secret,Pair) {
/// ask user pass (Cesium format) /// ask user pass (Cesium format)
pub fn prompt_predefined() -> Sr25519Pair { pub fn prompt_predefined() -> Sr25519Pair {
// Only interested in the keypair which is the second element of the tuple
prompt_predefined_and_compute_keypair().1
}
pub fn prompt_predefined_and_compute_keypair() -> (Secret, Sr25519Pair) {
let deriv = rpassword::prompt_password("Enter derivation path: ").unwrap(); let deriv = rpassword::prompt_password("Enter derivation path: ").unwrap();
(Secret::SimpleSecret(deriv.clone()), pair_from_predefined(&deriv).expect("invalid secret")) pair_from_predefined(&deriv).expect("invalid secret")
} }
/// ask user secret in relevant format /// ask user secret in relevant format
...@@ -231,9 +204,9 @@ pub fn fetch_or_get_keypair(data: &Data, address: Option<AccountId>) -> Result<K ...@@ -231,9 +204,9 @@ pub fn fetch_or_get_keypair(data: &Data, address: Option<AccountId>) -> Result<K
return Ok(pair_from_predefined(d).unwrap().into()); return Ok(pair_from_predefined(d).unwrap().into());
}; };
// look for corresponding KeyPair in keystore // look for corresponding secret in keystore
if let Some(key_pair) = commands::vault::try_fetch_key_pair(data, address)? { if let Some(secret) = commands::vault::try_fetch_secret(data, address)? {
return Ok(key_pair); return get_keypair(SecretFormat::Substrate, Some(&secret));
}; };
} }
// at the moment, there is no way to confg gcli to use an other kind of secret // at the moment, there is no way to confg gcli to use an other kind of secret
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment