1

I would like to know if there is a way in Go to populate a password output with special characters when you are typing the password.

For example, I want to type the word "password" in the password field when it prompts me for the password. I want the output on the screen to look like this:

Enter Password: ********

Where the "********" are the characters of "password". Does GOLANG have something that will allow me to do this?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
jberthia
  • 111
  • 7
  • 1
    I'm sure there's no standard function for this. But which function you should use depends a lot on where you're reading the input (on the console? through a GUI?). Creating such a function should be a trivial task. – Jonathan Hall Mar 06 '19 at 20:28
  • It will be through the console only. The GUI is not involved. I am new to golang, so any help you can give would be greatly appreciated. – jberthia Mar 06 '19 at 20:30
  • Well then, whatever function you wrote to echo back the password... just modify it to echo back a * char instead. – Jonathan Hall Mar 06 '19 at 20:32
  • I would probably just use [`x/crypto/ssh/terminal.ReadPassword`](https://godoc.org/golang.org/x/crypto/ssh/terminal#ReadPassword). –  Mar 06 '19 at 20:34
  • @Flimzy console echos what's typed by default. You have to turn echo off. – Adrian Mar 06 '19 at 20:34
  • @Tim From what I see about ReadPassword, it returns things without a local echo. So, I am assuming this will not return anything when I type the password. Is there a way to modify this so that it will show some output? – jberthia Mar 06 '19 at 20:42
  • @Adrian: That depends how you're reading data from the console. – Jonathan Hall Mar 07 '19 at 06:32

2 Answers2

2

Take a look at this.

I know, it might not answer your question. But, this is an alternative to the answer. Instead of using ********* to mask the password, actually it will use the standard "blank" password masking on the terminal.

Here is the screenshot of the program when executed: Screenshot of running program

You can see at the Enter Password: part, that it is blank instead of asterisks ********* or other symbols.

Piko Monde
  • 396
  • 1
  • 4
  • 18
2

I'm a bit late to the party here, but here's how you can do it:

import (
        "fmt"
        "os"

        "golang.org/x/term"
)

type Tty struct {
        state *term.State
        line  string
}

func readPassword(tty chan Tty, fd int) {
        state, _ := term.MakeRaw(fd)
        t := term.NewTerminal(os.Stdin, "")
        f := func(s string, i int, r rune) (string, int, bool) {
                fmt.Print("*")
                return s, i, false
        }

        t.AutoCompleteCallback = f
        line, _ := t.ReadPassword(">")
        tty <- Tty{state: state, line: line}
}

func enterPassword() string {
        tty := make(chan Tty)
        fd := int(os.Stdin.Fd())
        go readPassword(tty, fd)
        t := <-tty
        close(tty)
        term.Restore(fd, t.state)
        password := t.line
        return password
}

Sadly, the AutoCompleteCallback function isn't triggered when a backspace or null character key is pressed. However, if you are ok with substituting another key for the backspace, you can clear out the existing line and replace it. For example, on my keyboard the delete key maps to 55302, so I can add a conditional as follows:

    f := func(s string, i int, r rune) (string, int, bool) {
        if r == 55302 {
            fmt.Printf("\r>%s", strings.Repeat(" ", i))
            fmt.Printf("\r>%s", strings.Repeat("*", i-1))
            return s[:i-1], i - 1, true
        }
        fmt.Print("*")
        return s, i, false
    }

This mimics the backspace functionality.

Eratosthenes
  • 2,280
  • 1
  • 14
  • 11
  • Does this also work with the previous "terminal" package? Or does it only work with this new "term" package? – Adam E. Jul 22 '22 at 21:01
  • 1
    It works with the previous "terminal" package as well (I just tested this). – Eratosthenes Jul 23 '22 at 13:53
  • This worked perfectly. Thanks! The only minor downside is the inability to backspace to delete characters one by one. However, it's okay, because most of the usage is used for pasting very long tokens. Never or rarely typed in. – Adam E. Jul 28 '22 at 13:24
  • Can this be modified in order to be able to delete characters? – acampana Sep 07 '22 at 07:50
  • 1
    @acampana I edited my response to answer your question about deleting characters; hope that helps. If anyone figures out a better way feel free to reply. – Eratosthenes Sep 11 '22 at 17:06
  • 2
    @AdamElkurd I did some investigation and came up with a workaround for deleting (see the edited post). – Eratosthenes Sep 11 '22 at 17:07
  • @Eratosthenes Thanks. Unfortunately, when I tested this on my side, the delete key did not map to anything. I tested this by printing the r value and when I press Delete on the main keyboard or Del on the number pad, it displays nothing on the screen. I'm using Windows by the way. I'm not sure if it's a keyboard thing or a platform thing. – Adam E. Sep 13 '22 at 20:50
  • 1
    @AdamElkurd that's a shame; it's probably specific to my keyboard. Well there is still a way to get it done, however, it can't be done the "easy" way with the autocompletecallback. This person has a repo with a method that works, though it's not maintained: https://github.com/howeyc/gopass – Eratosthenes Sep 14 '22 at 00:08