Bash script to accept password and replace characters with * as they are typed

I googled this and couldn't find an answer, so I rolled my own. Here it is, hope it helps. Feel free to improve on it.

#!/bin/bash
PWORD=
ANYKEY=0
echo -n "Password:  "
until [ -z "$ANYKEY" ]
do
    read -N 1 -s ANYKEY
    echo -n "*"
    PWORD="$PWORD$ANYKEY"
done
echo
echo $PWORD
exit
#!/bin/bash

passwd=""
omodes=$(stty -g)

printf "Enter Password: "
while :
do
   stty raw -echo
   c=$(dd bs=1 count=1 2>/dev/null)
   stty -raw

   # break out of loop if CR found
   [[ -z $(echo $c | tr -d "\015") ]] && break

   stty echo
   printf "*"
   passwd=${passwd}${c}
done

stty $omodes

printf "\nPassword entered: $passwd\n"

Sort of cute, couple of thoughts:

  1. Use -r option of read to avoid backslash acting as an escape
  2. How about support for backspace to allow correction of typos

For the sake of argument, here is an example ksh script called "getpw" that I have in my bag of tricks. I did not write this, but saw it somewhere and saved it. My apologies to the author. Perhaps it can be adapted to bash, or at least studied to learn some new tricks :slight_smile:

#! /usr/bin/ksh
exec 4>/dev/tty
function getpass
{
  typeset prompt=$1
  typeset backspace=$(echo  \\b\\c)
  typeset enter=$(echo \\r\\c)
  typeset savesetting=$(stty -g)
  typeset keystroke password n i reading result
  n=0
  echo "${prompt}"\\c >&4
  stty -echo -icrnl -icanon min 1 time 0
  reading=1

  while ((reading)) ; do
    keystroke=$(dd bs=1 count=1 2>/dev/null)
    case $keystroke in
          $enter) reading=0
                  ;;
      $backspace) if ((n)) ; then
                    echo "${backspace} ${backspace}"\\c >&4
                    ((n=n-1))
                  fi
                  ;;
               *) echo \*\\c >&4
                  data[n]=$keystroke
                  ((n=n+1))
                  ;;
    esac
  done

  stty "$savesetting"
  echo >&4
  result=""
  i=0

  while ((i<n)) ; do
    result="${result}${data}"
    ((i=i+1))
  done

  echo $result
  return 0
}

final=$(getpass "password: ")
echo the password is $final
exit 0
2 Likes