Masking user input in python with asterisks

I am trying to mask what the user types into IDLE with asterisks so people around them can’t see what they’re typing/have typed in. I’m using basic raw input to collect what they type.

key = raw_input('Password :: ')

Ideal IDLE prompt after user types password:

Password :: **********

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

If you want a solution that works on Windows/macOS/Linux and on Python 2 & 3, you can install the pwinput module:

pip install pwinput

Unlike getpass.getpass() (which is in the Python Standard Library), the pwinput module can display *** mask characters as you type.

Example usage:

>>> pwinput.pwinput()
Password: *********
'swordfish'
>>> pwinput.pwinput(mask='X') # Change the mask character.
Password: XXXXXXXXX
'swordfish'
>>> pwinput.pwinput(prompt='PW: ', mask='*') # Change the prompt.
PW: *********
'swordfish'
>>> pwinput.pwinput(mask='') # Don't display anything.
Password:
'swordfish'

Unfortunately this module, like Python’s built-in getpass module, doesn’t work in IDLE or Jupyter Notebook.

More details at https://pypi.org/project/pwinput/

Note that pwinput is the new name for the stdiomask module.

Method 2

To solve this I wrote this small module pyssword to mask the user input password at the prompt. It works with windows. The code is below:

from msvcrt import getch
import getpass, sys

def pyssword(prompt='Password: '):
    '''
        Prompt for a password and masks the input.
        Returns:
            the value entered by the user.
    '''

    if sys.stdin is not sys.__stdin__:
        pwd = getpass.getpass(prompt)
        return pwd
    else:
        pwd = ""        
        sys.stdout.write(prompt)
        sys.stdout.flush()        
        while True:
            key = ord(getch())
            if key == 13: #Return Key
                sys.stdout.write('n')
                return pwd
                break
            if key == 8: #Backspace key
                if len(pwd) > 0:
                    # Erases previous character.
                    sys.stdout.write('b' + ' ' + 'b')                
                    sys.stdout.flush()
                    pwd = pwd[:-1]                    
            else:
                # Masks user input.
                char = chr(key)
                sys.stdout.write('*')
                sys.stdout.flush()                
                pwd = pwd + char

Method 3

Disclaimer: does not provide the asterix in terminal, but it does so in jupyter notebook.

The below code provides replaces written characters with asterix and allow for deletion of wrongly typed characters. The number of asterixes reflects the number of typed characters.

import getpass
key = getpass.getpass('Password :: ')

enter image description here

And after the user press enter:

enter image description here

Method 4

Depending on the OS, how you get a single character from user input and how to check for the carriage return will be different.

See this post: Python read a single character from the user

On OSX, for example, you could so something like this:

import sys, tty, termios

def getch():
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(sys.stdin.fileno())
        ch = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch

key = ""
sys.stdout.write('Password :: ')
while True:
    ch = getch()
    if ch == 'r':
        break
    key += ch
    sys.stdout.write('*')
print
print key

Method 5

I stumbled upon this thread while I was trying to preform the same feat. I know this thread is old, but if anyone else needs this – here is how I did it.

I ended up using readchar package.

Here is my solution, it prints asterisks and also handles backspaces:

import sys, readchar

def passprompt(prompt: str, out = sys.stdout) -> str:
    out.write(prompt); out.flush()
    password = ""
    while True:
        ch = str(readchar.readchar(), encoding='UTF-8')
        if ch == 'r':
            break
        elif ch == 'b':
            out.write('b b')
            password = password[0:len(password)-1]
            out.flush()
        else: 
            password += ch
            out.write('*')
            out.flush()
    return password

I had to regularly flush stdout for it to work.

Method 6

My suggestion is — DO NOT DO IT!

Don’t reinvent the wheel, use a password helper if you want ‘stars’

See https://stackoverflow.com/a/67327327/701532


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x