How to mask user password input and save it as output to replace default password in another file

Question:

I want to let user enter his password using input and the output is masked as asterisk,and the user input will be used to change another file info( i’m using python 3 on windows 10).

I know i could use the getpass.getpass() and showing password as asterisk is risky because it let others read and count how long is the password, but since i want to make this small app looking ‘profesional’ and let user feel safe then i see the need to mask the password.

And finally the output should be saved to replace another file basic info such as email, user id and password.

I’ve succeeded to replace all of them except the password out since it only change the entered password(mynewpassword12345) to "" .

I tried reading Masking user input in python with asterisks, but the accepted answer has no direction on how to or didnt provide example. I also tried Masking user input in python with asterisks , but the accepted answer doesn’t appear to be applicable to Windows.

Below is sample code example i got from SO answer to mask user password as asterisk ( but sorry that i forgot to save the link).

It worked on python exe(but not on idle) and is masking user password input as asterisk, but it did not let me save the printed password as user output.

So far this is what i’m trying to do, extract a zip file from certin folder in certain path, prompt user to input and add to change default info i.e email, id, and etc.

from zipfile import ZipFile
from selenium.webdriver.support.ui import WebDriverWait
import fileinput
import os
import py_compile
import shutil, glob
import textwrap
import datetime
import msvcrt
import time
import sys

script_dir = os.path.dirname(__file__)
file_path2 = os.path.join(script_dir, ' alert ' , 'temp' , 'temp folder' , 'temp' , 'myapp.zip')
##print(file_path2)
NameFile2 = file_path2

with ZipFile(NameFile2, 'r') as zf:
    zf.extractall(os.path.join(script_dir, 'alert' , 'temp' , 'temp folder' , 'temp' ) , pwd=b'mypassword' )

file_path = os.path.join(script_dir, ' alert ' , 'temp' , 'temp folder' , 'temp' , 'myapp.py')
##print(file_path)
NameFile = file_path


email = "emailaddress"
password = "userpassword"
userID = "userID"
id1 = "id1"
id2 = "id2"
id3 = "id3"
id4 = "id4"
id5 = "id5"
id6 = "id6"
id7 = "id7"
id8 = "id8"
id9 = "id9"
idlast = "idlast"

level = 3
##
x = datetime.datetime.now()
text1 = '''hi, welcome to my app.
'''
#print('t' * level, text1 )
#print(textwrap.fill(text1, 60))

print(" ")


print((x.strftime("%c")).center(80))
print(" ")
for line in textwrap.wrap(text1, width=50):
    print(line.center(80))


print(" ")



newemail = input ("  email : " )

#newpassword = input ("  password : ")


list1 = []
def getPASS():
    print("Input password")
    list1 = []
    while True:
        char = msvcrt.getch()
        char =str(char)
        char = char[2:-1]
        if char == "\n'" or char == "\r":
            break
        elif char == "\x08":
            del list1[-1]
            os.system("cls")
            print("Input password:")
            sys.stdout.write("*" * len(list1))
            sys.stdout.flush()
            continue
        else:
            list1.append(char)
            sys.stdout.write("*")
            sys.stdout.flush()
print("n")
psw = "".join(list1)
print(psw)
invalid = ' ,:;/?"}]{[-=+!@#$%^&*()|'
for x in psw:
    if x in invalid:
        print("Character %r is not allowed in password" % x)
        getPASS()
    else:
        pass

getPASS()

newpassword = psw

newuserID = input ("  userID : ")
newid1 = input ("  ID seefirst1 : ")
newid2 = input ("  ID seefirst2 : ")
newid3 = input ("  ID seefirst3 : ")
newid4 = input ("  ID seefirst4 : ")
newid5 = input ("  ID seefirst5 : ")
newid6 = input ("  ID seefirst6 : ")
newid7 = input ("  ID seefirst7 : ")
newid8 = input ("  ID seefirst8 : ")
newid9 = input ("  ID seefirst9 : ")
newidlast = input ("  ID seefirst10 : ")


with fileinput.FileInput(NameFile, inplace=True, backup='.bak') as file:
        for line in file:
            print(line.replace(email, newemail), end='')

with fileinput.FileInput(NameFile, inplace=True, backup='.bak') as file:
        for line in file:
            print(line.replace(password, newpassword), end='')

with fileinput.FileInput(NameFile, inplace=True, backup='.bak') as file:
        for line in file:
            print(line.replace(userID, newuserID), end='')


with fileinput.FileInput(NameFile, inplace=True, backup='.bak') as file:
        for line in file:
            print(line.replace(id1, newid1), end='')
            
with fileinput.FileInput(NameFile, inplace=True, backup='.bak') as file:
        for line in file:
            print(line.replace(id2, newid2), end='')
                
with fileinput.FileInput(NameFile, inplace=True, backup='.bak') as file:
        for line in file:
            print(line.replace(id3, newid3), end='')
            
with fileinput.FileInput(NameFile, inplace=True, backup='.bak') as file:
        for line in file:
            print(line.replace(id4, newid4), end='')
            
with fileinput.FileInput(NameFile, inplace=True, backup='.bak') as file:
        for line in file:
            print(line.replace(id5, newid5), end='')
            
with fileinput.FileInput(NameFile, inplace=True, backup='.bak') as file:
        for line in file:
            print(line.replace(id6, newid6), end='')
            
with fileinput.FileInput(NameFile, inplace=True, backup='.bak') as file:
        for line in file:
            print(line.replace(id7, newid7), end='')
            
with fileinput.FileInput(NameFile, inplace=True, backup='.bak') as file:
        for line in file:
            print(line.replace(id8, newid8), end='')
            
with fileinput.FileInput(NameFile, inplace=True, backup='.bak') as file:
        for line in file:
            print(line.replace(id9, newid9), end='')
            
with fileinput.FileInput(NameFile, inplace=True, backup='.bak') as file:
        for line in file:
            print(line.replace(idlast, newidlast), end='')
            


#wait = WebDriverWait(driver, 10)
            
file_path3 = os.path.join(script_dir, ' alert ' , 'temp' , 'temp folder' , 'temp' , 'myapp.py')
#print(file_path3)
script = file_path3
py_compile.compile(script)

            


from pathlib import Path

# ...

#pathtofile = Path(__file__).parent.parent.parent.parent.parent  # Path to Folder myapp
pathtoduplicate = os.path.join(script_dir ,'myapp.cpython-37.pyc')
#print(pathtoduplicate)

if os.path.exists(pathtoduplicate):
  os.remove(pathtoduplicate)
else:
  print("The file does not exist")

##print(pathtofile) 

source_dir = os.path.join(script_dir, ' alert ' , 'temp' , 'temp folder' , 'temp' , '__pycache__') #Path to Pycache 
dst = os.path.join(script_dir) # Path to myapp
files = glob.iglob(os.path.join(source_dir, "*.pyc"))
for file in files:
    if os.path.isfile(file):
        shutil.move(file, dst)


            
raise SystemExit()

i got the result i want that the input show as asterisk, but it didnt change the output and only show " " rather than actual password.

Wanted Result:
Masked input password has replaced default password.

email = "[email protected]"  
password = "mynewpassword12345"          
user = "mynewnewid1"
seefirst1 = "newid1" 
seefirst2 = "newid2"  
seefirst3 = "newid3"  
seefirst4 = "newid4" 
seefirst5 = "newid5" 
seefirst6 = "newid6"  
seefirst7 = "newid7"  
seefirst8 = "newid8" 
seefirst9 = "newid9"  
seefirst10 = "newid10"  

Unwanted result:
Masked input password didnt replace default password.

email = "[email protected]"  
password = ""          
user = "mynewnewid1"
seefirst1 = "newid1" 
seefirst2 = "newid2"  
seefirst3 = "newid3"  
seefirst4 = "newid4" 
seefirst5 = "newid5" 
seefirst6 = "newid6"  
seefirst7 = "newid7"  
seefirst8 = "newid8" 
seefirst9 = "newid9"  
seefirst10 = "newid10"

Please help me solve this. I’m noob and really new to python.

Asked By: Mr Noob

||

Answers:

Leaving other problems of your approach aside, I’ll focus on your “Unwanted result: Masked input password didnt replace default password.”

  1. You have a global list1, and you define a list1 in the getPASS() function as well, which you want to use after returning from the function. This doesn’t work as is, since the list1 in the function is local to it and distinct from the global list1. I recommend to return a proper value from the function, e. g.:

    def getPASS():
        print("Input password")
        list1 = []
        while True:
            …
        return "".join(list1)
    
    …
    psw = getPASS()
    
  2. The logic of password input and verification got mixed up here:

    psw = "".join(list1)
    print(psw)
    invalid = ' ,:;/?"}]{[-=+!@#$%^&*()|'
    for x in psw:
        if x in invalid:
            print("Character %r is not allowed in password" % x)
            getPASS()
        else:
            pass
    
    getPASS()
    

    You’re trying to assign and verify the password before you even call getPASS() to input it, therefore psw is empty. Rearrange that, e. g. (assuming above 1. change to getPASS()):

    while True:
        psw = getPASS()
        print(psw)  # only for debugging
        invalid = ' ,:;/?"}]{[-=+!@#$%^&*()|'
        for x in psw:
            if x in invalid:
                print("Character %r is not allowed in password" % x)
                break   # from for x in psw
        else:
            break   # from while True
    
Answered By: Armali

Thanks and many thanks to Sir Armali, wont get this to be solved without his guidance.

Below is the result of my edited script as suggested by Sir Armali on his accepted answer.( and i’m not gonna accept my answer as accepted, only as a reference for anyone interested in this part.)

import fileinput
import os
import textwrap
import msvcrt
import sys


text2 = 'Input password :'

def getPASS():
    for line in textwrap.wrap(text2, width=50):
        print(line.ljust(80))
    list1 = []
    while True:
        char = msvcrt.getch()
        char =str(char)
        char = char[2:-1]

        if char == "\n'" or char == "\r":
            break
        elif char == "\x08":
            del list1[-1]
            os.system("cls")
            print("Input password:")
            sys.stdout.write("*" * len(list1))
            sys.stdout.flush()
            continue
        else:
            list1.append(char)
            sys.stdout.write("*")
            sys.stdout.flush()
    return "".join(list1)

psw = getPASS()


while True:

    invalid = ' ,:;/?"}]{[-=+!@#$%^&*()|'
    for x in psw:
        if x in invalid:
            print("Character %r is not allowed in password" % x)
            break   # from for x in psw
    else:
        break   # from while True


newpassword = psw       


script_dir = os.path.dirname(__file__)
file_path = os.path.join(script_dir, 'alert' , 'temp' , 'temp folder' , 'temp' , 'myapp.py')
print(file_path)
NameFile = file_path


with fileinput.FileInput(NameFile, inplace=True, backup='.bak') as file:
        for line in file:
            print(line.replace(password, newpassword), end='')
Answered By: Mr Noob
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.