diff --git a/cmd/main.go b/cmd/main.go index 975fd99..692b371 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -16,14 +16,14 @@ import ( ) const ( - flagKeyType = "key-type" - flagKeyPassword = "password" - flagPrivateKey = "private-key" - flagKeyPath = "key-path" - flagNetwork = "network" - flagChain = "chain" - flagDockerImage = "docker-image" - flagKeyIndex = "key-index" + flagKeyType = "key-type" + flagKeyPasswordPath = "password-path" + flagPrivateKey = "private-key" + flagKeyPath = "key-path" + flagNetwork = "network" + flagChain = "chain" + flagDockerImage = "docker-image" + flagKeyIndex = "key-index" ) var ( @@ -39,8 +39,8 @@ var ( Usage: "Key `TYPE` (bls/ecdsa)", Aliases: []string{"t"}, } - keyPasswordFlag = &cli.StringFlag{ - Name: flagKeyPassword, + keyPasswordPathFlag = &cli.StringFlag{ + Name: flagKeyPasswordPath, Value: "", Usage: "Keystore `PASSWORD`", Aliases: []string{"p"}, @@ -104,7 +104,7 @@ func main() { Usage: "Generate a new keystore file for the given key type (bls/ecdsa)", Flags: []cli.Flag{ keyTypeFlag, - keyPasswordFlag, + keyPasswordPathFlag, }, Action: generateKeystore, }, @@ -113,7 +113,7 @@ func main() { Usage: "Import a private key to the keystore for the given key type (bls/ecdsa)", Flags: []cli.Flag{ keyTypeFlag, - keyPasswordFlag, + keyPasswordPathFlag, privateKeyFlag, }, Action: importKeystore, @@ -123,7 +123,7 @@ func main() { Usage: "Export a private key from the keystore", Flags: []cli.Flag{ keyTypeFlag, - keyPasswordFlag, + keyPasswordPathFlag, keyPathFlag, }, Action: exportKeystore, @@ -234,22 +234,22 @@ func main() { func generateKeystore(c *cli.Context) error { keyType := strings.ToLower(c.String(flagKeyType)) - password := c.String(flagKeyPassword) - return utils.GenerateKeystore(keyType, password) + passwordPath := c.String(flagKeyPasswordPath) + return utils.GenerateKeystore(keyType, passwordPath) } func importKeystore(c *cli.Context) error { keyType := strings.ToLower(c.String(flagKeyType)) - password := c.String(flagKeyPassword) + passwordPath := c.String(flagKeyPasswordPath) privKey := nutils.Hex2Bytes(c.String(flagPrivateKey)) - return utils.ImportFromPrivateKey(keyType, password, privKey) + return utils.ImportFromPrivateKey(keyType, passwordPath, privKey) } func exportKeystore(c *cli.Context) error { keyType := strings.ToLower(c.String(flagKeyType)) - password := c.String(flagKeyPassword) + passwordPath := c.String(flagKeyPasswordPath) keyPath := c.String(flagKeyPath) - privKey, err := utils.ExportKeystore(keyType, password, keyPath) + privKey, err := utils.ExportKeystore(keyType, passwordPath, keyPath) if err != nil { return err } diff --git a/utils/keystore.go b/utils/keystore.go index 4a60355..2802ecd 100644 --- a/utils/keystore.go +++ b/utils/keystore.go @@ -14,7 +14,12 @@ import ( const keystoreDir = ".lagrange/keystore" // GenerateKeystore generates a new keystore file for the given key. -func GenerateKeystore(keyType, password string) error { +func GenerateKeystore(keyType, passwordPath string) error { + password, err := crypto.ReadKeystorePasswordFromFile(passwordPath) + if err != nil { + return fmt.Errorf("failed to read password from file: %w", err) + } + switch keyType { case "ecdsa": privateKey, err := ecrypto.GenerateKey() @@ -41,7 +46,12 @@ func GenerateKeystore(keyType, password string) error { } // ImportFromPrivateKey imports a private key to the keystore. -func ImportFromPrivateKey(keyType, password string, privKey []byte) error { +func ImportFromPrivateKey(keyType, passwordPath string, privKey []byte) error { + password, err := crypto.ReadKeystorePasswordFromFile(passwordPath) + if err != nil { + return fmt.Errorf("failed to read password from file: %w", err) + } + switch keyType { case "ecdsa": privateKey, err := ecrypto.ToECDSA(privKey) @@ -63,12 +73,31 @@ func ImportFromPrivateKey(keyType, password string, privKey []byte) error { } // ExportKeystore exports the private key from the keystore file. -func ExportKeystore(keyType, password, filePath string) ([]byte, error) { +func ExportKeystore(keyType, passwordPath, filePath string) ([]byte, error) { + password, err := crypto.ReadKeystorePasswordFromFile(passwordPath) + if err != nil { + return nil, fmt.Errorf("failed to read password from file: %w", err) + } + switch keyType { case "ecdsa": - return crypto.LoadPrivateKey(crypto.CryptoCurve("ECDSA"), password, filePath) + privateKey, err := crypto.LoadPrivateKey(crypto.CryptoCurve("ECDSA"), password, filePath) + if err != nil { + return nil, fmt.Errorf("failed to load ECDSA private key: %w", err) + } + if err := DisplayWarningMessage(keyType, nutils.Bytes2Hex(privateKey), filePath); err != nil { + return nil, fmt.Errorf("failed to display warning message: %w", err) + } + return privateKey, nil case "bls": - return crypto.LoadPrivateKey(crypto.CryptoCurve("BN254"), password, filePath) + privateKey, err := crypto.LoadPrivateKey(crypto.CryptoCurve("BN254"), password, filePath) + if err != nil { + return nil, fmt.Errorf("failed to load BLS private key: %w", err) + } + if err := DisplayWarningMessage(keyType, nutils.Bytes2Hex(privateKey), filePath); err != nil { + return nil, fmt.Errorf("failed to display warning message: %w", err) + } + return privateKey, nil default: return nil, fmt.Errorf("invalid key type: %s", keyType) } @@ -86,7 +115,9 @@ func saveKeystore(keyType string, password string, pubKey, privKey []byte) error } else if keyType == "bls" { cryptoCurve = crypto.CryptoCurve("BN254") } - DisplayWarningMessage(keyType, nutils.Bytes2Hex(privKey), ksPath) + if err := DisplayWarningMessage(keyType, nutils.Bytes2Hex(privKey), ksPath); err != nil { + return fmt.Errorf("failed to display warning message: %w", err) + } return crypto.SaveKey(cryptoCurve, privKey, password, ksPath) } diff --git a/utils/utils.go b/utils/utils.go index b09a64a..bd2d9d5 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -23,31 +23,55 @@ func ConvertBLSKey(blsPubKey []byte) ([2]*big.Int, error) { } // DisplayWarningMessage displays a warning message with ASCII art. -func DisplayWarningMessage(keyType, privateKey, ksPath string) { +func DisplayWarningMessage(keyType, privateKey, ksPath string) error { // Clear the screen - cmd := exec.Command("clear") // For Windows use "cls" + cmd := exec.Command("less", "-R") // For Windows use "cls" cmd.Stdout = os.Stdout - if err := cmd.Run(); err != nil { - fmt.Println("failed to clear the screen: ", err) + cmd.Stderr = os.Stderr + + stdin, err := cmd.StdinPipe() + if err != nil { + return fmt.Errorf("failed to create stdin pipe: %w", err) + } + if err := cmd.Start(); err != nil { + return fmt.Errorf("failed to start command: %w", err) } + msg := "" // Display warning message with ASCII art and colored text - fmt.Println("\033[1m\x1b[36m#########################################################################\033[0m") - fmt.Println("\033[1m\x1b[36m# _ _____ _____ _____ _____ _ _ _____ ______ #\033[0m") - fmt.Println("\033[1m\x1b[36m# (_) (_____) (_____) (_____) (_____) (_) (_) (_____) (______) #\033[0m") - fmt.Println("\033[1m\x1b[36m# (_) (_)___(_)(_) ___ (_)__(_)(_)___(_)(__)_ (_)(_) ___ (_)__ #\033[0m") - fmt.Println("\033[1m\x1b[36m# (_) (_______)(_) (___)(_____) (_______)(_)(_)(_)(_) (___)(____) #\033[0m") - fmt.Println("\033[1m\x1b[36m# (_)____ (_) (_)(_)___(_)( ) ( ) (_) (_)(_) (__)(_)___(_)(_)____ #\033[0m") - fmt.Println("\033[1m\x1b[36m# (______)(_) (_) (_____) (_) (_)(_) (_)(_) (_) (_____) (______) #\033[0m") - fmt.Println("\033[1m\x1b[36m#########################################################################\033[0m") - - fmt.Println("") - fmt.Println(strings.ToUpper(keyType) + " Private Key Generated Successfully 🎉") + msg += fmt.Sprintln("\033[1m\x1b[36m#########################################################################\033[0m") + msg += fmt.Sprintln("\033[1m\x1b[36m# _ _____ _____ _____ _____ _ _ _____ ______ #\033[0m") + msg += fmt.Sprintln("\033[1m\x1b[36m# (_) (_____) (_____) (_____) (_____) (_) (_) (_____) (______) #\033[0m") + msg += fmt.Sprintln("\033[1m\x1b[36m# (_) (_)___(_)(_) ___ (_)__(_)(_)___(_)(__)_ (_)(_) ___ (_)__ #\033[0m") + msg += fmt.Sprintln("\033[1m\x1b[36m# (_) (_______)(_) (___)(_____) (_______)(_)(_)(_)(_) (___)(____) #\033[0m") + msg += fmt.Sprintln("\033[1m\x1b[36m# (_)____ (_) (_)(_)___(_)( ) ( ) (_) (_)(_) (__)(_)___(_)(_)____ #\033[0m") + msg += fmt.Sprintln("\033[1m\x1b[36m# (______)(_) (_) (_____) (_) (_)(_) (_)(_) (_) (_____) (______) #\033[0m") + msg += fmt.Sprintln("\033[1m\x1b[36m#########################################################################\033[0m") + + msg += fmt.Sprintln("") + msg += fmt.Sprintln(strings.ToUpper(keyType) + " Private Key Generated Successfully 🎉") border := strings.Repeat("=", len(privateKey)+6) - fmt.Println("\033[1m\x1b[31m" + border + "\033[0m") - fmt.Println("\x1b[36m| " + privateKey + " |\033[0m") - fmt.Println("\033[1m\x1b[31m" + border + "\033[0m") - fmt.Println("") - fmt.Println("\033[1m\x1b[33m🔑 WARNING: Make sure to copy this private key securely and never share it with anyone!\033[0m") - fmt.Println("🔑 Keystore file saved at: " + ksPath) + msg += fmt.Sprintln("\033[1m\x1b[31m" + border + "\033[0m") + msg += fmt.Sprintln("\x1b[36m| " + privateKey + " |\033[0m") + msg += fmt.Sprintln("\033[1m\x1b[31m" + border + "\033[0m") + msg += fmt.Sprintln("") + msg += fmt.Sprintln("\033[1m\x1b[33m🔑 WARNING: Make sure to copy this private key securely and never share it with anyone!\033[0m") + msg += fmt.Sprintln("🔑 Keystore file saved at: " + ksPath) + + // Write the message to the command + if _, err = stdin.Write([]byte(msg)); err != nil { + return fmt.Errorf("failed to write to stdin: %w", err) + } + + // Close the stdin pipe + if err := stdin.Close(); err != nil { + return fmt.Errorf("failed to close stdin: %w", err) + } + + // Wait for the command to finish + if err := cmd.Wait(); err != nil { + return fmt.Errorf("failed to wait for command: %w", err) + } + + return nil }