In this article, we will be discussing various ways how to take passwords as input in Golang (hide the password as typed) with practical examples.
Password is a secret word or phrase of defined length within the system, which is used to allow users to login into either computer, laptop, or web application. It can be of combined characters i.e characters, digits or special characters [*,&,^,%,$,#,@,!], etc. For an example password:- JDoe@124$%
The standard input stdin i.e terminal, the terminal allows the user to provide requested information on the terminal.
In Golang, we can read users’ passwords using the following packages:-
- using term package
- using io and os package
Different methods to hide password input in GO
Method 1:- Using the term package
In Golang, the term package provides a function that deals with
terminals i.e UNIX system.
An example of the UNIX system is the use of
isTerminal, Restore and MakeRaw function while for non-Unix systems
use os.Stdin.Fd().The bcrypt package is used to encrypt or hash
algorithm to calculate the hash. The bufio package enables us to
read characters from the standard input STDIN at once. The fmt
package is mostly used to handle Inputs and format the Outputs
operations while the os package provides low-level system
functionalities i.e Open, Write, Read, etc.
The example below demonstrate how to silently enter the password and encrypt it as well.
package main
import (
"bufio"
"fmt"
"golang.org/x/crypto/bcrypt"
"golang.org/x/term"
"os"
"strings"
"syscall"
)
func main() {
company, username, password, hash, match, err := ReadUsersInputs()
if err != nil {
fmt.Println(err)
}
fmt.Println("\n--------- You have provided the following information------------")
fmt.Printf("CompanyName: %s \nUsername: %s \nPassword: %s \nHashedPassword: %s \nMatch: %v \n", company, username, password, string(hash), match)
fmt.Println("---------End------------")
}
func ReadUsersInputs() (string, string, string, []byte, bool, error) {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter Your FirstName: ")
firstName, err := reader.ReadString('\n')
if len(strings.TrimSpace(firstName)) == 0 {
err = fmt.Errorf("Your FirstName can't be empty %v", firstName)
fmt.Println(err.Error())
os.Exit(1)
}
if err != nil {
return "", "", "", nil, false, err
}
fmt.Print("Enter Your LastName: ")
lastName, err := reader.ReadString('\n')
if len(strings.TrimSpace(lastName)) == 0 {
err = fmt.Errorf("Your LastName can't be empty %v", lastName)
fmt.Println(err.Error())
os.Exit(1)
}
if err != nil {
return "", "", "", nil, false, err
}
fmt.Print("Enter Your OrganisationName: ")
companyName, err := reader.ReadString('\n')
if len(strings.TrimSpace(companyName)) == 0 {
err = fmt.Errorf("Your Company Name can't be empty %v", companyName)
fmt.Println(err.Error())
os.Exit(1)
}
if err != nil {
return "", "", "", nil, false, err
}
// create username
username := firstName[0:1] + lastName
fmt.Print("Enter Password: ")
bytePassword, err := term.ReadPassword(syscall.Stdin)
if err != nil {
return "", "", "", nil, false, nil
}
password := string(bytePassword)
// hash the password
hash, err := PasswordHash(bytePassword)
if err != nil {
return "", "", "", nil, false, err
}
//check if matches
passwordMatch := HashPasswordCheck(bytePassword, hash)
return strings.TrimSpace(companyName), strings.TrimSpace(username), strings.TrimSpace(password), hash, passwordMatch, nil
}
func PasswordHash(password []byte) ([]byte, error) {
resBytes, err := bcrypt.GenerateFromPassword(password, 15)
return resBytes, err
}
func HashPasswordCheck(password, hash []byte) bool {
err := bcrypt.CompareHashAndPassword(hash, password)
return err == nil
}
Output:-
Validation of Inputs: You cant provide empty fields,
$ go run main.go
Enter Your FirstName:
Your FirstName can't be empty
exit status 1
Add all required fields
$ go run main.go
Enter Your FirstName: John
Enter Your LastName: Doe
Enter Your OrganisationName: GoCloudLinux
Enter Password:
--------- You have provided the following information------------
CompanyName: GoCloudLinux
Username: JDoe
Password: DJon@1234
HashedPassword: $2a$15$P4Yi9e/BinIgvo9X70j88.GCB7E7LBZyyKRtk7dvTTZW6rGhRI10y
Match: true
---------End------------
Explanation:-
In the above code, we have imported all required packages. main():- In
this piece of code, we are just handling the results from the
ReadUsersInputs function. Using fmt package to format those results
into various data types.
ReadUsersInputs():- this function does not accept any input values but
it returns various datatypes from strings to errors.
bufio.NewReader(os.Stdin) reads users inputs into assigned variables.
Our major focus is on the password variable
bytePassword, err:= term.ReadPassword(syscall.Stdin) this function
from term the package accepts the field of integer data type and it
finally returns the a []bytes and error. Using syscall.Stdin package
syscall contains an interface to the low-level operating system
primitives. Finally we hash that password using
bcrypt.GenerateFromPassword(password, 15).
Method 2:- Using io and os package
In this method, we are focusing on creating a custom function to read
masked passwords i.e using asterisks to display entered values. Golang
provides a package golang.org/x/crypto/ssh/terminal using functions
provided by terminal packages such as makeRaw, and Restore under
the terminal.isTerminal uses the function for the UNIX system.
Below is a detailed example of how to read masked passwords using Golang.
package main
import (
"bufio"
"fmt"
"gitlab.com/david_mbuvi/go_asterisks"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter Your FirstName: ")
firstName, err := reader.ReadString('\n')
if err != nil {
fmt.Println(err)
}
if len(strings.TrimSpace(firstName)) == 0 {
err = fmt.Errorf("Your FirstName can't be empty %v", firstName)
fmt.Println(err.Error())
os.Exit(1)
}
fmt.Print("Enter Your LastName: ")
lastName, err := reader.ReadString('\n')
if err != nil {
fmt.Println(err)
}
if len(strings.TrimSpace(lastName)) == 0 {
err = fmt.Errorf("Your LastName can't be empty %v", lastName)
fmt.Println(err.Error())
os.Exit(1)
}
fmt.Print("Enter Your OrganisationName: ")
company, err := reader.ReadString('\n')
if err != nil {
fmt.Println(err.Error())
}
if len(strings.TrimSpace(company)) == 0 {
err = fmt.Errorf("Your OrganisationName can't be empty %v", company)
fmt.Println(err.Error())
os.Exit(1)
}
// create username
username := firstName[0:1] + lastName
fmt.Printf("Enter your password: ")
// The password you provided from the terminal, echoing as asterisks.
password, err := go_asterisks.GetUsersPassword("", true, os.Stdin, os.Stdout)
if err != nil {
fmt.Println(err.Error())
}
fmt.Println("\n--------- You have provided the following information------------")
fmt.Printf("CompanyName: %s\nUsername: %s\nPassword: %s\n", company, username, password)
fmt.Println("---------End------------")
}
Output:
$ go run main.go
Enter Your FirstName: Doe
Enter Your LastName: John
Enter Your OrganisationName: AWS
Enter your password: *******
--------- You have provided the following information------------
CompanyName: AWS
Username: DJohn
Password: NJ0@123
---------End------------
Explanation:-
In the above code, we have created the readChunk() function which is
for reading users’ inputs in chunks of specific length into the buffer.
getUsersPassword(prompt string, masked bool, r FieldReader, w io.Writer)([]byte, error){}
its a function that returns inputs read from the terminal. It validates
various variables namely prompt if its empty output is prompted to
the user, masked if its true, typing will be matched by asterisks
on the screen i.e ******* . the rest will display nothing
however they hold the state of the terminal implemented using the if
terminal.IsTerminal(int(r.Fd())) {}.
Summary
In this article, we have discussed and demonstrated two ways of reading users’ passwords on the terminal. This is critical because the password is essential for access or authorization into an application or system i.e user login to a Linux machine or software etc. the password should be in asterisks or not displayed. This can help software engineer to develop a command line interface CLI login system on a terminal using Golang.

![Golang hide password input [Replace input with asterisk]](/golang-hide-password-input/golang_hide_password_input.jpg)
