Updated scripts and added new
This commit is contained in:
108
rc4.py
Normal file
108
rc4.py
Normal file
@ -0,0 +1,108 @@
|
||||
import logging
|
||||
from argparse import ArgumentParser
|
||||
from pathlib import Path
|
||||
|
||||
_VERBOSE_SBOX = False
|
||||
_VERBOSE_PRGA = False
|
||||
_STEPWISE_PRGA = False
|
||||
|
||||
|
||||
def sbox(key: list[int]) -> list[int]:
|
||||
"""
|
||||
Creates and permutates the substitution box given a key.
|
||||
"""
|
||||
# create sbox
|
||||
S = [i for i in range(256)]
|
||||
|
||||
# permutate sbox
|
||||
j = 0
|
||||
for i in range(256):
|
||||
j = (j + S[i] + key[i % len(key)]) % 256
|
||||
if _VERBOSE_SBOX:
|
||||
print(f"Swapping S[{i=:3d}] = {S[i]:3d} and S[{j=:3d}] = {S[j]:3d}.")
|
||||
S[i], S[j] = S[j], S[i] # swap
|
||||
|
||||
return S
|
||||
|
||||
|
||||
def prga(text: list[int], S: list[int]) -> list[int]:
|
||||
"""
|
||||
Encrypts/Decrypts text given a substitution box.
|
||||
"""
|
||||
text = list(text)
|
||||
i = 0
|
||||
j = 0
|
||||
for x in range(len(text)):
|
||||
i = (i + 1) % 256
|
||||
j = (j + S[i]) % 256
|
||||
|
||||
if _VERBOSE_PRGA:
|
||||
print(f"Swapping S[{i=:3d}] = {S[i]:3d} and S[{j=:3d}] = {S[j]:3d}.")
|
||||
|
||||
if _STEPWISE_PRGA:
|
||||
try:
|
||||
input("Press ENTER to continue ...") # Step through
|
||||
except KeyboardInterrupt:
|
||||
print("KeyboardInterrupt.")
|
||||
exit(0)
|
||||
|
||||
S[i], S[j] = S[j], S[i] # swap
|
||||
K = S[(S[i] + S[j]) % 256]
|
||||
text[x] ^= K
|
||||
return text
|
||||
|
||||
|
||||
def convert(text: bytes | list[int]) -> bytes | list[int]:
|
||||
"""
|
||||
Converts text from bytes -> list[int] and back.
|
||||
"""
|
||||
if isinstance(text, bytes):
|
||||
return [int(c) for c in text]
|
||||
elif isinstance(text, list):
|
||||
return bytes(text)
|
||||
else:
|
||||
raise ValueError(f"Unsupported input type '{type(text)}'")
|
||||
|
||||
|
||||
def rc4(in_file: str | Path, out_file: str | Path, key_file: str | Path):
|
||||
"""
|
||||
Execute the RC4 encryption/decryption algorithm on the input file,
|
||||
creating the output file using the contents from the key file.
|
||||
"""
|
||||
|
||||
with open(key_file, "rb") as key_file:
|
||||
S = sbox(convert(key_file.read()))
|
||||
|
||||
with open("sbox_solution", "wb") as fd:
|
||||
fd.write(convert(S))
|
||||
|
||||
# read input
|
||||
with open(in_file, "rb") as data_in_file:
|
||||
data_in = data_in_file.read()
|
||||
|
||||
data_in = convert(data_in) # bytes -> list[int]
|
||||
data_out = prga(data_in, S)
|
||||
data_out = convert(data_out) # list[int] -> bytes
|
||||
|
||||
# write output
|
||||
with open(out_file, "wb") as data_out_file:
|
||||
data_out_file.write(data_out)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = ArgumentParser(
|
||||
description="Encrypts plaintext using the RC4 encryption algorithm, or decrypts RC4 ciphertext (based on input)"
|
||||
)
|
||||
parser.add_argument("input", type=str, help="Input file")
|
||||
parser.add_argument("key", type=str, help="Key file")
|
||||
parser.add_argument("output", type=str, help="Output file")
|
||||
parser.add_argument("--verbose-sbox", const=True, default=False, action="store_const", help="Show S-Box swaps")
|
||||
parser.add_argument("--verbose-prga", const=True, default=False, action="store_const", help="Show PRGA swaps")
|
||||
parser.add_argument("--step-prga", const=True, default=False, action="store_const", help="Step-by-step PRGA swaps")
|
||||
args = parser.parse_args()
|
||||
|
||||
_VERBOSE_SBOX = args.verbose_sbox
|
||||
_VERBOSE_PRGA = args.verbose_prga
|
||||
_STEPWISE_PRGA = args.step_prga
|
||||
|
||||
rc4(args.input, args.output, args.key)
|
||||
Reference in New Issue
Block a user