Can this be shortened/improved? I'm trying to make a password checker in Python.
Could the if
s be put into a for
loop? If so, how?
pw = input("Enter password to test: ")
caps = sum(1 for c in pw if c.isupper())
lower = sum(1 for c in pw if c.islower())
nums = sum(1 for c in pw if c.isnumeric())
scr = ['weak', 'medium', 'strong']
r = [caps, lower, nums]
if len(pw) < 6:
print("too short")
elif len(pw) > 12:
print("too long")
if caps >= 1:
if lower >= 1:
if nums >= 1:
print(scr[2])
elif nums < 1:
print("your password is " + scr[1])
elif lower < 1:
print("your password strength is " + scr[0])
elif caps < 1:
print("your password strength is " + scr[1])
-
3\$\begingroup\$ the code works from the looks of Gareth's answer, but I agree that your knowledge of Password strength is lacking. Note: Password Strength \$\endgroup\$Malachi– Malachi2013年10月25日 22:18:01 +00:00Commented Oct 25, 2013 at 22:18
2 Answers 2
Enter password to test: premaintenance disdainful hayloft seer
too long
your password strength is medium
Enter password to test: NXJCWGGDVQZO
your password strength is weak
Enter password to test: Password1
strong
Your knowledge of password strength is: weak.
Explanation
Password strength is normally measured in "bits of entropy" — the idea being that if a password has been picked randomly from a pool of similar passwords of size N, then its entropy is log2N bits.
The first password I tried above was picked using a method suggested by Randall Munroe, like this:
>>> words = list(open('/usr/share/dict/words'))
>>> import random
>>> random.SystemRandom().shuffle(words)
>>> print(' '.join(w.strip() for w in words[:4]))
premaintenance disdainful hayloft seer
Its entropy can be calculated like this:
>>> from math import log
>>> l = len(words)
>>> log(l * (l - 1) * (l - 2) * (l - 3), 2)
71.39088438576361
This is a strong password—a cracker that tried a billion such passwords a second would take on average about 50,000 years to find it.
The second password is also strong, but not as good as the first. I generated it like this:
$ </dev/random base64 | tr -cd A-Z | head -c 12
NXJCWGGDVQZO
Its entropy is 12 ×ばつ log226 = 56.4 bits.
The third password is, of course, the weakest. password1
is about the 600th most common password (according to Mark Burnett, here) and the initial capital letter is a common substitution that password cracking programs know all about.
-
3\$\begingroup\$ that was kind of harsh. but I agree. \$\endgroup\$Malachi– Malachi2013年10月25日 22:16:29 +00:00Commented Oct 25, 2013 at 22:16
-
\$\begingroup\$ Judging from the last one, this code needs emergency improvement. \$\endgroup\$Jamal– Jamal2013年10月25日 22:23:56 +00:00Commented Oct 25, 2013 at 22:23
Gareth's answer is correct and shows the real issues with what you are trying to achieve.
For the sake of learning more, let's review the actual code.
What is good
- Your code is simple and easy to understand.
- You are using
sum
,isupper
,islower
andisnumeric
properly.
What can be improved
- Don't repeat yourself :
You don't need to do something like :
if condition:
foo
elif not condition:
bar
Just write :
if condition:
foo
else:
bar
Also, you don't need to repeat print("your password strength is " + whatever)
.
The corresponding snippet can be written :
if caps >= 1:
if lower >= 1:
if nums >= 1:
strength = scr[2]
else:
strength = scr[1]
else:
strength = scr[0]
else:
strength = scr[1]
print("your password strength is " + scr[1])
- Keep things simple :
Also, because of the way Python evaluates integers as boolean, you can write the conditions : if caps:
, if lower
and if nums
.
The r
list is not used, get rid of it.
In a "normal" password checker, I guess it would be possible to factorise the different possible cases on the different criteria to make your code more concise. Here, I have troubles trying to see a logic behind the different cases you are considering. Why would a lower case password be medium
no matter the other criteria while a pure upper case password would be weak
...