3
3
import random
4
4
import secrets
5
5
import string
6
+ from typing import Optional
6
7
7
8
import click
8
9
import requests
18
19
128+ bits\t = Very Strong; often overkill"""
19
20
20
21
_available_charsets = {"l" , "u" , "d" , "p" }
22
+ _max_pass_length = 50
23
+ _min_pass_length = 12
24
+ _max_pass_number = 50
21
25
22
26
23
27
@click .command (context_settings = {'help_option_names' : ['-h' , '--help' ]})
@@ -44,15 +48,15 @@ def rpg(pass_length: int, number: int, output: click.File, exclude_charsets: str
44
48
:return: None
45
49
"""
46
50
# Check pass_length validity
47
- msg .Prints .verbose ("Checking <pass-length> ({}) validity" . format ( pass_length ) , verbose )
48
- if pass_length > 90 or pass_length < 12 :
51
+ msg .Prints .verbose (f "Checking <pass-length> ({ pass_length } ) validity" , verbose )
52
+ if pass_length > _max_pass_length or pass_length < _min_pass_length :
49
53
raise click .BadArgumentUsage (
50
- msg .Echoes .error ("Invalid value for \" <pass-length> \" : {} is not in the valid range of 12 to 90." )
51
- . format ( pass_length ))
54
+ msg .Echoes .error (
55
+ f"Invalid value for \" <pass-length> \" : { pass_length } is not in the valid range of 12 to 90." ))
52
56
53
57
# Check number validity
54
- msg .Prints .verbose ("Checking <pass-number> ({}) validity" . format ( number ) , verbose )
55
- if number > 50 :
58
+ msg .Prints .verbose (f "Checking <pass-number> ({ number } ) validity" , verbose )
59
+ if number > _max_pass_number :
56
60
raise click .BadOptionUsage ("number" , msg .Echoes .error (
57
61
"Invalid value for \" <pass-number>\" : the maximum value accepted is 50." ))
58
62
@@ -66,7 +70,7 @@ def rpg(pass_length: int, number: int, output: click.File, exclude_charsets: str
66
70
raise click .BadOptionUsage ("--exclude-charsets" ,
67
71
msg .Echoes .error ("RPG needs at least one charsets type to generate password." ))
68
72
else :
69
- if not len (chars ) == 4 :
73
+ if not len (chars ) == len ( string . ascii_lowercase + string . ascii_uppercase + string . digits + string . punctuation ) :
70
74
# User chose to not use any charsets, print warning message
71
75
msg .Prints .warning ("You are going to generate passwords without one or more of default charsets!" )
72
76
msg .Prints .warning (
@@ -99,20 +103,20 @@ def rpg(pass_length: int, number: int, output: click.File, exclude_charsets: str
99
103
100
104
for pw in pw_list :
101
105
if output :
102
- output .write ("{ }\n ". format ( pw ) )
106
+ output .write (f" { pw } \n " )
103
107
else :
104
108
msg .Prints .info (pw )
105
109
106
110
# Calculate entropy and print it
107
111
entropy = _get_entropy (pass_length , chars )
108
112
if output :
109
- output .write ("\n Entropy: {}" . format ( entropy ) )
113
+ output .write (f "\n Entropy: { entropy } " )
110
114
else :
111
- msg .Prints .emphasis ("\n The entropy of generated password is: {}" . format ( entropy ) )
115
+ msg .Prints .emphasis (f "\n The entropy of generated password is: { entropy } " )
112
116
113
117
# Print summary table, only if --verbose or --output
114
118
if output :
115
- output .write ("\n {}" . format ( _password_entropy_table ) )
119
+ output .write (f "\n { _password_entropy_table } " )
116
120
else :
117
121
msg .Prints .verbose (_password_entropy_table , verbose )
118
122
@@ -124,7 +128,7 @@ def _get_char_list(charsets_to_exclude: str = None) -> list:
124
128
:param str charsets_to_exclude: charsets to exclude
125
129
:return list: available charsets list
126
130
"""
127
- chars = []
131
+ chars = ""
128
132
129
133
charsets = {}
130
134
if charsets_to_exclude is not None :
@@ -134,21 +138,21 @@ def _get_char_list(charsets_to_exclude: str = None) -> list:
134
138
# If charsets is empty, take all charsets
135
139
if not bool (charsets ):
136
140
if charsets_to_exclude is not None :
137
- return chars
141
+ return list ( chars )
138
142
else :
139
143
charsets = _available_charsets
140
144
141
145
for cset in charsets :
142
146
if cset == "l" :
143
- chars . append ( string .ascii_lowercase )
147
+ chars += string .ascii_lowercase
144
148
elif cset == "u" :
145
- chars . append ( string .ascii_uppercase )
149
+ chars += string .ascii_uppercase
146
150
elif cset == "d" :
147
- chars . append ( string .digits )
151
+ chars += string .digits
148
152
elif cset == "p" :
149
- chars . append ( string .punctuation )
153
+ chars += string .punctuation
150
154
151
- return chars
155
+ return list ( chars )
152
156
153
157
154
158
def _sanitize_excluded_charsets (charsets_to_sanitize : str ) -> set :
@@ -163,7 +167,7 @@ def _sanitize_excluded_charsets(charsets_to_sanitize: str) -> set:
163
167
return set_to_sanitize & _available_charsets
164
168
165
169
166
- def _generate_random_password (length : int , charsets : list , no_safe : bool = False ):
170
+ def _generate_random_password (length : int , charsets : list , no_safe : bool = False ) -> Optional [ str ] :
167
171
"""
168
172
Generate random password.
169
173
@@ -173,27 +177,26 @@ def _generate_random_password(length: int, charsets: list, no_safe: bool = False
173
177
:return: str random password | None
174
178
"""
175
179
pw = []
176
- chars = len (charsets )
177
180
178
181
# Shuffle chars to change every password generation
179
182
random .shuffle (charsets )
180
183
181
184
for i in range (length ):
182
185
# Append random char into generated password
183
- pw .append (secrets .choice (charsets [ i % chars ] ))
186
+ pw .append (secrets .choice (charsets ))
184
187
185
188
random .shuffle (pw )
186
- pw = "" .join (pw )
189
+ pw_str = "" .join (pw )
187
190
188
191
# Check if generated password is in a password leak
189
192
if not no_safe :
190
- leaks = _is_leaked_password (pw )
193
+ leaks = _is_leaked_password (pw_str )
191
194
if leaks == 1 :
192
- _generate_random_password (length , charsets )
195
+ return _generate_random_password (length , charsets )
193
196
elif leaks == 9 :
194
197
return None
195
198
196
- return pw
199
+ return pw_str
197
200
198
201
199
202
def _is_leaked_password (pw : str ) -> int :
0 commit comments