I'm trying to make a username and password program in Python, and although it isn't necessary to the final program, I thought it would be nice to make it display a different character when they input their text. Like most password fields, which may display something like an asterisk (*). So I was wondering how I might go about displaying their input as a different character. Thank you for any help :)
1 Answer
Using the getch recipe from the question " Python read a single character from the user "
def getpass(prompt):
sys.stdout.write(prompt)
sys.stdout.flush()
password = ''
while True:
c = getch()
if c == '\r':
sys.stdout.write('\n')
sys.stdout.flush()
return password
password += c
sys.stdout.write('*')
sys.stdout.flush()
Proof:
>>> getpass('secret: ')
secret: ********
'asdfsafd'
Echoing * for each character typed may fell cool from the UI perspective but will compromise security a bit because it gives up the length of the password. I guess that is why the builtin getpass module will not echo anything.
[update]
According to Andrea Corbellini, this implementation will leak keystrokes if the system is under heavy load, because it is resetting the tty before returning - characters may be echoed after getch() has returned and before getch() is called again. Looks like this is very hard to accomplish in a safe way, so probably this is the reason why the builtin getpass is not providing a visual feedback for each keystroke.
5 Comments
if c == '\r' ... password += c ; sys.stdout.write('*') ... is executed, then the character will be displayedgetch is blocking. If you are able to trigger this bug, could you be kind enough to post a reproducible case?getch is running, but when it's not running. Try putting a for i in range(100000): pass after the call to getch() (to simulate slow code or high CPU load) and run your script holding a pressed. You'll see an alternance of * and a characters on the terminalgetch() implementation you are using is resetting the tty before returning. So characters may be echoed after getch() has returned and before getch() is called again
*on standard output or on the tty