This commit is contained in:
lda committed 2025-07-09 01:26:26 +07:00
1 parent bfbd9904f9
commit 71446f6f5a
5 files changed
+108 -42

No files matched your search

+3
View File
@@ -168,3 +168,6 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/
# real blocker
*real.txt
+21 -1
View File
@@ -24,11 +24,31 @@ python main.py decrypt <filein> <keyfile>
- `filein`: Input text file (should match the input used in encrypt) - `filein`: Input text file (should match the input used in encrypt)
- `keyfile`: Key file produced during encryption - `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 ### Example
encryption:
```sh ```sh
python main.py encrypt message.txt target.txt --seed 42 > mykey.txt 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 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
+1
View File
@@ -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)]
+83 -41
View File
@@ -2,33 +2,46 @@
asscryption: Proof-of-concept random key-based text transformer. asscryption: Proof-of-concept random key-based text transformer.
USAGE: 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) filein: Input text file (plaintext)
target: Target text file (what you want to transform to) 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) keyfile: Output key file (redirect stdout)
Decrypt: python main.py decrypt <filein> <keyfile> Decrypt: python main.py decrypt <filein> <keyfile> [-b [N]]
filein: Input text file (should match the target used in encrypt)
filein: Input text file (should match the input used in encrypt)
keyfile: Key file produced during encryption keyfile: Key file produced during encryption
-b, --bytes [N]: (Optional) Read key as bytes, with N bytes for the index (must match encryption).
EXAMPLES: EXAMPLES:
python main.py encrypt message.txt target.txt --seed 42 > mykey.txt 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: NOTES:
- This is a proof-of-concept. The "key" is printed to stdout during encryption. - 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 from itertools import repeat
import random import random
import argparse import argparse
from typing import Generator, Tuple import sys
import ast 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. Generate a sequence of random indices from the given range, of specified length.
If a seed is provided, the random sequence is reproducible. 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: if seed is not None:
random.seed(seed) random.seed(seed)
return (random.choice(range) for _ in repeat(None, length)) return (random.choice(range_) for _ in repeat(None, length))
def funky_function( def funky_function(text_in: str, text_out: str, seed=None) -> Iterator[tuple[int, int]]:
text_in, text_out, seed=None
) -> Generator[Tuple[int, int], None, None]:
""" """
For each character in text_out, randomly select a character from text_in (using index_list), 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. 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)): for id_out, id_in in enumerate(index_list(range_text_in, len_text_out, seed)):
val_in = text_in[id_in] val_in = text_in[id_in]
val_out = text_out[id_out] 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 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. 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: for ind, offset in this:
val_in = text_in[ind] 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(): def main():
parser = argparse.ArgumentParser( 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) subparsers = parser.add_subparsers(dest="command", required=True)
@@ -80,38 +109,51 @@ def main():
enc.add_argument("filein") enc.add_argument("filein")
enc.add_argument("target") enc.add_argument("target")
enc.add_argument("--seed", type=int, default=None) 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 = subparsers.add_parser("decrypt")
dec.add_argument("filein") dec.add_argument("filein")
dec.add_argument("keyfile") 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() args = parser.parse_args()
if args.command == "encrypt": match args.command:
# read filein case "encrypt":
with open(args.filein, "r", encoding="utf-8") as fin: with open(args.filein, "r", encoding="utf-8") as fin:
text_in = fin.read() text_in = fin.read()
with open(args.target, "r", encoding="utf-8") as fout:
# read fileout text_out = fout.read()
with open(args.target, "r", encoding="utf-8") as fout: key = funky_function(text_in, text_out, args.seed)
text_out = fout.read() if args.bytes:
sys.stdout.buffer.write(keycrypt(key))
# Build key else:
key = list(funky_function(text_in, text_out, args.seed)) print(list(key))
case "decrypt":
# Print key to stdout with open(args.filein, "r", encoding="utf-8") as fin:
print(key) text_in = fin.read()
elif args.command == "decrypt": if args.bytes:
# read filein, read keyfile, print recovered text with open(args.keyfile, "rb") as kf:
with open(args.filein, "r", encoding="utf-8") as fin: key = parse_bytecrypt(kf.read())
text_in = fin.read() else:
with open(args.keyfile, "r", encoding="utf-8") as kf:
with open(args.keyfile, "r", encoding="utf-8") as kf: key = ast.literal_eval(kf.read())
key = ast.literal_eval(kf.read()) result = "".join(rebuild(text_in, iter(key)))
print(result)
# Rebuild original text
result = "".join(rebuild(text_in, key))
print(result)
if __name__ == "__main__": if __name__ == "__main__":
BIN
View File
Binary file not shown.