3

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 :)

4
  • 2
    use the getpass module Commented Feb 4, 2016 at 17:29
  • You should read the password from the tty (so that you can disable echoing of characters) and write your * on standard output or on the tty Commented Feb 4, 2016 at 17:29
  • @Paulo Scardine I'm trying to make my program check against a username and password as a fun project, that would defeat the point of what I'm doing :P Commented Feb 4, 2016 at 17:30
  • Actually what I wrote may be wrong: while echoing is disabled, characters written won't be shown. I don't think there exists a safe way Commented Feb 4, 2016 at 17:46

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

5 Comments

I don't know about Windows, but on UNIX this solution is subject to race conditions: if you type a character while if c == '\r' ... password += c ; sys.stdout.write('*') ... is executed, then the character will be displayed
@AndreaCorbellini Are you sure? We are not using asynchronous I/O here, getch is blocking. If you are able to trigger this bug, could you be kind enough to post a reproducible case?
The problem is not when 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 terminal
The getch() 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
Thanks. I guess it is hard enough to trigger that the OP can use it in practice if he accepts the risk of echoing some keystrokes when the system is under heavy load.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.