-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrandom_password_generator.py
181 lines (143 loc) · 6.7 KB
/
random_password_generator.py
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
180
import random
import string
import hashlib
class PasswordGenerator:
"""Generates random passwords using a salt generated by SHA512 and
provides hash value from a given string.
Variables:
__SALT: A string generated by SHA512 used with hash value of passwords.
MIN_UPPER: minimum uppercase characters allowed in the password.
MIN_LOWER: minimum lowercase characters allowed in the password.
MIN_DIGITS: minimum digits (0-9) allowed in the password.
MIN_PUNC: minimum punctuations allowed in the password.
MAX: maximum allowed for each type of characters.
MIN_LENGTH: minimum length of the expected random password
ENCODING: uses utf-16 to encode passwords.
UPPERCASE: all uppercase characters to choose from.
LOWERCASE: all lowercase characters to choose from.
DIGITS: all digits (0-9) characters to choose from.
PUNC: all punctuations characters to choose from.
"""
__SALT = "$6$LAmFHjPBAl0Sp2hG" # generated using SHA512 algo
MAX = 8 # max for each cases below
MIN_UPPER = 4
MIN_LOWER = 4
MIN_DIGITS = 4
MIN_PUNC = 4
MAX_LENGTH = 32
MIN_LENGTH = MIN_UPPER + MIN_LOWER + MIN_DIGITS + MIN_PUNC
ENCODING = 'utf-16'
UPPERCASE = set(string.ascii_uppercase)
LOWERCASE = set(string.ascii_lowercase)
DIGITS = set(string.digits)
PUNC = set(string.punctuation)
def __init__(self, tag, upper=MIN_UPPER, lower=MIN_LOWER,
digits=MIN_DIGITS, punc=MIN_PUNC):
"""Initializes the given parameters after validating them.
Parameters and Instance variables:
__hashed_password: a hash value of the generated password.
tag: a name identify what the random password is for.
upper: # of wanted uppercase characters, default to MIN_UPPER.
lower: # of wanted lowercase characters, default to MIN_LOWER.
digits: # of wanted digits, default to MIN_DIGITS.
punc: # of wanted punctuations, default to MIN_PUNC.
Returns:
self
"""
self.__hashed_password = None
self.tag = tag
self.total_upper = self.validate_input(upper, self.MIN_UPPER, self.MAX)
self.total_lower = self.validate_input(lower, self.MIN_LOWER, self.MAX)
self.total_digits =\
self.validate_input(digits, self.MIN_DIGITS, self.MAX)
self.total_punc = self.validate_input(punc, self.MIN_PUNC, self.MAX)
def get_hashed_password(self, silent=False):
"""Returns the hash value of the currently generated password. If it is
called before the password is generated then it will raise a ValueError
exception which can be ignored by passing True to this. This method
should be called after generate_password(.) is called.
Parameters:
silent: A boolean flag to stop raising exception when no hashed
password exists.
Returns:
string, None or a ValueError exception.
"""
if self.__hashed_password is None and silent is False:
raise ValueError("A hashed password does not exists because a "
"password hasn't been generated yet!")
return None if self.__hashed_password is None and silent is True\
else self.__hashed_password
def generate_password(self, randomized_order=False):
"""Method which generates the random password utilizing a helper
method.
Parameters:
randomized_order: indicates if password should be shuffled or not.
Returns:
tuple: tag name, password, hashed value.
"""
return self.__generate_password(randomized_order)
def __generate_password(self, randomized_order=False):
"""A private method which generates the random password and returns
the result to the caller.
Parameters:
randomized_order: indicates if password should be shuffled or not.
Returns:
tuple: tag name, password, hashed value.
"""
uppercase = "".join(random.sample(self.UPPERCASE, self.total_upper))
lowercase = "".join(random.sample(self.LOWERCASE, self.total_lower))
digits = "".join(random.sample(self.DIGITS, self.total_digits))
punc = "".join(random.sample(self.PUNC, self.total_punc))
elements = [uppercase, lowercase, digits, punc]
original_password = "".join(elements)
random_ordered_password = list(original_password)
if randomized_order:
while True:
random.shuffle(random_ordered_password)
random_ordered_password = "".join(random_ordered_password)
if original_password != random_ordered_password:
break
if randomized_order:
self.__hashed_password = self.apply_hash(random_ordered_password)
return (self.tag, random_ordered_password,
self.get_hashed_password())
else:
self.__hashed_password = self.apply_hash(original_password)
return (self.tag, original_password,
self.get_hashed_password())
@classmethod
def apply_hash(cls, password):
"""Generates a hash value of the given password parameter. Given
password length must be at least 1 or more characters long otherwise
a ValueError exception is raised.
Parameters:
password: password from which a hash value will be generated.
Returns:
string: hash value of the given password.
"""
if len(password) < 1:
raise ValueError("The length of the given password is invalid.")
return cls.__SALT + hashlib.md5(password.encode(cls.ENCODING))\
.hexdigest()
@classmethod
def validate_input(cls, given, _min, _max):
"""Validates if a parameter is in the range of the other parameters.
Parameters:
given: a number which is tested against _min and _max.
_min: a number which must be smaller or equal to given param.
_max: a number which must be greater than given param.
Returns:
an integer or a ValueError exception.
"""
if given >= _min and given <= _max:
return given
else:
raise ValueError("Expected a number in between {}-{} but given {}."
.format(_min, _max, given))
def __str__(self):
"""String representation of the self object. Uses tag and
__hashed_password attribute for string representation.
Returns:
string: tag and hashed password.
"""
return str(self.tag) + ", " + str(self.__hashed_password)