Turn echo off when reading passwords

This commit is contained in:
Javed Khan 2014-10-20 20:59:23 +05:30 committed by Dave Collins
parent b44f48882f
commit 45a33353b0

View file

@ -18,6 +18,7 @@ package main
import ( import (
"bufio" "bufio"
"bytes"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"os" "os"
@ -31,6 +32,7 @@ import (
"github.com/btcsuite/btcwallet/waddrmgr" "github.com/btcsuite/btcwallet/waddrmgr"
"github.com/btcsuite/btcwallet/walletdb" "github.com/btcsuite/btcwallet/walletdb"
_ "github.com/btcsuite/btcwallet/walletdb/bdb" _ "github.com/btcsuite/btcwallet/walletdb/bdb"
"golang.org/x/crypto/ssh/terminal"
) )
// promptConsoleList prompts the user with the given prefix, list of valid // promptConsoleList prompts the user with the given prefix, list of valid
@ -83,17 +85,18 @@ func promptConsoleListBool(reader *bufio.Reader, prefix string, defaultEntry str
// promptConsolePass prompts the user for a passphrase with the given prefix. // promptConsolePass prompts the user for a passphrase with the given prefix.
// The function will ask the user to confirm the passphrase and will repeat // The function will ask the user to confirm the passphrase and will repeat
// the prompts until they enter a matching response. // the prompts until they enter a matching response.
func promptConsolePass(reader *bufio.Reader, prefix string, confirm bool) (string, error) { func promptConsolePass(reader *bufio.Reader, prefix string, confirm bool) ([]byte, error) {
// Prompt the user until they enter a passphrase. // Prompt the user until they enter a passphrase.
prompt := fmt.Sprintf("%s: ", prefix) prompt := fmt.Sprintf("%s: ", prefix)
for { for {
fmt.Print(prompt) fmt.Print(prompt)
pass, err := reader.ReadString('\n') pass, err := terminal.ReadPassword(int(os.Stdin.Fd()))
if err != nil { if err != nil {
return "", err return nil, err
} }
pass = strings.TrimSpace(pass) fmt.Print("\n")
if pass == "" { pass = bytes.TrimSpace(pass)
if len(pass) == 0 {
continue continue
} }
@ -102,12 +105,13 @@ func promptConsolePass(reader *bufio.Reader, prefix string, confirm bool) (strin
} }
fmt.Print("Confirm passphrase: ") fmt.Print("Confirm passphrase: ")
confirm, err := reader.ReadString('\n') confirm, err := terminal.ReadPassword(int(os.Stdin.Fd()))
if err != nil { if err != nil {
return "", err return nil, err
} }
confirm = strings.TrimSpace(confirm) fmt.Print("\n")
if pass != confirm { confirm = bytes.TrimSpace(confirm)
if !bytes.Equal(pass, confirm) {
fmt.Println("The entered passphrases do not match") fmt.Println("The entered passphrases do not match")
continue continue
} }
@ -122,7 +126,7 @@ func promptConsolePass(reader *bufio.Reader, prefix string, confirm bool) (strin
// used to unlock it. On the other hand, when the legacy keystore is nil, the // used to unlock it. On the other hand, when the legacy keystore is nil, the
// user is prompted for a new private passphrase. All prompts are repeated // user is prompted for a new private passphrase. All prompts are repeated
// until the user enters a valid response. // until the user enters a valid response.
func promptConsolePrivatePass(reader *bufio.Reader, legacyKeyStore *keystore.Store) (string, error) { func promptConsolePrivatePass(reader *bufio.Reader, legacyKeyStore *keystore.Store) ([]byte, error) {
// When there is not an existing legacy wallet, simply prompt the user // When there is not an existing legacy wallet, simply prompt the user
// for a new private passphase and return it. // for a new private passphase and return it.
if legacyKeyStore == nil { if legacyKeyStore == nil {
@ -140,7 +144,7 @@ func promptConsolePrivatePass(reader *bufio.Reader, legacyKeyStore *keystore.Sto
privPass, err := promptConsolePass(reader, "Enter the private "+ privPass, err := promptConsolePass(reader, "Enter the private "+
"passphrase for your existing wallet", false) "passphrase for your existing wallet", false)
if err != nil { if err != nil {
return "", err return nil, err
} }
// Keep prompting the user until the passphrase is correct. // Keep prompting the user until the passphrase is correct.
@ -150,7 +154,7 @@ func promptConsolePrivatePass(reader *bufio.Reader, legacyKeyStore *keystore.Sto
continue continue
} }
return "", err return nil, err
} }
return privPass, nil return privPass, nil
@ -165,29 +169,30 @@ func promptConsolePrivatePass(reader *bufio.Reader, legacyKeyStore *keystore.Sto
// and prompt the user if they are sure they want to use the same passphrase for // and prompt the user if they are sure they want to use the same passphrase for
// both. Finally, all prompts are repeated until the user enters a valid // both. Finally, all prompts are repeated until the user enters a valid
// response. // response.
func promptConsolePublicPass(reader *bufio.Reader, privPass string, cfg *config) (string, error) { func promptConsolePublicPass(reader *bufio.Reader, privPass []byte, cfg *config) ([]byte, error) {
pubPass := defaultPubPassphrase pubPass := []byte(defaultPubPassphrase)
usePubPass, err := promptConsoleListBool(reader, "Do you want "+ usePubPass, err := promptConsoleListBool(reader, "Do you want "+
"to add an additional layer of encryption for public "+ "to add an additional layer of encryption for public "+
"data?", "no") "data?", "no")
if err != nil { if err != nil {
return "", err return nil, err
} }
if !usePubPass { if !usePubPass {
return pubPass, nil return pubPass, nil
} }
if cfg.WalletPass != pubPass { walletPass := []byte(cfg.WalletPass)
if !bytes.Equal(walletPass, pubPass) {
useExisting, err := promptConsoleListBool(reader, "Use the "+ useExisting, err := promptConsoleListBool(reader, "Use the "+
"existing configured public passphrase for encryption "+ "existing configured public passphrase for encryption "+
"of public data?", "no") "of public data?", "no")
if err != nil { if err != nil {
return "", err return nil, err
} }
if useExisting { if useExisting {
return cfg.WalletPass, nil return walletPass, nil
} }
} }
@ -195,15 +200,15 @@ func promptConsolePublicPass(reader *bufio.Reader, privPass string, cfg *config)
pubPass, err = promptConsolePass(reader, "Enter the public "+ pubPass, err = promptConsolePass(reader, "Enter the public "+
"passphrase for your new wallet", true) "passphrase for your new wallet", true)
if err != nil { if err != nil {
return "", err return nil, err
} }
if pubPass == privPass { if bytes.Equal(pubPass, privPass) {
useSamePass, err := promptConsoleListBool(reader, useSamePass, err := promptConsoleListBool(reader,
"Are you sure want to use the same passphrase "+ "Are you sure want to use the same passphrase "+
"for public and private data?", "no") "for public and private data?", "no")
if err != nil { if err != nil {
return "", err return nil, err
} }
if useSamePass { if useSamePass {