Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support pipe in key creation and export #57

Merged
merged 3 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 84 additions & 48 deletions pkg/operator/keys/create.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package keys

import (
"bufio"
"crypto/ecdsa"
"encoding/hex"
"errors"
Expand Down Expand Up @@ -42,6 +43,9 @@ use --key-type ecdsa/bls to create ecdsa/bls key.
It will prompt for password to encrypt the key, which is optional but highly recommended.
If you want to create a key with weak/no password, use --insecure flag. Do NOT use those keys in production

This command also support piping the password from stdin.
For example: echo "password" | eigenlayer keys create --key-type ecdsa keyname

This command will create keys in $HOME/.eigenlayer/operator_keys/ location
`,
Flags: []cli.Flag{
Expand All @@ -60,6 +64,9 @@ This command will create keys in $HOME/.eigenlayer/operator_keys/ location
return err
}

// Check if input is available in the pipe and read the password from it
stdInPassword := getStdInPassword()

keyType := ctx.String(KeyTypeFlag.Name)
insecure := ctx.Bool(InsecureFlag.Name)

Expand All @@ -69,13 +76,13 @@ This command will create keys in $HOME/.eigenlayer/operator_keys/ location
if err != nil {
return err
}
return saveEcdsaKey(keyName, p, privateKey, insecure)
return saveEcdsaKey(keyName, p, privateKey, insecure, stdInPassword)
case KeyTypeBLS:
blsKeyPair, err := bls.GenRandomBlsKeys()
if err != nil {
return err
}
return saveBlsKey(keyName, p, blsKeyPair, insecure)
return saveBlsKey(keyName, p, blsKeyPair, insecure, stdInPassword)
default:
return ErrInvalidKeyType
}
Expand All @@ -96,7 +103,7 @@ func validateKeyName(keyName string) error {
return nil
}

func saveBlsKey(keyName string, p utils.Prompter, keyPair *bls.KeyPair, insecure bool) error {
func saveBlsKey(keyName string, p utils.Prompter, keyPair *bls.KeyPair, insecure bool, stdInPassword string) error {
homePath, err := os.UserHomeDir()
if err != nil {
return err
Expand All @@ -106,28 +113,21 @@ func saveBlsKey(keyName string, p utils.Prompter, keyPair *bls.KeyPair, insecure
if checkIfKeyExists(fileLoc) {
return errors.New("key name already exists. Please choose a different name")
}
password, err := p.InputHiddenString("Enter password to encrypt the bls private key:", "",
func(s string) error {
if insecure {
return nil
}
return validatePassword(s)
},
)
if err != nil {
return err
}

_, err = p.InputHiddenString("Please confirm your password:", "",
func(s string) error {
if s != password {
return errors.New("passwords are not matched")
var password string
if len(stdInPassword) == 0 {
password, err = getPasswordFromPrompt(p, insecure, "Enter password to encrypt the bls private key:")
if err != nil {
return err
}
} else {
password = stdInPassword
if !insecure {
err = validatePassword(password)
if err != nil {
return err
}
return nil
},
)
if err != nil {
return err
}
}

err = keyPair.SaveToFile(fileLoc, password)
Expand All @@ -136,14 +136,20 @@ func saveBlsKey(keyName string, p utils.Prompter, keyPair *bls.KeyPair, insecure
}
// TODO: display it using `less` of `vi` so that it is not saved in terminal history
fmt.Println("BLS Private Key: " + keyPair.PrivKey.String())
fmt.Println("Please backup the above private key in safe place.")
fmt.Println("\033[1;32m🔐 Please backup the above private key hex in a safe place 🔒\033[0m")
fmt.Println()
fmt.Println("BLS Pub key: " + keyPair.PubKey.String())
fmt.Println("Key location: " + fileLoc)
fmt.Println("BLS Pub key: " + keyPair.PubKey.String())
return nil
}

func saveEcdsaKey(keyName string, p utils.Prompter, privateKey *ecdsa.PrivateKey, insecure bool) error {
func saveEcdsaKey(
keyName string,
p utils.Prompter,
privateKey *ecdsa.PrivateKey,
insecure bool,
stdInPassword string,
) error {
homePath, err := os.UserHomeDir()
if err != nil {
return err
Expand All @@ -154,29 +160,20 @@ func saveEcdsaKey(keyName string, p utils.Prompter, privateKey *ecdsa.PrivateKey
return errors.New("key name already exists. Please choose a different name")
}

password, err := p.InputHiddenString("Enter password to encrypt the ecdsa private key:", "",
func(s string) error {
if insecure {
return nil
}
return validatePassword(s)
},
)
if err != nil {
return err
}

_, err = p.InputHiddenString("Please confirm your password:", "",

func(s string) error {
if s != password {
return errors.New("passwords are not matched")
var password string
if len(stdInPassword) == 0 {
password, err = getPasswordFromPrompt(p, insecure, "Enter password to encrypt the ecdsa private key:")
if err != nil {
return err
}
} else {
password = stdInPassword
if !insecure {
err = validatePassword(password)
if err != nil {
return err
}
return nil
},
)
if err != nil {
return err
}
}

err = sdkEcdsa.WriteKey(fileLoc, privateKey, password)
Expand All @@ -188,6 +185,7 @@ func saveEcdsaKey(keyName string, p utils.Prompter, privateKey *ecdsa.PrivateKey
// TODO: display it using `less` of `vi` so that it is not saved in terminal history
fmt.Println("ECDSA Private Key (Hex): ", privateKeyHex)
fmt.Println("\033[1;32m🔐 Please backup the above private key hex in a safe place 🔒\033[0m")
fmt.Println()
fmt.Println("Key location: " + fileLoc)
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
Expand All @@ -201,6 +199,44 @@ func saveEcdsaKey(keyName string, p utils.Prompter, privateKey *ecdsa.PrivateKey
return nil
}

func getStdInPassword() string {
stat, _ := os.Stdin.Stat()
if (stat.Mode() & os.ModeCharDevice) == 0 {
// Input is available in the pipe, read from it
scanner := bufio.NewScanner(os.Stdin)
if scanner.Scan() {
return scanner.Text()
}
}
return ""
}

func getPasswordFromPrompt(p utils.Prompter, insecure bool, prompt string) (string, error) {
password, err := p.InputHiddenString(prompt, "",
func(s string) error {
if insecure {
return nil
}
return validatePassword(s)
},
)
if err != nil {
return "", err
}
_, err = p.InputHiddenString("Please confirm your password:", "",
func(s string) error {
if s != password {
return errors.New("passwords are not matched")
}
return nil
},
)
if err != nil {
return "", err
}
return password, nil
}

func checkIfKeyExists(fileLoc string) bool {
_, err := os.Stat(fileLoc)
return !os.IsNotExist(err)
Expand Down
10 changes: 8 additions & 2 deletions pkg/operator/keys/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ use --key-type ecdsa/bls to import ecdsa/bls key.
It will prompt for password to encrypt the key, which is optional but highly recommended.
If you want to import a key with weak/no password, use --insecure flag. Do NOT use those keys in production

This command also support piping the password from stdin.
For example: echo "password" | eigenlayer keys import --key-type ecdsa keyname privateKey

This command will import keys in $HOME/.eigenlayer/operator_keys/ location
`,
Flags: []cli.Flag{
Expand All @@ -52,6 +55,9 @@ This command will import keys in $HOME/.eigenlayer/operator_keys/ location
return err
}

// Check if input is available in the pipe and read the password from it
stdInPassword := getStdInPassword()

keyType := ctx.String(KeyTypeFlag.Name)
insecure := ctx.Bool(InsecureFlag.Name)

Expand All @@ -62,7 +68,7 @@ This command will import keys in $HOME/.eigenlayer/operator_keys/ location
if err != nil {
return err
}
return saveEcdsaKey(keyName, p, privateKeyPair, insecure)
return saveEcdsaKey(keyName, p, privateKeyPair, insecure, stdInPassword)
case KeyTypeBLS:
privateKeyBigInt := new(big.Int)
_, ok := privateKeyBigInt.SetString(privateKey, 10)
Expand All @@ -88,7 +94,7 @@ This command will import keys in $HOME/.eigenlayer/operator_keys/ location
return err
}
}
return saveBlsKey(keyName, p, blsKeyPair, insecure)
return saveBlsKey(keyName, p, blsKeyPair, insecure, stdInPassword)
default:
return ErrInvalidKeyType
}
Expand Down
Loading