-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extracted Helper Functions and added values only flag
- Loading branch information
1 parent
2f40234
commit 3deab74
Showing
1 changed file
with
195 additions
and
181 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,181 +1,195 @@ | ||
""" | ||
This script is a command line utility which takes the folllowing arguments: | ||
-h, --help show this help message and exit | ||
-f, --file Specify a text file whose contents are to be encoded | ||
-m, --msg The text to be encoded | ||
-s, --seed The seed for encoding [default:random] | ||
-z, --size The size_seed for encoding [default:2] | ||
It determines how large to make the encoded string. | ||
The encoded message is "roughly" 'size_seed' times the length of actual message | ||
-c, --char_range The range of unicode characters to be used for encoded the message [default:256] | ||
-o, --output Specify a text file where the output code will be saved | ||
-g, --garbage Seed for garbage values | ||
It encodes a given message (or contents of a given file) and provides a python code to extract the original message | ||
It uses python random module and XOR (^) operator to encode the message | ||
""" | ||
|
||
|
||
from random import Random | ||
from typing import Any | ||
|
||
|
||
def encode( | ||
message: str = "", | ||
seed: Any = 0, | ||
size_seed: int = 2, | ||
char_range: int = 256, | ||
garbage_seed: Any = None, | ||
) -> tuple[str, Any, int, int]: | ||
"""\ | ||
This function encodes the given message | ||
The feild 'seed' is the seed for randomisation. | ||
The feild 'size_seed' determines how large to make the encoded string | ||
The encoded message is "roughly" 'size_seed' times the length of actual message | ||
The feild 'char_range' determines the range of unicode characters to be used for encoded the message | ||
NOTE: The same 'seed', 'size_seed' and 'char_range' has to be used while decoding | ||
P.S. Yes I do take care of that by default | ||
The feild 'garbage_seed' is the seed for garbage values. | ||
If you intend to get the same encoded message again pass same value to this feild. | ||
""" | ||
if seed is None: | ||
seed = 0 | ||
temp = Random(garbage_seed) | ||
determined = Random(seed) | ||
result = "" | ||
i = 0 | ||
n = len(message) | ||
if size_seed < 2: | ||
size_seed = 2 | ||
while i < n: | ||
char = message[i] | ||
if not determined.randrange(size_seed): | ||
i += 1 | ||
result += chr(determined.randrange(char_range) ^ ord(char)) | ||
else: | ||
result += chr(temp.randrange(char_range)) | ||
return result.encode().hex().upper(), seed, size_seed, char_range | ||
|
||
|
||
def decode( | ||
encoded: str = "", | ||
seed: Any = 0, | ||
size_seed: int = 2, | ||
char_range: int = 256, | ||
) -> str: | ||
"""\ | ||
Decodes the encoded message based on the given parameters | ||
""" | ||
determined = Random(seed) | ||
# return "".join((chr(determined.randrange(char_range) ^ ord(char)) for char in bytes.fromhex(encoded).decode() if not determined.randrange(size_seed))) | ||
message = "" | ||
for char in bytes.fromhex(encoded).decode(): | ||
if not determined.randrange(size_seed): | ||
message += chr(determined.randrange(char_range) ^ ord(char)) | ||
return message | ||
|
||
|
||
def give_code( | ||
code: str = "", | ||
seed: Any = 0, | ||
size_seed: int = 2, | ||
char_range: int = 256, | ||
) -> str: | ||
"""\ | ||
This function gives the python code that can be used to decode the message based on given parameters | ||
""" | ||
return f"""\ | ||
import random | ||
random.seed({seed!r}) | ||
m = {code!r} | ||
print(''.join((chr(random.randrange({char_range})^ord(c))for c in bytes.fromhex(m).decode()if not random.randrange({size_seed})))) | ||
""" | ||
|
||
|
||
def get_input(): | ||
import argparse | ||
|
||
parser = argparse.ArgumentParser() | ||
parser.add_argument( | ||
"--file", | ||
"-f", | ||
type=str, | ||
default="", | ||
help="Specify a text file whose contents are to be encoded", | ||
) | ||
parser.add_argument( | ||
"--msg", | ||
"-m", | ||
type=str, | ||
default="", | ||
help="The text to be encoded", | ||
) | ||
parser.add_argument( | ||
"--seed", | ||
"-s", | ||
default=f"{Random().random()}"[3:], | ||
help="The seed for encoding [default:random]", | ||
) | ||
parser.add_argument( | ||
"--size", | ||
"-z", | ||
default=2, | ||
type=int, | ||
help="The size_seed for encoding [default:2]\nIt determines how large to make the encoded string.\n\tThe encoded message is \"roughly\" 'size_seed' times the length of actual message", | ||
) | ||
parser.add_argument( | ||
"--char_range", | ||
"-c", | ||
type=int, | ||
default="256", | ||
help="The range of unicode characters to be used for encoded the message [default:256]", | ||
) | ||
parser.add_argument( | ||
"--output", | ||
"-o", | ||
type=str, | ||
default="", | ||
help="Specify a text file where the output code will be saved", | ||
) | ||
parser.add_argument( | ||
"--garbage", | ||
"-g", | ||
default=None, | ||
help="Seed for garbage values", | ||
) | ||
return parser.parse_args() | ||
|
||
|
||
def main(args): | ||
message = "" | ||
if args.msg: | ||
message = args.msg | ||
else: | ||
if args.file: | ||
try: | ||
with open(args.file) as f: | ||
message = f.read() | ||
except FileNotFoundError: | ||
print("File does not exist") | ||
exit() | ||
else: | ||
print("No Arguments Given") | ||
exit() | ||
|
||
temp = give_code( | ||
*encode( | ||
message=message, | ||
seed=args.seed, | ||
size_seed=args.size_seed, | ||
char_range=args.char_range, | ||
garbage_seed=args.garbage_seed, | ||
) | ||
) | ||
if args.output: | ||
with open(args.output, "w") as f: | ||
f.write(temp) | ||
else: | ||
print("\n\n", temp, sep="\n") | ||
|
||
|
||
if __name__ == "__main__": | ||
main(get_input()) | ||
""" | ||
`python encode.py -h` for help message | ||
It encodes a given message (or contents of a given file) and provides a python code to extract the original message | ||
It uses python random module and XOR (^) operator to encode the message | ||
""" | ||
|
||
from random import Random | ||
from typing import Any | ||
|
||
|
||
def encode( | ||
message: str, | ||
seed: Any = 0, | ||
size_seed: int = 2, | ||
char_range: int = 256, | ||
garbage_seed: Any = None, | ||
) -> str: | ||
"""\ | ||
Encodes the given message | ||
The feild 'seed' is the seed for randomisation. | ||
The feild 'size_seed' determines how large to make the encoded string | ||
The encoded message is "roughly" 'size_seed' times the length of actual message | ||
The feild 'char_range' determines the range of unicode characters to be used for encoded the message | ||
The feild 'garbage_seed' is the seed for garbage values. | ||
If you intend to get the same encoded message again pass same value to this feild. | ||
NOTE: The same 'seed', 'size_seed' and 'char_range' values are required for decoding | ||
""" | ||
temp = Random(garbage_seed) | ||
determined = Random(seed) | ||
result = "" | ||
i = 0 | ||
n = len(message) | ||
while i < n: | ||
char = message[i] | ||
if not determined.randrange(size_seed): | ||
i += 1 | ||
result += chr(determined.randrange(char_range) ^ ord(char)) | ||
else: | ||
result += chr(temp.randrange(char_range)) | ||
return result.encode().hex().upper() | ||
|
||
|
||
def validate( | ||
seed: Any = 0, | ||
size_seed: int = 2, | ||
char_range: int = 256, | ||
) -> tuple[Any, int, int]: | ||
""" | ||
Validate the values passed by the user | ||
If seed is None, then the encryption will not be consistent and the algorithm will fail | ||
""" | ||
if seed is None: seed = 0 | ||
size_seed = max(size_seed, 1) | ||
if char_range < 1: char_range = 256 | ||
return seed, size_seed, char_range | ||
|
||
|
||
def decode( | ||
encoded: str, | ||
seed: Any = 0, | ||
size_seed: int = 2, | ||
char_range: int = 256, | ||
) -> str: | ||
"""\ | ||
Decodes the encoded message based on the given parameters | ||
Please use the same values of 'seed', 'size_seed' and 'char_range' as used while encoding | ||
""" | ||
determined = Random(seed) | ||
# return "".join((chr(determined.randrange(char_range) ^ ord(char)) for char in bytes.fromhex(encoded).decode() if not determined.randrange(size_seed))) | ||
message = "" | ||
for char in bytes.fromhex(encoded).decode(): | ||
if not determined.randrange(size_seed): | ||
message += chr(determined.randrange(char_range) ^ ord(char)) | ||
return message | ||
|
||
|
||
def give_code(encoded_message: str, seed: Any, size_seed: int, char_range: int) -> str: | ||
"""\ | ||
This function gives the python code that can be used to decode the message based on given parameters | ||
""" | ||
return f"""import random; random.seed({seed!r}); m = {encoded_message!r} | ||
print(''.join((chr(random.randrange({char_range})^ord(c))for c in bytes.fromhex(m).decode()if not random.randrange({size_seed})))) | ||
""" | ||
|
||
|
||
def give_values(encoded_message: str, seed: Any, size_seed: int, char_range: int) -> str: | ||
return f"message:\t{encoded_message}\nseed:\t\t{seed}\nsize seed:\t{size_seed}\nchar range:\t{char_range}" | ||
|
||
|
||
def get_input(): | ||
import argparse | ||
|
||
parser = argparse.ArgumentParser() | ||
parser.add_argument( | ||
"arg", | ||
type=str, | ||
default="", | ||
help="The text to be encoded, or the path of the file if -f flag is set", | ||
) | ||
parser.add_argument( | ||
"--file", | ||
"-f", | ||
action="store_true", | ||
default=False, | ||
help="If the argument is a file", | ||
) | ||
parser.add_argument( | ||
"--seed", | ||
"-s", | ||
default=f"{Random().random()}"[3:], | ||
help="The seed for encoding [default:random]", | ||
) | ||
parser.add_argument( | ||
"--size", | ||
"-z", | ||
default=2, | ||
type=int, | ||
help="The size_seed for encoding [default:2]\nIt determines how large to make the encoded string.\n\tThe encoded message is \"roughly\" 'size_seed' times the length of actual message", | ||
) | ||
parser.add_argument( | ||
"--char_range", | ||
"-r", | ||
type=int, | ||
default="256", | ||
help="The range of unicode characters to be used for encoded the message [default:256]", | ||
) | ||
parser.add_argument( | ||
"--output", | ||
"-o", | ||
type=str, | ||
default="", | ||
help="Specify a text file where the output code will be saved", | ||
) | ||
parser.add_argument( | ||
"--garbage", | ||
"-g", | ||
default=None, | ||
help="Seed for garbage values", | ||
) | ||
parser.add_argument( | ||
"--values-only", | ||
"-vo", | ||
default=False, | ||
action="store_true", | ||
help="Give values only, not the entire code", | ||
) | ||
return parser.parse_args() | ||
|
||
|
||
def _extract_message(args) -> str | int: | ||
if args.file: | ||
try: | ||
with open(args.arg) as f: | ||
message = f.read() | ||
except FileNotFoundError: | ||
print("File does not exist") | ||
return -1 | ||
else: | ||
message = args.arg | ||
return message if message else -1 | ||
|
||
|
||
def _extract_keys(args): | ||
seed, size_seed, char_range = validate(args.seed, args.size, args.char_range) | ||
try: garbage_seed = args.garbage | ||
except: garbage_seed = None | ||
return seed, size_seed, char_range, garbage_seed | ||
|
||
|
||
def run(args): | ||
message = _extract_message(args) | ||
if message == -1: # file does not exist or empty file | ||
print("No message to encode") | ||
return | ||
|
||
# keys = (seed, size_seed, char_range) | ||
*keys, garbage_seed = _extract_keys(args) | ||
encoded_message = encode(message, *keys, garbage_seed) | ||
|
||
output_tuple = (encoded_message, *keys) | ||
output = ( | ||
give_values(*output_tuple) if args.values_only else give_code(*output_tuple) | ||
) | ||
if args.output: | ||
try: | ||
with open(args.output, "w") as f: | ||
f.write(output) | ||
except Exception as err: | ||
print(f"Error occured while writing to file: {err}") | ||
else: | ||
print(f"\n{output}") | ||
|
||
|
||
if __name__ == "__main__": | ||
run(get_input()) |