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
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.