You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
2.2 KiB

  1. package cmd
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. "strings"
  7. "github.com/bgentry/speakeasy"
  8. "github.com/mattn/go-isatty"
  9. "github.com/pkg/errors"
  10. "github.com/spf13/viper"
  11. data "github.com/tendermint/go-wire/data"
  12. "github.com/tendermint/tmlibs/cli"
  13. keys "github.com/tendermint/go-crypto/keys"
  14. )
  15. const PassLength = 10
  16. // if we read from non-tty, we just need to init the buffer reader once,
  17. // in case we try to read multiple passwords (eg. update)
  18. var buf *bufio.Reader
  19. func inputIsTty() bool {
  20. return isatty.IsTerminal(os.Stdin.Fd()) || isatty.IsCygwinTerminal(os.Stdin.Fd())
  21. }
  22. func stdinPassword() (string, error) {
  23. if buf == nil {
  24. buf = bufio.NewReader(os.Stdin)
  25. }
  26. pass, err := buf.ReadString('\n')
  27. if err != nil {
  28. return "", err
  29. }
  30. return strings.TrimSpace(pass), nil
  31. }
  32. func getPassword(prompt string) (pass string, err error) {
  33. if inputIsTty() {
  34. pass, err = speakeasy.Ask(prompt)
  35. } else {
  36. pass, err = stdinPassword()
  37. }
  38. if err != nil {
  39. return "", err
  40. }
  41. if len(pass) < PassLength {
  42. return "", errors.Errorf("Password must be at least %d characters", PassLength)
  43. }
  44. return pass, nil
  45. }
  46. func getCheckPassword(prompt, prompt2 string) (string, error) {
  47. // simple read on no-tty
  48. if !inputIsTty() {
  49. return getPassword(prompt)
  50. }
  51. // TODO: own function???
  52. pass, err := getPassword(prompt)
  53. if err != nil {
  54. return "", err
  55. }
  56. pass2, err := getPassword(prompt2)
  57. if err != nil {
  58. return "", err
  59. }
  60. if pass != pass2 {
  61. return "", errors.New("Passphrases don't match")
  62. }
  63. return pass, nil
  64. }
  65. func printInfo(info keys.Info) {
  66. switch viper.Get(cli.OutputFlag) {
  67. case "text":
  68. addr, err := data.ToText(info.Address)
  69. if err != nil {
  70. panic(err) // really shouldn't happen...
  71. }
  72. sep := "\t\t"
  73. if len(info.Name) > 7 {
  74. sep = "\t"
  75. }
  76. fmt.Printf("%s%s%s\n", info.Name, sep, addr)
  77. case "json":
  78. json, err := data.ToJSON(info)
  79. if err != nil {
  80. panic(err) // really shouldn't happen...
  81. }
  82. fmt.Println(string(json))
  83. }
  84. }
  85. func printInfos(infos keys.Infos) {
  86. switch viper.Get(cli.OutputFlag) {
  87. case "text":
  88. fmt.Println("All keys:")
  89. for _, i := range infos {
  90. printInfo(i)
  91. }
  92. case "json":
  93. json, err := data.ToJSON(infos)
  94. if err != nil {
  95. panic(err) // really shouldn't happen...
  96. }
  97. fmt.Println(string(json))
  98. }
  99. }