from __future__ import annotations import marshal import random import zlib from . import crypto from .util import gen_bytes CIPHER_OPS = ('xor', 'perm', 'rot') def pack(code_obj, rng: random.Random, layers: int=3) -> tuple[bytes, list[tuple[str, bytes]]]: data = marshal.dumps(code_obj) data = zlib.compress(data, 9) layer_keys: list[tuple[str, bytes]] = [] for _ in range(layers): op = rng.choice(CIPHER_OPS) key = gen_bytes(rng, rng.randint(20, 40)) if op == 'xor': data = crypto.stream_xor(data, key) elif op == 'perm': data = crypto.perm_apply(data, key) elif op == 'rot': data = crypto.rot_apply(data, key) layer_keys.append((op, key)) return (data, layer_keys)