1

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.

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 = "mynewemail@gmail.com"  
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 = "mynewemail@gmail.com"  
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.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
Mr Noob
  • 116
  • 2
  • 10
  • 2
    If the password ends up in a text file in cleartext, security is a lost cause anyway. – TigerhawkT3 Jan 24 '19 at 10:47
  • the password will end up in a text file, but at the end of this above basic script will automatically delete the extracted/modified file. It will also create new pyc file(yes i know this pyc also is not safe at a point it could be decoded but i consider it should be enough to the purpose of letting user assume it is safe(user is a non coding person). – Mr Noob Jan 24 '19 at 11:02
  • "letting the user assume it is safe" when it isn't is highly unethical. – bruno desthuilliers Jan 24 '19 at 11:37
  • sir bruno desthuilliers, thanks for commenting and i accept that as an advice. actually i'm letting a user to have the encoded pyc script to be used by himself on his own computer. and truly as a basic learner i'm now, i still dont get to know how i'm going to make a secure script, still have a lot of things i couldnt solve them by myself, thats why i'm here to learn from you and many more advanced coder. – Mr Noob Jan 24 '19 at 18:05
  • @karl-knechtel . No, this is not duplicate question. Look again, even if same name but this question has more detail in that. please take a look again.. – Mr Noob Aug 03 '22 at 07:57
  • 1
    "And finally the output should be saved to replace another file basic info such as email, user id and password." ... "but it did not let me save the printed password as user output." I can't understand what this means. When you use any of these methods to get a password **input**, you end up saving that input in a variable, and you can do what you want with that. If the question is just about how to write a string into a file, then that is a) a completely separate question and b) also a duplicate. – Karl Knechtel Aug 03 '22 at 19:36
  • 1
    If you want to "save the output" by selecting `*` symbols on the screen and copying them, and then paste the password somewhere else, that is not possible: the selection is handled by something outside of your program, and it can only see the `*` symbols. – Karl Knechtel Aug 03 '22 at 19:39
  • 1
    If the question is about making the long code example at the end work properly, then it is instead a *debugging* question, and should not have been accepted as is in the first place. It lacks the appropriate focus, and is missing important debugging details. Please read https://ericlippert.com/2014/03/05/how-to-debug-small-programs/ and [mre]. – Karl Knechtel Aug 03 '22 at 19:41

2 Answers2

1

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
    
Armali
  • 18,255
  • 14
  • 57
  • 171
  • 1
    thanks for your answer sir. I've read your solutions a couple of hours ago and finally after hours of change here and change there i've succeeded to complete this as you suggested. many thanks Sir. (I've tried to your answer as accepted answer but since i have not reach minimum 15 rep i cant do that for now.) – Mr Noob Jan 24 '19 at 17:50
1

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='')
Mr Noob
  • 116
  • 2
  • 10