Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Ğ
Ğcli-v2s
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Nicolas80
Ğcli-v2s
Commits
fb218187
Commit
fb218187
authored
5 months ago
by
Nicolas80
Browse files
Options
Downloads
Patches
Plain Diff
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
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/commands/vault.rs
+21
-121
21 additions, 121 deletions
src/commands/vault.rs
src/keys.rs
+11
-38
11 additions, 38 deletions
src/keys.rs
with
32 additions
and
159 deletions
src/commands/vault.rs
+
21
−
121
View file @
fb218187
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
)
}
}
...
...
This diff is collapsed.
Click to expand it.
src/keys.rs
+
11
−
38
View file @
fb218187
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
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment