mirror of
https://github.com/bikini/patchwork
synced 2026-06-27 08:08:41 +00:00
49 lines
1.4 KiB
Python
49 lines
1.4 KiB
Python
from __future__ import annotations
|
|
import hashlib
|
|
import random
|
|
|
|
def keystream(key: bytes, length: int) -> bytes:
|
|
out = bytearray()
|
|
ctr = 0
|
|
while len(out) < length:
|
|
out.extend(hashlib.sha256(key + ctr.to_bytes(8, 'big')).digest())
|
|
ctr += 1
|
|
return bytes(out[:length])
|
|
|
|
def stream_xor(data: bytes, key: bytes) -> bytes:
|
|
ks = keystream(key, len(data))
|
|
return bytes((a ^ b for a, b in zip(data, ks)))
|
|
|
|
def make_perm(key: bytes) -> bytes:
|
|
seed = int.from_bytes(hashlib.sha256(key).digest(), 'big')
|
|
rng = random.Random(seed)
|
|
perm = list(range(256))
|
|
rng.shuffle(perm)
|
|
return bytes(perm)
|
|
|
|
def invert_perm(perm: bytes) -> bytes:
|
|
inv = bytearray(256)
|
|
for i, p in enumerate(perm):
|
|
inv[p] = i
|
|
return bytes(inv)
|
|
|
|
def perm_apply(data: bytes, key: bytes) -> bytes:
|
|
perm = make_perm(key)
|
|
return bytes((perm[b] for b in data))
|
|
|
|
def perm_invert(data: bytes, key: bytes) -> bytes:
|
|
inv = invert_perm(make_perm(key))
|
|
return bytes((inv[b] for b in data))
|
|
|
|
def _rot_left(b: int, n: int) -> int:
|
|
n &= 7
|
|
if not n:
|
|
return b
|
|
return (b << n | b >> 8 - n) & 255
|
|
|
|
def rot_apply(data: bytes, key: bytes) -> bytes:
|
|
return bytes((_rot_left(b, key[i % len(key)]) for i, b in enumerate(data)))
|
|
|
|
def rot_invert(data: bytes, key: bytes) -> bytes:
|
|
return bytes((_rot_left(b, -key[i % len(key)] & 7) for i, b in enumerate(data)))
|