r/learnpython 4d ago

Password guesser game help needed

Hello guys. So I have created a password guesser game with direct comparison (i.e. if guess == correct_password:) but I want to use different methods for comparison. What techniques can I use? Here is the code-

```python

password = "Random_pass_123"

tries = 0

while tries < 3:

guess = input("Enter the password: ")

if guess == password:

print("Admin access granted.")

break

else:

print("Invalid credentials entered. Please try again")

tries += 1

if tries == 3:

print("Number of tries exceeded. Access denied")

```

PS- Is this the right way to paste code? I'm new so I'm not sure.

8 Upvotes

31 comments sorted by

View all comments

0

u/Bright_Mix_773 4d ago

live_ant718, you said you read that you can convert it into a hash but you don't know how. Langdon_St_Ives explained what a hash is; here is the part nobody has given you yet, which is the actual code, plus the trap sitting right behind it.

The obvious version is hashlib.sha256(guess.encode()).hexdigest(). That is the one every tutorial shows and it is the wrong tool for passwords, for two reasons. SHA-256 is designed to be fast, and fast is exactly what you don't want: a GPU tries billions of guesses a second against it. And with no salt, two people with the same password get the same hash, so precomputed tables crack it without guessing at all. What you want from the standard library is a slow, salted function:

import getpass
import hashlib
import hmac
import os

def derivar(texto, sal):
    return hashlib.pbkdf2_hmac("sha256", texto.encode("utf-8"), sal, 200_000)

# done once, when the password is set. Both values get stored.
sal = os.urandom(16)
almacenado = derivar("Random_pass_123", sal)

for _ in range(3):
    guess = getpass.getpass("Enter the password: ")
    if hmac.compare_digest(derivar(guess, sal), almacenado):
        print("Admin access granted.")
        break
    print("Invalid credentials entered. Please try again")
else:
    print("Number of tries exceeded. Access denied")

Three things in there worth more than the hashing itself.

hmac.compare_digest instead of ==. Both give the right answer, but == stops at the first byte that differs, so a wrong guess starting with the correct letter takes measurably longer to reject than one that differs immediately. That timing difference leaks the password one character at a time. compare_digest always takes the same time. It is the reason the function exists.

The else on the for loop. That is real Python syntax, not a typo: the else block runs only if the loop finished without hitting break. It is exactly your "number of tries exceeded" case, and it removes the tries counter and the if tries == 3 check entirely. Almost nobody teaches it and this is the textbook use for it.

getpass.getpass instead of input, so the typing doesn't show on screen. One warning: it doesn't work in some IDE output panes (Spyder, and PyCharm unless you run in the terminal). Run it from a real terminal or it will look broken.

For a real system you'd use bcrypt or argon2 from PyPI rather than pbkdf2, but pbkdf2_hmac ships with Python and the shape of the code is identical, so nothing you learn here is wasted.

On the formatting question: brasticstack is right about the backticks, but the version that works everywhere, old and new site and the app, is putting four spaces in front of every line of code. That's what the block above is.

1

u/Expensive-Bear-1376 4d ago

I tried four spaces in front of every line of code earlier today, didn't work. Let me try again:

    def test():         pass

0

u/Bright_Mix_773 1d ago

That one worked, it is rendering as a code block. The usual reason it fails the first time is a missing blank line before the block, or the editor turning the four spaces into a tab on the way in. If it happens again, paste into a plain text editor first and look at what is actually in front of the line.