think
This commit is contained in:
1 parent
bfbd9904f9
commit
71446f6f5a
5 files changed
+99
-33
No files matched your search
@@ -168,3 +168,6 @@ cython_debug/
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
|
||||
# real blocker
|
||||
*real.txt
|
||||
@@ -24,11 +24,31 @@ python main.py decrypt <filein> <keyfile>
|
||||
- `filein`: Input text file (should match the input used in encrypt)
|
||||
- `keyfile`: Key file produced during encryption
|
||||
|
||||
### Output as bytes
|
||||
|
||||
For both encryption and decryption, use `-b` or `--bytes` to output or read the key as a compact bytearray of N bytes for the index (usize) plus 1 byte (u8) for the offset.
|
||||
|
||||
- Use `-b` or `--bytes` alone for the default size (8 bytes for index).
|
||||
- Optionally specify a size after `-b` (e.g. `-b 4` or `--bytes=4`) to customize the index size in bytes.
|
||||
- **Important:** When decrypting, you must specify the same byte size as was used for encryption.
|
||||
|
||||
### Example
|
||||
|
||||
encryption:
|
||||
|
||||
```sh
|
||||
python main.py encrypt message.txt target.txt --seed 42 > mykey.txt
|
||||
python main.py encrypt filein.txt target.txt -b > keyfile.bin # 8-byte index (default)
|
||||
python main.py encrypt filein.txt target.txt -b 4 > keyfile.bin
|
||||
python main.py encrypt filein.txt target.txt --seed 123 -b=4 > keyfile.bin
|
||||
```
|
||||
|
||||
decryption:
|
||||
|
||||
```sh
|
||||
python main.py decrypt message.txt mykey.txt > reconstructed_target.txt
|
||||
python main.py decrypt filein.txt keyfile.bin -b 4 > out.txt # must match key size
|
||||
python main.py decrypt filein.txt keyfile.bin --bytes=4 > out.txt
|
||||
```
|
||||
|
||||
---
|
||||
@@ -37,4 +57,4 @@ python main.py decrypt message.txt mykey.txt > reconstructed_target.txt
|
||||
|
||||
---
|
||||
|
||||
Version 1
|
||||
Version 1.1
|
||||
@@ -0,0 +1 @@
|
||||
[(11, 3), (69, 181), (92, 184), (80, 198), (71, 52), (12, 0), (65, 9), (121, 186), (43, 1), (64, 0), (6, 234), (15, 158), (114, 239), (135, 20), (50, 82), (114, 248), (84, 173), (135, 204), (116, 240), (12, 183), (14, 48), (85, 47), (117, 238), (141, 231), (68, 187), (94, 186), (116, 252), (101, 179), (96, 187), (84, 181), (88, 242), (13, 251), (93, 13), (116, 193), (133, 186), (32, 204), (5, 39), (51, 188), (73, 174), (63, 207), (105, 9), (83, 5), (132, 5), (125, 237), (142, 9), (142, 15), (88, 186), (32, 243), (102, 20), (105, 10), (14, 69), (34, 210), (50, 84), (18, 69), (22, 10), (35, 19), (101, 194), (57, 80), (34, 4), (1, 252), (84, 246), (129, 2), (49, 205), (15, 247), (71, 58), (117, 252), (65, 13), (103, 83), (116, 253), (34, 12), (12, 212), (54, 7), (0, 12), (120, 247), (112, 190), (140, 207), (34, 186), (141, 179), (116, 0), (91, 0), (127, 7), (34, 8), (132, 4), (139, 198), (28, 187), (126, 206), (87, 238), (98, 83), (8, 11), (61, 186), (87, 249), (19, 0), (126, 11), (96, 251), (33, 65), (138, 14), (99, 240), (18, 79), (49, 255), (141, 194), (130, 4), (107, 252), (98, 76), (118, 6), (45, 71), (134, 71), (7, 241), (82, 82), (53, 161), (95, 234), (54, 4), (67, 5), (137, 180), (15, 193), (140, 9), (102, 1), (138, 0), (32, 206), (95, 0), (76, 186), (26, 197), (137, 2), (67, 7), (24, 13), (12, 7), (117, 13), (88, 242), (82, 83), (79, 253), (107, 254), (99, 3), (110, 69), (3, 193), (91, 254), (24, 79), (39, 1), (13, 1)]
|
||||
@@ -2,33 +2,46 @@
|
||||
asscryption: Proof-of-concept random key-based text transformer.
|
||||
|
||||
USAGE:
|
||||
Encrypt: python main.py encrypt <filein> <target> [--seed SEED] > keyfile
|
||||
|
||||
Encrypt: python main.py encrypt <filein> <target> [--seed SEED] [-b [N]] > keyfile
|
||||
|
||||
filein: Input text file (plaintext)
|
||||
target: Target text file (what you want to transform to)
|
||||
--seed: (Optional) Random seed for reproducibility
|
||||
--seed: (Optional) Random seed for reproducibility (use the same seed to get the same key/output)
|
||||
-b, --bytes [N]: (Optional) Output key as bytes, with N bytes for the index (default 8).
|
||||
Use -b or --bytes alone for 8 bytes, or specify a size (e.g. -b 4).
|
||||
keyfile: Output key file (redirect stdout)
|
||||
|
||||
Decrypt: python main.py decrypt <filein> <keyfile>
|
||||
filein: Input text file (should match the target used in encrypt)
|
||||
Decrypt: python main.py decrypt <filein> <keyfile> [-b [N]]
|
||||
|
||||
filein: Input text file (should match the input used in encrypt)
|
||||
keyfile: Key file produced during encryption
|
||||
-b, --bytes [N]: (Optional) Read key as bytes, with N bytes for the index (must match encryption).
|
||||
|
||||
EXAMPLES:
|
||||
|
||||
python main.py encrypt message.txt target.txt --seed 42 > mykey.txt
|
||||
python main.py decrypt target.txt mykey.txt
|
||||
python main.py encrypt filein.txt target.txt -b > keyfile.bin # 8-byte index (default)
|
||||
python main.py encrypt filein.txt target.txt -b 4 > keyfile.bin # 4-byte index
|
||||
python main.py decrypt filein.txt keyfile.bin -b 4 > out.txt # must match key size
|
||||
|
||||
NOTES:
|
||||
|
||||
- This is a proof-of-concept. The "key" is printed to stdout during encryption.
|
||||
- The target file must exist and be the same length as the input.
|
||||
- The target file must exist. No length checks are required.
|
||||
- When using -b/--bytes, the key is stored as a compact bytearray: N bytes for the index (usize) and 1 byte (u8) for the offset.
|
||||
- When decrypting, you must specify the same byte size as was used for encryption.
|
||||
"""
|
||||
|
||||
from collections.abc import Iterator
|
||||
from itertools import repeat
|
||||
import random
|
||||
import argparse
|
||||
from typing import Generator, Tuple
|
||||
import sys
|
||||
import ast
|
||||
|
||||
|
||||
def index_list(range: range, length: int, seed=None) -> Generator[int, None, None]:
|
||||
def index_list(range_: range, length: int, seed=None) -> Iterator[int]:
|
||||
"""
|
||||
Generate a sequence of random indices from the given range, of specified length.
|
||||
If a seed is provided, the random sequence is reproducible.
|
||||
@@ -37,12 +50,10 @@ def index_list(range: range, length: int, seed=None) -> Generator[int, None, Non
|
||||
"""
|
||||
if seed is not None:
|
||||
random.seed(seed)
|
||||
return (random.choice(range) for _ in repeat(None, length))
|
||||
return (random.choice(range_) for _ in repeat(None, length))
|
||||
|
||||
|
||||
def funky_function(
|
||||
text_in, text_out, seed=None
|
||||
) -> Generator[Tuple[int, int], None, None]:
|
||||
def funky_function(text_in: str, text_out: str, seed=None) -> Iterator[tuple[int, int]]:
|
||||
"""
|
||||
For each character in text_out, randomly select a character from text_in (using index_list),
|
||||
and yield a tuple (index_in, offset) where offset is the difference in ordinal values.
|
||||
@@ -55,10 +66,10 @@ def funky_function(
|
||||
for id_out, id_in in enumerate(index_list(range_text_in, len_text_out, seed)):
|
||||
val_in = text_in[id_in]
|
||||
val_out = text_out[id_out]
|
||||
yield id_in, ord(val_out) - ord(val_in)
|
||||
yield id_in, (ord(val_out) - ord(val_in)) % 256
|
||||
|
||||
|
||||
def rebuild(text_in, this: Generator[Tuple[int, int], None, None]):
|
||||
def rebuild(text_in, this: Iterator[tuple[int, int]]):
|
||||
"""
|
||||
Rebuilds the output text by applying the offset to the character at index_in in text_in
|
||||
for each (index_in, offset) in the key.
|
||||
@@ -67,12 +78,30 @@ def rebuild(text_in, this: Generator[Tuple[int, int], None, None]):
|
||||
"""
|
||||
for ind, offset in this:
|
||||
val_in = text_in[ind]
|
||||
yield chr(ord(val_in) + offset)
|
||||
yield chr((ord(val_in) + offset) % 256)
|
||||
|
||||
|
||||
def keycrypt(genkey: Iterator[tuple[int, int]], usize_length=8) -> bytearray:
|
||||
i = bytearray()
|
||||
for index, dif in genkey:
|
||||
i.extend(
|
||||
index.to_bytes(usize_length, sys.byteorder) + dif.to_bytes(1)
|
||||
) # little endian? in 2025?
|
||||
return i
|
||||
|
||||
|
||||
def parse_bytecrypt(data: bytes, usize_length=8) -> Iterator[tuple[int, int]]:
|
||||
for i in range(0, len(data), usize_length + 1):
|
||||
index = int.from_bytes(data[i : i + usize_length], sys.byteorder)
|
||||
offset = data[i + usize_length]
|
||||
yield (index, offset)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="asscryption: Random key-based text transformer (PoC). See top of file for usage."
|
||||
# description="asscryption: Random key-based text transformer (PoC). See top of file for usage.",
|
||||
usage=__doc__,
|
||||
epilog="by lda (and copilot)",
|
||||
)
|
||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
@@ -80,37 +109,50 @@ def main():
|
||||
enc.add_argument("filein")
|
||||
enc.add_argument("target")
|
||||
enc.add_argument("--seed", type=int, default=None)
|
||||
enc.add_argument(
|
||||
"-b",
|
||||
"--bytes",
|
||||
nargs="?",
|
||||
const=8,
|
||||
type=int,
|
||||
help="Output key as bytes to stdout (optionally specify index size in bytes, default 8)",
|
||||
)
|
||||
|
||||
dec = subparsers.add_parser("decrypt")
|
||||
dec.add_argument("filein")
|
||||
dec.add_argument("keyfile")
|
||||
dec.add_argument(
|
||||
"-b",
|
||||
"--bytes",
|
||||
nargs="?",
|
||||
const=8,
|
||||
type=int,
|
||||
help="Read key as bytes (optionally specify index size in bytes, default 8)",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.command == "encrypt":
|
||||
# read filein
|
||||
match args.command:
|
||||
case "encrypt":
|
||||
with open(args.filein, "r", encoding="utf-8") as fin:
|
||||
text_in = fin.read()
|
||||
|
||||
# read fileout
|
||||
with open(args.target, "r", encoding="utf-8") as fout:
|
||||
text_out = fout.read()
|
||||
|
||||
# Build key
|
||||
key = list(funky_function(text_in, text_out, args.seed))
|
||||
|
||||
# Print key to stdout
|
||||
print(key)
|
||||
elif args.command == "decrypt":
|
||||
# read filein, read keyfile, print recovered text
|
||||
key = funky_function(text_in, text_out, args.seed)
|
||||
if args.bytes:
|
||||
sys.stdout.buffer.write(keycrypt(key))
|
||||
else:
|
||||
print(list(key))
|
||||
case "decrypt":
|
||||
with open(args.filein, "r", encoding="utf-8") as fin:
|
||||
text_in = fin.read()
|
||||
|
||||
if args.bytes:
|
||||
with open(args.keyfile, "rb") as kf:
|
||||
key = parse_bytecrypt(kf.read())
|
||||
else:
|
||||
with open(args.keyfile, "r", encoding="utf-8") as kf:
|
||||
key = ast.literal_eval(kf.read())
|
||||
|
||||
# Rebuild original text
|
||||
result = "".join(rebuild(text_in, key))
|
||||
result = "".join(rebuild(text_in, iter(key)))
|
||||
print(result)
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user