-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPasswordSystem.py
More file actions
179 lines (163 loc) · 6.34 KB
/
PasswordSystem.py
File metadata and controls
179 lines (163 loc) · 6.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import re
import HashSystem
SEPARATION = ";"
REGEX_PATTERN = re.compile(SEPARATION)
SPECIAL_CHARS = ['!', '@', '#', '$', '%', '?', '*']
PASSWORD_FILE = "passwd.txt"
WEAK_PASSWORD_FILE = "weakPasswd.txt"
def checkUsernameAvailability(username):
"""
Check if a username is available for use.
@param username: username to check.
@return true if available, false otherwise.
"""
try:
with open(PASSWORD_FILE, 'r') as file:
for line in file:
if(username.lower() == REGEX_PATTERN.split(line.strip())[0].lower()):
return False
except FileNotFoundError:
print("ERROR: Password file not found!")
return False
return True
def loadUserInfo(firstName, lastName, username, role, inputPassword):
"""
Load user info into the password file.
@param firstName: the first name of the user.
@param lastName: last name of the user.
@param username: the user's username.
@param role: the user's role.
@param inputPassword: the user's password.
@return true if user's info successfully loaded, false otherwise.
"""
newSalt = HashSystem.generateSalt()
hashedPassword = HashSystem.hashPassword(inputPassword, newSalt)
try:
with open(PASSWORD_FILE, 'a') as file:
file.write(username + SEPARATION + firstName + SEPARATION + lastName + SEPARATION + role + SEPARATION + newSalt.hex() + SEPARATION + hashedPassword.hex() + "\n")
print("Successfully loaded password.")
except IOError as e:
print("ERROR: Failed to load to password file.", str(e))
return False
return True
def verifyPassword(username, inputPassword):
"""
Verify that the username and password match.
@param username: the username to check.
@param inputPassword: the password to check.
@return true if correct match, false otherwise.
"""
userInfo = getUserSaltAndHashedPassword(username)
if(userInfo == None):
print("ERROR: User not found.")
return False
return HashSystem.verifyPassword(inputPassword, bytes.fromhex(userInfo[0]), bytes.fromhex(userInfo[1]))
def isValidNewPassword(username, password):
"""
Check the validity of a new password.
It checks if it follows these policies:
- must be 8-12 characters long.
- must have at least one uppercase letter.
- must have at least one lowercase letter.
- must have at least one numerical digit.
- must have at least one special character from the set: {!, @, #, $, %, ?, *}.
- must not contain the separation character.
- must not be a weak password.
- must not match the format of calendar dates, license plate numbers, telephone numbers, or other common number.
- must not contain username.
@param username: the user creating the password.
@param password: the password to check.
@return true if valid, false otherwise.
"""
hasUpperCase = False
hasLowerCase = False
hasNumber = False
hasSpecialChar = False
if not (8 <= len(password) <= 12):
return False
if(username in password):
return False
# check if the password contains all the required characters
for char in password:
if char.isupper():
hasUpperCase = True
elif char.islower():
hasLowerCase = True
elif char.isdigit():
hasNumber = True
elif char in SPECIAL_CHARS:
hasSpecialChar = True
elif char == SEPARATION:
return False
if(hasUpperCase and hasLowerCase and hasNumber and hasSpecialChar):
return not (isWeakPassword(password) or matchesDateFormat(password) or matchesLicenseFormat(password) or matchesPhoneNumberFormat(password))
return False
def isWeakPassword(password):
"""
Checks if a password is found in the list of weak passwords.
@param password: password to check.
@return true if found in list, false otherwise.
"""
try:
with open(WEAK_PASSWORD_FILE, "r") as file:
for line in file:
if password in line:
return True
except FileNotFoundError:
print("ERROR: Weak password file not found.")
return False
def matchesDateFormat(password):
"""
Check if the password matches a date format.
@param password: the password to check.
@return true if matches, false otherwise.
"""
# Define the regex pattern for calendar dates (assuming MM/DD/YYYY format)
regex = r'\b(0?[1-9]|1[0-2])/(0?[1-9]|[12][0-9]|3[01])/(\d{4})\b'
return re.search(regex, password) is not None
def matchesLicenseFormat(password):
"""
Check if the password matches a license plate number format.
@param password: the password to check.
@return true if matches, false otherwise.
"""
# Define the regex pattern for license plates (two letters, two numbers, two letters)
regex = r'\b[A-Z]{2}\d{2}[A-Z]{2}\b'
return re.search(regex, password) is not None
def matchesPhoneNumberFormat(password):
"""
Check if the password matches a phone number format.
@param password: the password to check.
@return true if matches, false otherwise.
"""
# Define the regex pattern for phone numbers (XXX-XXX-XXXX format)
regex = r'\b\d{3}-\d{3}-\d{4}\b'
return re.search(regex, password) is not None
def getUserSaltAndHashedPassword(username):
"""
Get the stored salt and hashed password for a user.
@param username: the user to get their info.
@return array of the salt and hashed password, None if user not found.
"""
try:
with open(PASSWORD_FILE, 'r') as file:
for line in file:
if(username == REGEX_PATTERN.split(line.strip())[0]):
return [REGEX_PATTERN.split(line.strip())[4], REGEX_PATTERN.split(line.strip())[5]]
except FileNotFoundError:
print("ERROR: Password file not found!")
return None
def getUserRole(username):
"""
Get the role of a user.
@param username: the user to get their role
@return the role of the user, null if user not found.
"""
try:
with open(PASSWORD_FILE, 'r') as file:
for line in file:
if(username == REGEX_PATTERN.split(line.strip())[0]):
return REGEX_PATTERN.split(line.strip())[3]
except FileNotFoundError:
print("ERROR: Password file not found!")
return None