Capturando senhas no terminal com Go

Ler uma senha no terminal parece trivial, mas tem duas armadilhas: a senha aparece na tela se você usar a leitura comum, e você precisa garantir que é realmente um terminal e não redirecionamento. Vamos resolver as duas com o pacote golang.org/x/term.

Se você ler com bufio.Scanner ou fmt.Scanln, cada tecla aparece na tela. Para senha isso não serve. O term.ReadPassword lê direto do terminal, sem eco:

fd := int(os.Stdin.Fd()) // #nosec G115 -- stdin's fd is small; the conversion is safe
fmt.Print("password: ")
pass, err := term.ReadPassword(fd)
fmt.Println() // the user's Enter doesn't emit a newline; we do it

código fonte completo em

Se a entrada vier de um pipe, não há terminal para desligar o eco. Vale recusar antes:

if !term.IsTerminal(fd) {
    return "", errors.New("an interactive terminal is required for the password")
}

Quando a senha é nova, peça duas vezes e compare. Assim um erro de digitação não cria um segredo que você nunca mais consegue abrir:

Também usamos #nosec G115 para ignorar o alerta de segurança sobre o uso de os.Stdin.Fd(), que é seguro neste contexto.

Para comparar as senhas, você pode fazer cast para strings mas o melhor é usar bytes.Equal, que é mais eficiente.

Cesar Gimenes

Última modificação
Tags: