cpass-cli 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cpass/__init__.py +0 -0
- cpass/main.py +406 -0
- cpass_cli-1.0.0.dist-info/METADATA +640 -0
- cpass_cli-1.0.0.dist-info/RECORD +8 -0
- cpass_cli-1.0.0.dist-info/WHEEL +5 -0
- cpass_cli-1.0.0.dist-info/entry_points.txt +2 -0
- cpass_cli-1.0.0.dist-info/licenses/LICENSE +674 -0
- cpass_cli-1.0.0.dist-info/top_level.txt +1 -0
cpass/__init__.py
ADDED
|
File without changes
|
cpass/main.py
ADDED
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import re
|
|
3
|
+
import os
|
|
4
|
+
import random
|
|
5
|
+
import string
|
|
6
|
+
from MorseCodePy import encode, decode
|
|
7
|
+
from prettytable import PrettyTable
|
|
8
|
+
|
|
9
|
+
def ischaotic(text: str) -> bool:
|
|
10
|
+
"""Determine if a string is chaotic case.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
text (str): Your string.
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
bool: Return True if the string is chaotic case. False if not.
|
|
17
|
+
"""
|
|
18
|
+
return not (text.islower() or text.isupper() or text.istitle())
|
|
19
|
+
|
|
20
|
+
def isspecial(text: str) -> bool:
|
|
21
|
+
"""Determine if the text contains specials character only.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
text (str): The text.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
bool: Return True if the text contains only specials character. False if not.
|
|
28
|
+
"""
|
|
29
|
+
specials = string.punctuation + string.whitespace
|
|
30
|
+
return all(c in specials for c in text)
|
|
31
|
+
|
|
32
|
+
def is_not_supported(text: str) -> str:
|
|
33
|
+
"""Determine if a special character is supported for encoding or not.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
text (str): The text.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
str: Returns all unsupported specials characters.
|
|
40
|
+
"""
|
|
41
|
+
specials_not_supported: list[str] = ["#", "[", "]", "{", "}", "<", ">", "|", "*", "µ", "£", "^", "~", "°", "`", "§", "%"]
|
|
42
|
+
return ', '.join([f'"{char}"' for char in text if char in specials_not_supported])
|
|
43
|
+
|
|
44
|
+
def transform_string(text: str, fingerprint: str) -> str:
|
|
45
|
+
"""Transform letters in uppercase or lowercase according to the fingerprint.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
text (str): Original string.
|
|
49
|
+
fingerprint (str): Fingerprint of the original string.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
str: Return the tranformed string.
|
|
53
|
+
"""
|
|
54
|
+
transformed_string: list[str] = []
|
|
55
|
+
for index, letter in enumerate(text):
|
|
56
|
+
if fingerprint[index] == '1':
|
|
57
|
+
transformed_string.append(letter.lower())
|
|
58
|
+
elif fingerprint[index] == '2':
|
|
59
|
+
transformed_string.append(letter.upper())
|
|
60
|
+
else:
|
|
61
|
+
transformed_string.append(letter)
|
|
62
|
+
return ''.join(transformed_string)
|
|
63
|
+
|
|
64
|
+
def fingerprint(text: str) -> str:
|
|
65
|
+
"""Create a fingerprint to determine which letter is uppercase ou lowercase.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
text (str): Your text.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
str: Returns the fingerprint of the text.
|
|
72
|
+
"""
|
|
73
|
+
counter: list[str] = []
|
|
74
|
+
for char in text:
|
|
75
|
+
if char.islower():
|
|
76
|
+
counter.append('1')
|
|
77
|
+
elif char.isupper():
|
|
78
|
+
counter.append('2')
|
|
79
|
+
else:
|
|
80
|
+
counter.append(str(random.randint(3, 9)))
|
|
81
|
+
return ''.join(counter)
|
|
82
|
+
|
|
83
|
+
def detect_file_or_text(input: str) -> str:
|
|
84
|
+
"""Detect if the input is a text or a file path.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
input (str): The input
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
str: Return the content of the input/file.
|
|
91
|
+
"""
|
|
92
|
+
if os.path.isfile(input):
|
|
93
|
+
with open(input) as f:
|
|
94
|
+
return f.read()
|
|
95
|
+
return input
|
|
96
|
+
|
|
97
|
+
def format_words(text: str) -> list[str]:
|
|
98
|
+
"""Format textual words to a list.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
text (str): Your textual words.
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
list[str]: Return a list of formatted words.
|
|
105
|
+
"""
|
|
106
|
+
words: list[str] = text.splitlines()
|
|
107
|
+
return [re.sub(r"^\d+\.", "", word).strip() for word in words]
|
|
108
|
+
|
|
109
|
+
def show_encoded_secret_words(text: str, language: str, dot: str, dash: str, hidden: bool) -> None:
|
|
110
|
+
"""Show your original and encoded words in a table.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
text (str): Your textual words.
|
|
114
|
+
language (str): Language of your words.
|
|
115
|
+
dot (str): Character representing the dot.
|
|
116
|
+
dash (str): Character representing the dash.
|
|
117
|
+
hidden (bool): Display or not your original words.
|
|
118
|
+
"""
|
|
119
|
+
table = PrettyTable()
|
|
120
|
+
table.align = 'l'
|
|
121
|
+
formatted_words: list[str] = format_words(text)
|
|
122
|
+
table.field_names = ["Original words", "Encoded words"]
|
|
123
|
+
for index, word in enumerate(formatted_words):
|
|
124
|
+
encoded_word: str = encode(word, language=language, dot=dot, dash=dash)
|
|
125
|
+
table.add_row([f"{index+1}. {"******" if hidden else word}", f"{index+1}. {encoded_word}"])
|
|
126
|
+
|
|
127
|
+
print(table)
|
|
128
|
+
|
|
129
|
+
def show_decoded_secret_words(text: str, language: str, dot: str, dash: str, hidden: bool) -> None:
|
|
130
|
+
"""Show your encoded and decoded words in a table.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
text (str): Your encoded words.
|
|
134
|
+
language (str): Language of your (decoded) words.
|
|
135
|
+
dot (str): Character representing the dot.
|
|
136
|
+
dash (str): Character representing the dash.
|
|
137
|
+
hidden (bool): Display or not your decoded words.
|
|
138
|
+
"""
|
|
139
|
+
table = PrettyTable()
|
|
140
|
+
table.align = 'l'
|
|
141
|
+
formatted_words: list[str] = format_words(text)
|
|
142
|
+
table.field_names = ["Encoded words", "Decoded words"]
|
|
143
|
+
for index, word in enumerate(formatted_words):
|
|
144
|
+
decoded_word: str = decode(word, language=language, dot=dot, dash=dash)
|
|
145
|
+
table.add_row([f"{index+1}. {word}", f"{index+1}. {"******" if hidden else decoded_word}"])
|
|
146
|
+
|
|
147
|
+
print(table)
|
|
148
|
+
|
|
149
|
+
def encode_secret_words(text: str, language: str, dot: str, dash: str, output: str) -> None:
|
|
150
|
+
"""Encode your words and store the value in a txt file.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
text (str): Your textual words.
|
|
154
|
+
language (str): Language of your words.
|
|
155
|
+
dot (str): Character representing the dot.
|
|
156
|
+
dash (str): Character representing the dash.
|
|
157
|
+
output (str): Path of the output file.
|
|
158
|
+
"""
|
|
159
|
+
formatted_words: list[str] = format_words(text)
|
|
160
|
+
encoded_words: list[str] = [f"{index+1}. {encode(word, language=language, dot=dot, dash=dash)}" for index, word in enumerate(formatted_words)]
|
|
161
|
+
with open(output, 'w') as f:
|
|
162
|
+
f.write("\n".join(encoded_words))
|
|
163
|
+
print("Your encoded secret words have been successfully saved in:", output)
|
|
164
|
+
|
|
165
|
+
def decode_secret_words(text: str, language: str, dot: str, dash: str, output: str) -> None:
|
|
166
|
+
"""Decode your words and store the value in a txt file.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
text (str): Your encoded words.
|
|
170
|
+
language (str): Language of your (decoded) words.
|
|
171
|
+
dot (str): Character representing the dot.
|
|
172
|
+
dash (str): Character representing the dash.
|
|
173
|
+
output (str): Path of the output file.
|
|
174
|
+
"""
|
|
175
|
+
formatted_words: list[str] = format_words(text)
|
|
176
|
+
decoded_words: list[str] = [f"{index+1}. {decode(word, language=language, dot=dot, dash=dash)}" for index, word in enumerate(formatted_words)]
|
|
177
|
+
with open(output, 'w') as f:
|
|
178
|
+
f.write("\n".join(decoded_words))
|
|
179
|
+
print("Your decoded secret words have been successfully saved in:", output)
|
|
180
|
+
|
|
181
|
+
def main():
|
|
182
|
+
"""Main program"""
|
|
183
|
+
parser = argparse.ArgumentParser(
|
|
184
|
+
prog="cPass",
|
|
185
|
+
description="Encode/Decode your passwords with Morse code."
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
parser.add_argument('-v', '--version',
|
|
189
|
+
action='version',
|
|
190
|
+
version='%(prog)s v1.0.0',
|
|
191
|
+
help="Version of the %(prog)s program.")
|
|
192
|
+
|
|
193
|
+
subparser = parser.add_subparsers(dest='subcommand')
|
|
194
|
+
|
|
195
|
+
### ENCODE subcommand
|
|
196
|
+
encode_subcommand = subparser.add_parser("encode", help="Encode your passphrase/password/file")
|
|
197
|
+
encode_subcommand.add_argument('input', type=str, help="Your passphrase/password/file path to encode")
|
|
198
|
+
encode_subcommand.add_argument('-L', '--language',
|
|
199
|
+
type=str,
|
|
200
|
+
choices=['english', 'french', 'spanish', 'russian', 'ukrainian', 'numbers', 'special'],
|
|
201
|
+
default="english",
|
|
202
|
+
help="Language of your passphrase/password (default: english)")
|
|
203
|
+
encode_subcommand.add_argument('-d', '--dot',
|
|
204
|
+
type=str,
|
|
205
|
+
default='.',
|
|
206
|
+
help="Character representing the dot (default: '.')")
|
|
207
|
+
encode_subcommand.add_argument('-D', '--dash',
|
|
208
|
+
type=str,
|
|
209
|
+
default='-',
|
|
210
|
+
help="Character representing the dash (default: '-')")
|
|
211
|
+
encode_subcommand.add_argument('-s', '--separator',
|
|
212
|
+
type=str,
|
|
213
|
+
default='/',
|
|
214
|
+
help="Character representing the words spacing (default: '/')")
|
|
215
|
+
encode_subcommand.add_argument('-o', '--output',
|
|
216
|
+
type=str,
|
|
217
|
+
help="Path to store the encoded passphrase/password/file")
|
|
218
|
+
encode_subcommand.add_argument('--markup',
|
|
219
|
+
action='store_true',
|
|
220
|
+
help="Show the original character in brackets before its Morse code")
|
|
221
|
+
|
|
222
|
+
### DECODE subcommand
|
|
223
|
+
decode_subcommand = subparser.add_parser("decode", help="Decode your passphrase/password/file")
|
|
224
|
+
decode_subcommand.add_argument('input', type=str, help="Your passphrase/password/file path to decode")
|
|
225
|
+
decode_subcommand.add_argument('-L', '--language',
|
|
226
|
+
type=str,
|
|
227
|
+
choices=['english', 'french', 'spanish', 'russian', 'ukrainian', 'numbers', 'special'],
|
|
228
|
+
default="english",
|
|
229
|
+
help="Language of your passphrase/password (default: english)")
|
|
230
|
+
decode_subcommand.add_argument('-d', '--dot',
|
|
231
|
+
type=str,
|
|
232
|
+
default='.',
|
|
233
|
+
help="Character representing the dot (default: '.')")
|
|
234
|
+
decode_subcommand.add_argument('-D', '--dash',
|
|
235
|
+
type=str,
|
|
236
|
+
default='-',
|
|
237
|
+
help="Character representing the dash (default: '-')")
|
|
238
|
+
decode_subcommand.add_argument('-s', '--separator',
|
|
239
|
+
type=str,
|
|
240
|
+
default='/',
|
|
241
|
+
help="Character representing the words spacing (default: '/')")
|
|
242
|
+
decode_subcommand.add_argument('-o', '--output',
|
|
243
|
+
type=str,
|
|
244
|
+
help="Path to store the decoded passphrase/password/file")
|
|
245
|
+
decode_subcommand.add_argument('--markup',
|
|
246
|
+
action='store_true',
|
|
247
|
+
help="Show the original Morse code sequence in brackets before the decoded character")
|
|
248
|
+
|
|
249
|
+
decode_subcommand_group = decode_subcommand.add_mutually_exclusive_group()
|
|
250
|
+
decode_subcommand_group.add_argument('-u', '--upper-case',
|
|
251
|
+
action='store_true',
|
|
252
|
+
help="Show your passphrase in UPPERCASE")
|
|
253
|
+
decode_subcommand_group.add_argument('-t', '--title-case',
|
|
254
|
+
action='store_true',
|
|
255
|
+
help="Show your passphrase in Title Case")
|
|
256
|
+
decode_subcommand_group.add_argument('-f', '--fingerprint',
|
|
257
|
+
type=str,
|
|
258
|
+
help="Determine which letter is uppercase or lowercase. The length of the fingerprint must match with the length of your (decoded) passphrase")
|
|
259
|
+
|
|
260
|
+
### ENCRYPTO subcommand
|
|
261
|
+
encrypto_subcommand = subparser.add_parser('encrypto', help="Encode your secret words")
|
|
262
|
+
encrypto_subcommand.add_argument('input',
|
|
263
|
+
type=str,
|
|
264
|
+
help="Your file path of your secret words to encode")
|
|
265
|
+
encrypto_subcommand.add_argument('-L', '--language',
|
|
266
|
+
type=str,
|
|
267
|
+
choices=['english', 'french', 'spanish', 'russian', 'ukrainian', 'numbers', 'special'],
|
|
268
|
+
default="english",
|
|
269
|
+
help="Language of your secret words (default: english)")
|
|
270
|
+
encrypto_subcommand.add_argument('-d', '--dot',
|
|
271
|
+
type=str,
|
|
272
|
+
default='.',
|
|
273
|
+
help="Character representing the dot (default: '.')")
|
|
274
|
+
encrypto_subcommand.add_argument('-D', '--dash',
|
|
275
|
+
type=str,
|
|
276
|
+
default='-',
|
|
277
|
+
help="Character representing the dash (default: '-')")
|
|
278
|
+
encrypto_subcommand.add_argument('-o', '--output',
|
|
279
|
+
type=str,
|
|
280
|
+
help="Path to store your encoded secret words")
|
|
281
|
+
encrypto_subcommand.add_argument('--hidden',
|
|
282
|
+
action="store_true",
|
|
283
|
+
help="Hide your original secret words")
|
|
284
|
+
|
|
285
|
+
### DECRYPTO subcommand
|
|
286
|
+
decrypto_subcommand = subparser.add_parser('decrypto', help="Decode your secret words")
|
|
287
|
+
decrypto_subcommand.add_argument('input',
|
|
288
|
+
type=str,
|
|
289
|
+
help="Your file path of your encoded secret words to decode")
|
|
290
|
+
decrypto_subcommand.add_argument('-L', '--language',
|
|
291
|
+
type=str,
|
|
292
|
+
choices=['english', 'french', 'spanish', 'russian', 'ukrainian', 'numbers', 'special'],
|
|
293
|
+
default="english",
|
|
294
|
+
help="Language of your secret words (default: english)")
|
|
295
|
+
decrypto_subcommand.add_argument('-d', '--dot',
|
|
296
|
+
type=str,
|
|
297
|
+
default='.',
|
|
298
|
+
help="Character representing the dot (default: '.')")
|
|
299
|
+
decrypto_subcommand.add_argument('-D', '--dash',
|
|
300
|
+
type=str,
|
|
301
|
+
default='-',
|
|
302
|
+
help="Character representing the dash (default: '-')")
|
|
303
|
+
decrypto_subcommand.add_argument('-o', '--output',
|
|
304
|
+
type=str,
|
|
305
|
+
help="Path to store your decoded secret words")
|
|
306
|
+
decrypto_subcommand.add_argument('--hidden',
|
|
307
|
+
action="store_true",
|
|
308
|
+
help="Hide your decoded secret words")
|
|
309
|
+
|
|
310
|
+
args = parser.parse_args()
|
|
311
|
+
|
|
312
|
+
if args.subcommand:
|
|
313
|
+
if args.input:
|
|
314
|
+
pp = detect_file_or_text(args.input)
|
|
315
|
+
else:
|
|
316
|
+
print("Error: The input argument cannot be empty.")
|
|
317
|
+
exit()
|
|
318
|
+
|
|
319
|
+
if args.subcommand == 'encode':
|
|
320
|
+
if is_not_supported(pp):
|
|
321
|
+
print(f"These specials characters aren't supported: {is_not_supported(pp)}")
|
|
322
|
+
exit()
|
|
323
|
+
|
|
324
|
+
pp = " ".join(pp.splitlines())
|
|
325
|
+
|
|
326
|
+
encoded_string: str = encode(pp,
|
|
327
|
+
language=args.language,
|
|
328
|
+
dash=args.dash,
|
|
329
|
+
dot=args.dot,
|
|
330
|
+
separator=args.separator,
|
|
331
|
+
markup=args.markup)
|
|
332
|
+
if args.output:
|
|
333
|
+
with open(args.output, 'w') as f:
|
|
334
|
+
f.write(encoded_string)
|
|
335
|
+
print(f"Your encoded password is stored in \"{args.output}\".")
|
|
336
|
+
if ischaotic(pp) and not (pp.isdigit() or isspecial(pp)):
|
|
337
|
+
print(f"Fingerprint: {fingerprint(pp)}")
|
|
338
|
+
else:
|
|
339
|
+
print(encoded_string)
|
|
340
|
+
if ischaotic(pp) and not (pp.isdigit() or isspecial(pp)):
|
|
341
|
+
print(f"Fingerprint: {fingerprint(pp)}")
|
|
342
|
+
elif args.subcommand == 'decode':
|
|
343
|
+
pp = " ".join(pp.splitlines())
|
|
344
|
+
decoded_string: str = decode(pp,
|
|
345
|
+
language=args.language,
|
|
346
|
+
dot=args.dot,
|
|
347
|
+
dash=args.dash,
|
|
348
|
+
separator=args.separator,
|
|
349
|
+
markup=args.markup)
|
|
350
|
+
if args.output:
|
|
351
|
+
with open(args.output, 'w') as f:
|
|
352
|
+
if args.upper_case:
|
|
353
|
+
f.write(decoded_string.upper())
|
|
354
|
+
elif args.title_case:
|
|
355
|
+
f.write(decoded_string.title())
|
|
356
|
+
elif args.fingerprint:
|
|
357
|
+
if len(decoded_string) == len(args.fingerprint):
|
|
358
|
+
f.write(transform_string(decoded_string, args.fingerprint))
|
|
359
|
+
else:
|
|
360
|
+
print(f"Error with fingerprint: {args.fingerprint}")
|
|
361
|
+
exit()
|
|
362
|
+
else:
|
|
363
|
+
f.write(decoded_string)
|
|
364
|
+
print(f"Your decoded password is stored in \"{args.output}\".")
|
|
365
|
+
else:
|
|
366
|
+
if args.upper_case:
|
|
367
|
+
print(decoded_string.upper())
|
|
368
|
+
elif args.title_case:
|
|
369
|
+
print(decoded_string.title())
|
|
370
|
+
elif args.fingerprint:
|
|
371
|
+
if len(decoded_string) == len(args.fingerprint):
|
|
372
|
+
print(transform_string(decoded_string, args.fingerprint))
|
|
373
|
+
else:
|
|
374
|
+
print(f"Error with fingerprint: {args.fingerprint}")
|
|
375
|
+
else:
|
|
376
|
+
print(decoded_string)
|
|
377
|
+
elif args.subcommand == 'encrypto':
|
|
378
|
+
if args.output:
|
|
379
|
+
encode_secret_words(pp,
|
|
380
|
+
language=args.language,
|
|
381
|
+
dot=args.dot,
|
|
382
|
+
dash=args.dash,
|
|
383
|
+
output=args.output)
|
|
384
|
+
else:
|
|
385
|
+
show_encoded_secret_words(pp,
|
|
386
|
+
language=args.language,
|
|
387
|
+
dot=args.dot,
|
|
388
|
+
dash=args.dash,
|
|
389
|
+
hidden=args.hidden)
|
|
390
|
+
elif args.subcommand == 'decrypto':
|
|
391
|
+
if args.output:
|
|
392
|
+
decode_secret_words(pp,
|
|
393
|
+
language=args.language,
|
|
394
|
+
dot=args.dot,
|
|
395
|
+
dash=args.dash,
|
|
396
|
+
output=args.output)
|
|
397
|
+
else:
|
|
398
|
+
show_decoded_secret_words(pp,
|
|
399
|
+
language=args.language,
|
|
400
|
+
dot=args.dot,
|
|
401
|
+
dash=args.dash,
|
|
402
|
+
hidden=args.hidden)
|
|
403
|
+
|
|
404
|
+
if __name__ == "__main__":
|
|
405
|
+
main()
|
|
406
|
+
|