think
This commit is contained in:
1 parent
bfbd9904f9
commit
71446f6f5a
5 files changed
+108
-42
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.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.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)
|
- `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
|
||||||
@@ -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.
|
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__":
|
||||||
|
|||||||
Reference in new issue
Block a user