39

How can one read passwords in bash scripts in such a way that tools do not show it on a terminal?

(Changing font to black-on-black is easily worked around by copy & paste, so it's not solution.)

Kev
  • 1,729
  • 4
  • 27
  • 47
Grzegorz Wierzowiecki
  • 13,865
  • 23
  • 89
  • 137
  • 6
    For anyone reading this: do NOT read in passwords with echo on and black-on-black. The password is still transmitted, and if the terminal doesn't know the terminal directives you've used, characters will echo visibly. Turn echo off. Use `termios`, `stty`, `read -s`, anything that does it. – Alexios Mar 26 '12 at 22:14
  • 1
    That's why I've wrote, that it is not a solution ;). – Grzegorz Wierzowiecki Mar 26 '12 at 22:18
  • 1
    Indeed! Sometimes people skim questions and come to misguided conclusions. :) – Alexios Mar 26 '12 at 22:25

4 Answers4

50

From help read:

-s        do not echo input coming from a terminal

For example, to prompt the user and read an arbitrary password into the variable passwd,

IFS= read -s -p 'Password please: ' passwd
Kusalananda
  • 320,670
  • 36
  • 633
  • 936
Ignacio Vazquez-Abrams
  • 44,857
  • 7
  • 93
  • 100
  • 2
    Great. It's not written in my `man read`, I haven't check in `help read`. Good to know. – Grzegorz Wierzowiecki Mar 26 '12 at 21:19
  • 5
    @GrzegorzWierzowiecki: You are viewing the wrong manual. you have to read the manual of bash i.e `man bash` and there you can find -s option `Silent mode. If input is coming from a terminal, characters are not echoed.` – pradeepchhetri Mar 27 '12 at 06:34
11

I always used stty -echo to turn echoing off, then read and afterwards do stty echo (read more by viewing man of stty - i.e. man stty). This is more useful from a programmers perspective as you can turn echoing off and then read a password from a programming language such as Java, C(++), Python, etc. with their standard stdin "readers."

In bash, the usage could look like this:

echo -n "USERNAME: "; IFS= read -r uname
echo -n "PASSWORD: "; stty -echo; IFS= read -r passwd; stty echo; echo
program "$uname" "$passwd"
unset -v passwd    # get rid of passwd

Python, for example, would look like:

from sys import stdout
from os import system as term

uname = raw_input("USERNAME: ") # read input from stdin until [Enter] in 2
stdout.write("PASSWORD: ")
term("stty -echo") # turn echo off
try:
    passwd = raw_input()
except KeyboardInterrupt: # ctrl+c pressed
    raise SystemExit("Password attempt interrupted")
except EOFError: # ctrl+d pressed
    raise SystemExit("Password attempt interrupted")
finally:
    term("stty echo") # turn echo on again

print "username:", uname
print "password:", "*" * len(passwd)

I had to do this a lot of times in Python, so I know it pretty well from that perspective. This isn't very hard to translate to other languages, though.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
Dylan
  • 435
  • 5
  • 12
  • I'm finding that `stty -echo; sleep 3; stty echo` makes any characters entered show up _after_ the last command has completed. – hennes Jul 08 '22 at 19:07
0

If you're fine with adding an external dependency, you may use a password box provided by tools such as dialog or whiptail.

Whiptail

Peregrino69
  • 2,337
  • 1
  • 15
  • 22
Deyan
  • 1
-2

Your question reads kind of different "in a way like tools???" so I don't exactly know if this will work for you:

system1 $ passwd=abc123
system1 $ printf "%s\n" "${passwd//?/*}"
******
2bc
  • 3,938
  • 1
  • 17
  • 18