Reputation: 53
as a school work, I am trying to make a password encryption/decryption program. I need consider the following rules:
If the password violates those conditions, I will terminate the program with:
print('Invalid password!')
sys.exit()
I've been stuck for hours trying to add these conditions... I don't get where to add these conditions, wherever I add them, my program just terminates even though I've input a valid password T-T
Here is what I have so far (I've removed the part for decryption so that I can try to figure out that part for myself afterwards):
# import sys module for termination
import sys
# init
password_out = ''
case_changer = ord('a') - ord('A')
encryption_key = (('a','m'), ('b','h'), ('c','t'), ('d','f'), ('e','g'),
('f','k'), ('g','b'), ('h','p'), ('i','j'), ('j','w'), ('k','e'),('l','r'),
('m','q'), ('n','s'), ('o','l'), ('p','n'), ('q','i'), ('r','u'), ('s','o'),
('t','x'), ('u','z'), ('v','y'), ('w','v'), ('x','d'), ('y','c'), ('z','a'),
('#', '!'), ('@', '('), ('%', ')'), ('0'), ('1'), ('2'), ('3'), ('4'), ('5'),
('6'), ('7'), ('8'), ('9'))
encrypting = True
# get password
password_in = input('Enter password: ')
# perform encryption / decryption
if encrypting:
from_index = 0
to_index = 1
else:
from_index = 1
to_index = 0
case_changer = ord('a') - ord('A')
for ch in password_in:
letter_found = False
for t in encryption_key:
if ('a' <= ch and ch <= 'z') and ch == t[from_index]:
password_out = password_out + t[to_index]
letter_found = True
elif ('A' <= ch and ch <= 'Z') and chr(ord(ch) + 32) == t[from_index]:
password_out = password_out + chr(ord(t[to_index]) - case_changer)
letter_found = True
elif (ch == '#' or ch == '@' or ch == '%') and ch == t[from_index]:
password_out = password_out + t[to_index]
elif (ch >= '0' and ch <= '9') and ch == t[from_index]:
password_out = password_out + ch
# output
if encrypting:
print('Your encrypted password is:', password_out)
else:
print('Your decrypted password is:', password_out)
Upvotes: 5
Views: 6944
Reputation: 10990
No regular expressions required
import string
import sys
NON_ALPHABETIC_CHARACTERS = {'#', '@', '%'}
DIGITS_CHARACTERS = set(string.digits)
LETTERS_CHARACTERS = set(string.ascii_letters)
def validate_password_1(password,
non_alphabetic_characters=NON_ALPHABETIC_CHARACTERS,
digits_characters=DIGITS_CHARACTERS,
letters_characters=LETTERS_CHARACTERS):
if not any(character in password
for character in non_alphabetic_characters):
err_msg = ('Password should contain at least '
'one non-alphabetic character.')
print(err_msg)
print('Invalid password!')
sys.exit()
if not any(character in password
for character in digits_characters):
err_msg = ('Password should contain at least '
'one digit character.')
print(err_msg)
print('Invalid password!')
sys.exit()
if not any(character in password
for character in letters_characters):
err_msg = ('Password should contain at least '
'one letter character.')
print(err_msg)
print('Invalid password!')
sys.exit()
ALLOWED_CHARACTERS = (NON_ALPHABETIC_CHARACTERS
| DIGITS_CHARACTERS
| LETTERS_CHARACTERS)
def validate_password_2(password,
allowed_characters=ALLOWED_CHARACTERS):
if not all(character in allowed_characters
for character in password):
print('Invalid password!')
sys.exit()
Added additional messages to see what exactly is wrong with given password
Upvotes: 2
Reputation: 4523
I will do something like that using regexp:
import re
def test(x):
regexp = r'[@#%]+[0-9]+@*[a-zA-Z]+'
sorted_x = ''.join(sorted(x))
if '@' in sorted_x:
sorted_x = '@%s' % sorted_x
p = re.compile(regexp)
return p.match(sorted_x) is not None
Then the function gives :
In [34]: test("dfj")
Out[34]: False
In [35]: test("dfj23")
Out[35]: False
In [36]: test("dfj23#")
Out[36]: True
If you need one upper AND one lower case letter you can change the regexp to:
regexp = r'[@#%]+[0-9]+@*[A-Z]+[a-z]+'
The sorted function will put the #
and the %
first, then the numbers, then the @
and finally the letters (first the uper case and then the lower case). Because the @
is put in the middle, I put one first if I find one in the string.
So at the end you want a string with at least a special character : [@#%]+
, at least a number [0-9]+
, optionally there can be a @
in the middle, and finally a letter [a-zA-Z]+
(or if you want upper and lower [A-Z]+[a-z]+
).
Upvotes: 0
Reputation: 24282
This certainly won't qualify as answer for your homework, but you can test that kind of conditions easily with sets
:
import string
alpha = set(string.ascii_lowercase + string.ascii_uppercase)
digits = set(string.digits)
non_alpha = set('#@%')
def is_valid(password):
password_chars = set(password)
# We substract the set of letters (resp. digits, non_alpha)
# from the set of chars used in password
# If any of the letters is used in password, this should be
# smaller than the original set
all_classes_used = all([len(password_chars - char_class) != len(password_chars)
for char_class in [alpha, digits, non_alpha] ])
# We remove all letters, digits and non_alpha from the
# set of chars composing the password, nothing should be left.
all_chars_valid = len(password_chars - alpha - digits - non_alpha) == 0
return all_classes_used and all_chars_valid
for pw in ['a', 'a2', 'a2%', 'a2%!']:
print(pw, is_valid(pw))
# a False
# a2 False
# a2% True
# a2%! False
Upvotes: 1
Reputation: 29710
One possible way to check for both cases would be to do the following:
if password == password.lower() or password == password.upper():
# Reject password here.
We're not going to write the rest of the encryption for you, though!
Upvotes: 0