What do you mean by:
"but I don't know how to add something to the dictionary while the program is running"?
Member #531174
Dani AI
Generated
This thread covers three linked issues: how to persistently add users at runtime, how to let users retry login, and how to store passwords safely. is right that a file is the simplest persistence, but for anything beyond a toy script prefer a small database (sqlite) or a vetted password library. hit the common Python pitfall: do not use pass as a variable name (it is a keyword). is correct to hash+salt, but SHA-1 is outdated; use a slow, salted KDF (PBKDF2/bcrypt/argon2) with many iterations.
Minimal, practical pattern (Python 3): keep a persistent store (sqlite), hash passwords with PBKDF2 and a random salt, verify with a constant-time compare, and wrap login in a retry loop. Example functions (create DB, add user, verify) and a 3-attempt login loop:
import os, sqlite3, hashlib, binascii, hmac, getpass
ITER = 200_000
def open_db(path='users.db'):
conn = sqlite3.connect(path)
conn.execute("CREATE TABLE IF NOT EXISTS users(username TEXT PRIMARY KEY, pw TEXT)")
return conn
def hash_pw(password):
salt = os.urandom(16)
dk = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, ITER)
return binascii.hexlify(salt + dk).decode()
def verify_pw(stored_hex, password):
raw = binascii.unhexlify(stored_hex.encode())
salt, dk = raw[:16], raw[16:]
test = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, ITER)
return hmac.compare_digest(test, dk) Use parameterized SQL to add/check users, and a small loop for retries:
for attempt in range(3):
user = input('user: ')
pwd = getpass.getpass('pass: ')
if check_login(conn, user, pwd):
print('OK'); break
print('Invalid')
else:
print('Too many attempts') Practical tips:
- Use sqlite3 for simple, transactional storage; see the Python docs for sqlite3 (https://docs.python.org/3/library/sqlite3.html).
- Prefer PBKDF2/bcrypt/argon2 (or passlib) over raw SHA1; see hashlib.pbkdf2_hmac docs (https://docs.python.org/3/library/hashlib.html#hashlib.pbkdf2_hmac) or Passlib (https://passlib.readthedocs.io/en/stable/).
- Avoid shelve for untrusted data (it pickles objects). If using a JSON file, write atomically (temp + rename) to avoid corruption.
- Catch missing-user cases (do not index into the DB without checking), handle sqlite3.IntegrityError when inserting duplicate users, and never print passwords or store them in plain text.
This gives a robust, modern foundation compared to the earlier Python-2 examples in the thread.
Recommended Answers
Jump to Post— InsaneVr6 0The best way to do this would be for you to use a text file as your dictionary rather than as a variable within the script. Then you can read/write to the dictionary.
All 4 Replies
InsaneVr6 0 Light Poster
The best way to do this would be for you to use a text file as your dictionary rather than as a variable within the script. Then you can read/write to the dictionary.
Archenemie 2 Junior Poster
How would i loop this script? when i run it it doesnt give you a chance to retry the username and pass...
i should imagine it is in the same section as the
else:
print 'Invalid password or username' also replace "pass" with "password" in the following lines - i had to do this when running python 2.6.4
pass = raw_input('Enter password: ')
if pass in database[name]: mn_kthompson 3 Junior Poster
One thing you might want to consider is writing the code so that the users password isn't stored in clear text. The way to do this is to hash the user's password with a cryptographic algorithm and store that. Then you hash the password that the user provides at logon time and compare them.
import hashlib
database = {'kevin':'70ccd9007338d6d81dd3b6271621b9cf9a97ea00'}
name = raw_input('Enter the username: ')
password = hashlib.sha1(raw_input('Enter the password: ')).hexdigest()
if database[name] == password:
print "Good job." That way if someone were to examine the code he or she would not be able to learn what my password is.
mn_kthompson 3 Junior Poster
Another thing you can do to add to the security of the application is to add a "seed" value to the stored passwords. You store the seed value along with the password. Then when the user provides a password for authentication, your application appends the salt to the password and then hash that.
The reason for the salt is that it makes it more difficult to use previously calculated hashes to reverse the stored passwords. For example, you might run through hundreds of words and calculate the sha1 hash of the word and then compare it to the stored hashes to learn that my password above was 'Password1'. Once you knew that you would also know if any other users are using that password because they will have the same hash. But if I apply a random salt value, it will force you to calculate hashes for every possible password combination for each individual user that you want to hack.
import hashlib
# All these users have the same password, but the hashes are different.
# when creating the users, use random.randint to create the salt value.
# The password is Password1
database = {'kevin':('421','7e322290cf8348bb1dd197dc1f2944592ccf6eb2'), \
'james':('619','54aa94ece4706348d2224c847c64871888ed3619'), \
'rick':('1','231b40173139841d096d95e5ac42eaaa9f43920a')}
# Without the salt, all users would have the same hashed password. If you
# learned that one of them was using Password1 for a password, then you would
# have learned all of their passwords.
username = raw_input('Enter your user name: ')
password = raw_input('Enter your password: ')
password += database[username][0]
password = hashlib.sha1(password).hexdigest()
if database[username][1] == password:
print "Good Job" Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.